83using CLHEP::perMillion;
99 for (
const auto& edge : facet.edge) {
100 ostr <<
" " << edge.v <<
"/" << edge.f;
107 ostr <<
"Nvertices=" << ph.
nvert <<
", Nfacets=" << ph.
nface << std::endl;
109 for (i=1; i<=ph.
nvert; i++) {
110 ostr <<
"xyz(" << i <<
")="
111 << ph.
pV[i].
x() <<
' ' << ph.
pV[i].
y() <<
' ' << ph.
pV[i].
z()
114 for (i=1; i<=ph.
nface; i++) {
115 ostr <<
"face(" << i <<
")=" << ph.
pF[i] << std::endl;
128: nvert(0), nface(0), pV(nullptr), pF(nullptr)
140: nvert(0), nface(0), pV(nullptr), pF(nullptr)
154: nvert(0), nface(0), pV(nullptr), pF(nullptr)
225 for (i=0; i<4; i++) {
226 if (iNode == std::abs(pF[iFace].edge[i].v))
break;
230 <<
"HepPolyhedron::FindNeighbour: face " << iFace
231 <<
" has no node " << iNode
237 if (pF[iFace].edge[i].v == 0) i = 2;
239 return (pF[iFace].edge[i].v > 0) ? 0 : pF[iFace].edge[i].f;
253 G4int k = iFace, iOrder = 1;
256 k = FindNeighbour(k, iNode, iOrder);
257 if (k == iFace)
break;
259 normal += GetUnitNormal(k);
261 if (iOrder < 0)
break;
266 return normal.
unit();
292 if (index < 1 || index >
nvert)
295 <<
"HepPolyhedron::SetVertex: vertex index = " << index
296 <<
" is out of range\n"
297 <<
" N. of vertices = " <<
nvert <<
"\n"
298 <<
" N. of facets = " <<
nface << std::endl;
315 if (index < 1 || index >
nface)
318 <<
"HepPolyhedron::SetFacet: facet index = " << index
319 <<
" is out of range\n"
320 <<
" N. of vertices = " <<
nvert <<
"\n"
321 <<
" N. of facets = " <<
nface << std::endl;
324 if (iv1 < 1 || iv1 >
nvert ||
325 iv2 < 1 || iv2 >
nvert ||
326 iv3 < 1 || iv3 >
nvert ||
327 iv4 < 0 || iv4 >
nvert)
330 <<
"HepPolyhedron::SetFacet: incorrectly specified facet"
331 <<
" (" << iv1 <<
", " << iv2 <<
", " << iv3 <<
", " << iv4 <<
")\n"
332 <<
" N. of vertices = " <<
nvert <<
"\n"
333 <<
" N. of facets = " <<
nface << std::endl;
336 pF[index] =
G4Facet(iv1, 0, iv2, 0, iv3, 0, iv4, 0);
349 const G4int nMin = 3;
352 <<
"HepPolyhedron::SetNumberOfRotationSteps: attempt to set the\n"
353 <<
"number of steps per circle < " << nMin <<
"; forced to " << nMin
390 if (Nvert > 0 && Nface > 0) {
410 enum {DUMMY, BOTTOM, LEFT, BACK, RIGHT, FRONT, TOP};
412 pF[1] =
G4Facet(1,LEFT, 4,BACK, 3,RIGHT, 2,FRONT);
413 pF[2] =
G4Facet(5,TOP, 8,BACK, 4,BOTTOM, 1,FRONT);
414 pF[3] =
G4Facet(8,TOP, 7,RIGHT, 3,BOTTOM, 4,LEFT);
415 pF[4] =
G4Facet(7,TOP, 6,FRONT, 2,BOTTOM, 3,BACK);
416 pF[5] =
G4Facet(6,TOP, 5,LEFT, 1,BOTTOM, 2,RIGHT);
417 pF[6] =
G4Facet(5,FRONT, 6,RIGHT, 7,BACK, 8,LEFT);
442 if (r1 == 0. && r2 == 0.)
return;
447 G4int ii1 = ifWholeCircle ? i1 : i1+nds;
448 G4int ii2 = ifWholeCircle ? i2 : i2+nds;
449 G4int vv = ifWholeCircle ? vEdge : 1;
453 pF[kface++] =
G4Facet(i1,0, v2*i2,0, (i2+1),0);
454 }
else if (r2 == 0.) {
455 pF[kface++] =
G4Facet(i1,0, i2,0, v1*(i1+1),0);
457 pF[kface++] =
G4Facet(i1,0, v2*i2,0, (i2+1),0, v1*(i1+1),0);
461 pF[kface++] =
G4Facet(vv*i1,0, v2*i2,0, vEdge*(i2+1),0);
462 for (i2++,i=1; i<nds-1; i2++,i++) {
463 pF[kface++] =
G4Facet(vEdge*i1,0, v2*i2,0, vEdge*(i2+1),0);
465 pF[kface++] =
G4Facet(vEdge*i1,0, v2*i2,0, vv*ii2,0);
466 }
else if (r2 == 0.) {
467 pF[kface++] =
G4Facet(vv*i1,0, vEdge*i2,0, v1*(i1+1),0);
468 for (i1++,i=1; i<nds-1; i1++,i++) {
469 pF[kface++] =
G4Facet(vEdge*i1,0, vEdge*i2,0, v1*(i1+1),0);
471 pF[kface++] =
G4Facet(vEdge*i1,0, vv*i2,0, v1*ii1,0);
473 pF[kface++] =
G4Facet(vv*i1,0, v2*i2,0, vEdge*(i2+1),0,v1*(i1+1),0);
474 for (i1++,i2++,i=1; i<nds-1; i1++,i2++,i++) {
475 pF[kface++] =
G4Facet(vEdge*i1,0, v2*i2,0, vEdge*(i2+1),0,v1*(i1+1),0);
477 pF[kface++] =
G4Facet(vEdge*i1,0, v2*i2,0, vv*ii2,0, v1*ii1,0);
502 G4int k1, k2, k3, k4;
504 if (std::abs(dphi-pi) < perMillion) {
505 for (
G4int i=0; i<4; i++) {
508 if (r[k1] == 0. && r[k2] == 0.) vv[i] = -1;
512 if (ii[1] == ii[2]) {
516 pF[kface++] =
G4Facet(vv[0]*k1,0, vv[2]*k2,0, vv[3]*k3,0);
517 if (r[ii[0]] != 0.) k1 += nds;
518 if (r[ii[2]] != 0.) k2 += nds;
519 if (r[ii[3]] != 0.) k3 += nds;
520 pF[kface++] =
G4Facet(vv[2]*k3,0, vv[0]*k2,0, vv[3]*k1,0);
521 }
else if (kk[ii[0]] == kk[ii[1]]) {
525 pF[kface++] =
G4Facet(vv[1]*k1,0, vv[2]*k2,0, vv[3]*k3,0);
526 if (r[ii[0]] != 0.) k1 += nds;
527 if (r[ii[2]] != 0.) k2 += nds;
528 if (r[ii[3]] != 0.) k3 += nds;
529 pF[kface++] =
G4Facet(vv[2]*k3,0, vv[1]*k2,0, vv[3]*k1,0);
530 }
else if (kk[ii[2]] == kk[ii[3]]) {
534 pF[kface++] =
G4Facet(vv[0]*k1,0, vv[1]*k2,0, vv[3]*k3,0);
535 if (r[ii[0]] != 0.) k1 += nds;
536 if (r[ii[1]] != 0.) k2 += nds;
537 if (r[ii[2]] != 0.) k3 += nds;
538 pF[kface++] =
G4Facet(vv[1]*k3,0, vv[0]*k2,0, vv[3]*k1,0);
544 pF[kface++] =
G4Facet(vv[0]*k1,0, vv[1]*k2,0, vv[2]*k3,0, vv[3]*k4,0);
545 if (r[ii[0]] != 0.) k1 += nds;
546 if (r[ii[1]] != 0.) k2 += nds;
547 if (r[ii[2]] != 0.) k3 += nds;
548 if (r[ii[3]] != 0.) k4 += nds;
549 pF[kface++] =
G4Facet(vv[2]*k4,0, vv[1]*k3,0, vv[0]*k2,0, vv[3]*k1,0);
579 static const G4double wholeCircle = twopi;
583 G4bool ifWholeCircle = std::abs(dphi-wholeCircle) < perMillion;
584 G4double delPhi = ifWholeCircle ? wholeCircle : dphi;
587 if (nSphi == 0) nSphi = 1;
588 G4int nVphi = ifWholeCircle ? nSphi : nSphi + 1;
589 G4bool ifClosed = np1 <= 0;
593 G4int absNp1 = std::abs(np1);
594 G4int absNp2 = std::abs(np2);
596 G4int i1end = absNp1-1;
597 G4int i2beg = absNp1;
598 G4int i2end = absNp1+absNp2-1;
601 for(i=i1beg; i<=i2end; i++) {
608 for (i=i1beg; i<=i1end; i++) {
609 Nverts += (r[i] == 0.) ? 1 : nVphi;
617 if (r[i2beg] != r[i1beg] || z[i2beg] != z[i1beg]) {
618 Nverts += (r[i2beg] == 0.) ? 1 : nVphi;
622 for(i=i2beg+1; i<i2end; i++) {
623 Nverts += (r[i] == 0.) ? 1 : nVphi;
626 if (r[i2end] != r[i1end] || z[i2end] != z[i1end]) {
627 if (absNp2 > 1) Nverts += (r[i2end] == 0.) ? 1 : nVphi;
635 G4int Nfaces = ifClosed ? absNp1*nSphi : (absNp1-1)*nSphi;
640 for(i=i2beg; i<i2end; i++) {
641 if (r[i] > 0. || r[i+1] > 0.) Nfaces += nSphi;
645 if (r[i2end] > 0. || r[i2beg] > 0.) Nfaces += nSphi;
652 if (ifSide1 && (r[i1beg] > 0. || r[i2beg] > 0.)) Nfaces += nSphi;
653 if (ifSide2 && (r[i1end] > 0. || r[i2end] > 0.)) Nfaces += nSphi;
658 if (!ifWholeCircle) {
659 Nfaces += ifClosed ? 2*absNp1 : 2*(absNp1-1);
665 if (
pV ==
nullptr ||
pF ==
nullptr)
return;
670 kk =
new G4int[absNp1+absNp2];
675 for(i=i1beg; i<=i1end; i++) {
678 {
pV[k++] =
G4Point3D(0, 0, z[i]); }
else { k += nVphi; }
687 {
pV[k++] =
G4Point3D(0, 0, z[i]); }
else { k += nVphi; }
694 for(i=i2beg+1; i<i2end; i++) {
697 {
pV[k++] =
G4Point3D(0, 0, z[i]); }
else { k += nVphi; }
716 for(j=0; j<nVphi; j++) {
717 cosPhi = std::cos(phi+j*delPhi/nSphi);
718 sinPhi = std::sin(phi+j*delPhi/nSphi);
719 for(i=i1beg; i<=i2end; i++) {
721 pV[kk[i]+j] =
G4Point3D(r[i]*cosPhi,r[i]*sinPhi,z[i]);
732 v2 = ifClosed ? nodeVis : 1;
733 for(i=i1beg; i<i1end; i++) {
735 if (!ifClosed && i == i1end-1) {
738 v2 = (r[i] == r[i+1] && r[i+1] == r[i+2]) ? -1 : nodeVis;
740 RotateEdge(kk[i], kk[i+1], r[i], r[i+1], v1, v2,
741 edgeVis, ifWholeCircle, nSphi, k);
744 RotateEdge(kk[i1end], kk[i1beg], r[i1end],r[i1beg], nodeVis, nodeVis,
745 edgeVis, ifWholeCircle, nSphi, k);
751 v2 = ifClosed ? nodeVis : 1;
752 for(i=i2beg; i<i2end; i++) {
754 if (!ifClosed && i==i2end-1) {
757 v2 = (r[i] == r[i+1] && r[i+1] == r[i+2]) ? -1 : nodeVis;
759 RotateEdge(kk[i+1], kk[i], r[i+1], r[i], v2, v1,
760 edgeVis, ifWholeCircle, nSphi, k);
763 RotateEdge(kk[i2beg], kk[i2end], r[i2beg], r[i2end], nodeVis, nodeVis,
764 edgeVis, ifWholeCircle, nSphi, k);
772 RotateEdge(kk[i2beg], kk[i1beg], r[i2beg], r[i1beg], 1, 1,
773 -1, ifWholeCircle, nSphi, k);
776 RotateEdge(kk[i1end], kk[i2end], r[i1end], r[i2end], 1, 1,
777 -1, ifWholeCircle, nSphi, k);
783 if (!ifWholeCircle) {
788 for (i=i1beg; i<=i1end; i++) {
790 ii[3] = (i == i1end) ? i1beg : i+1;
791 ii[1] = (absNp2 == 1) ? i2beg : ii[0]+absNp1;
792 ii[2] = (absNp2 == 1) ? i2beg : ii[3]+absNp1;
800 for (i=i1beg; i<i1end; i++) {
803 ii[1] = (absNp2 == 1) ? i2beg : ii[0]+absNp1;
804 ii[2] = (absNp2 == 1) ? i2beg : ii[3]+absNp1;
805 vv[0] = (i == i1beg) ? 1 : -1;
807 vv[2] = (i == i1end-1) ? 1 : -1;
820 <<
"HepPolyhedron::RotateAroundZ: number of generated faces ("
821 << k-1 <<
") is not equal to the number of allocated faces ("
831 const std::vector<G4TwoVector> &rz,
854 G4bool ifWholeCircle = std::abs(dphi - twopi) < perMillion;
855 G4double delPhi = (ifWholeCircle) ? twopi : dphi;
858 if (nSphi == 0) nSphi = 1;
859 G4int nVphi = (ifWholeCircle) ? nSphi : nSphi + 1;
865 for (
G4int i = 0; i < Nrz; ++i)
867 G4int k = (i == 0) ? Nrz - 1 : i - 1;
868 area += rz[k].x()*rz[i].y() - rz[i].x()*rz[k].y();
875 for (
G4int i = 0; i < Nrz; ++i)
885 for(
G4int i = 0; i < Nrz; ++i) Nverts += (r[i] == 0.) ? 1 : nVphi;
888 for (
G4int i = 0; i < Nrz; ++i)
890 G4int k = (i == 0) ? Nrz - 1 : i - 1;
891 Nedges -=
static_cast<int>(r[k] == 0 && r[i] == 0);
894 G4int Nfaces = Nedges*nSphi;
895 if (!ifWholeCircle) Nfaces += 2*(Nrz - 2);
900 if (
pV ==
nullptr ||
pF ==
nullptr)
909 auto kk =
new G4int[Nrz];
913 for(
G4int i = 0; i < Nrz; ++i)
916 if (r[i] == 0.)
pV[kfree++] =
G4Point3D(0, 0, z[i]);
917 if (r[i] != 0.) kfree += nVphi;
921 for(
G4int j = 0; j < nVphi; ++j)
923 G4double cosPhi = std::cos(phi + j*delPhi/nSphi);
924 G4double sinPhi = std::sin(phi + j*delPhi/nSphi);
925 for(
G4int i = 0; i < Nrz; ++i)
928 pV[kk[i] + j] =
G4Point3D(r[i]*cosPhi, r[i]*sinPhi, z[i]);
935 for(
G4int i = 0; i < Nrz; ++i)
937 G4int i1 = (i < Nrz - 1) ? i + 1 : 0;
939 if (area < 0.) std::swap(i1, i2);
940 RotateEdge(kk[i1], kk[i2], r[i1], r[i2], nodeVis, nodeVis,
941 edgeVis, ifWholeCircle, nSphi, kfree);
948 std::vector<G4int> triangles;
953 for (
G4int i = 0; i < ntria; ++i)
955 G4int i1 = triangles[0 + i*3];
956 G4int i2 = triangles[1 + i*3];
957 G4int i3 = triangles[2 + i*3];
958 if (area < 0.) std::swap(i1, i3);
959 G4int v1 = (std::abs(i2-i1) == 1 || std::abs(i2-i1) == Nrz-1) ? 1 : -1;
960 G4int v2 = (std::abs(i3-i2) == 1 || std::abs(i3-i2) == Nrz-1) ? 1 : -1;
961 G4int v3 = (std::abs(i1-i3) == 1 || std::abs(i1-i3) == Nrz-1) ? 1 : -1;
962 ii[0] = i1; ii[1] = i2; ii[2] = i2; ii[3] = i3;
963 vv[0] = v1; vv[1] = -1; vv[2] = v2; vv[3] = v3;
974 if (kfree - 1 !=
nface)
977 <<
"HepPolyhedron::RotateContourAroundZ: number of generated faces ("
978 << kfree-1 <<
") is not equal to the number of allocated faces ("
986 std::vector<G4int> &result)
1005 if (n < 3)
return false;
1010 for(
G4int i = 0; i < n; ++i)
1012 G4int k = (i == 0) ? n - 1 : i - 1;
1013 area += polygon[k].x()*polygon[i].y() - polygon[i].x()*polygon[k].y();
1019 auto V =
new G4int[n];
1021 for (
G4int i = 0; i < n; ++i) V[i] = i;
1023 for (
G4int i = 0; i < n; ++i) V[i] = (n - 1) - i;
1029 for(
G4int b = nv - 1; nv > 2; )
1035 if (area < 0.) std::reverse(result.begin(),result.end());
1040 G4int a = (b < nv) ? b : 0;
1041 b = (a+1 < nv) ? a+1 : 0;
1042 G4int c = (b+1 < nv) ? b+1 : 0;
1047 result.push_back(V[a]);
1048 result.push_back(V[b]);
1049 result.push_back(V[c]);
1053 for(
G4int i = b; i < nv; ++i) V[i] = V[i+1];
1059 if (area < 0.) std::reverse(result.begin(),result.end());
1079 G4double Ax = contour[V[a]].x(), Ay = contour[V[a]].y();
1080 G4double Bx = contour[V[b]].x(), By = contour[V[b]].y();
1081 G4double Cx = contour[V[c]].x(), Cy = contour[V[c]].y();
1082 if ((Bx-Ax)*(Cy-Ay) - (By-Ay)*(Cx-Ax) <
kCarTolerance)
return false;
1085 G4double xmin = std::min(std::min(Ax,Bx),Cx);
1086 G4double xmax = std::max(std::max(Ax,Bx),Cx);
1087 G4double ymin = std::min(std::min(Ay,By),Cy);
1088 G4double ymax = std::max(std::max(Ay,By),Cy);
1090 for (
G4int i=0; i<n; ++i)
1092 if((i == a) || (i == b) || (i == c))
continue;
1094 if (Px < xmin || Px > xmax)
continue;
1096 if (Py < ymin || Py > ymax)
continue;
1098 if ((Bx-Ax)*(Cy-Ay) - (By-Ay)*(Cx-Ax) > 0.)
1100 if ((Ax-Cx)*(Py-Cy) - (Ay-Cy)*(Px-Cx) < 0.)
continue;
1101 if ((Bx-Ax)*(Py-Ay) - (By-Ay)*(Px-Ax) < 0.)
continue;
1102 if ((Cx-Bx)*(Py-By) - (Cy-By)*(Px-Bx) < 0.)
continue;
1106 if ((Ax-Cx)*(Py-Cy) - (Ay-Cy)*(Px-Cx) > 0.)
continue;
1107 if ((Bx-Ax)*(Py-Ay) - (By-Ay)*(Px-Ax) > 0.)
continue;
1108 if ((Cx-Bx)*(Py-By) - (Cy-By)*(Px-Bx) > 0.)
continue;
1125 if (
nface <= 0)
return;
1127 struct edgeListMember {
1128 edgeListMember *next;
1132 } *edgeList, *freeList, **headList;
1137 edgeList =
new edgeListMember[2*
nface];
1138 headList =
new edgeListMember*[
nvert];
1141 for (i=0; i<
nvert; i++) {
1142 headList[i] =
nullptr;
1144 freeList = edgeList;
1145 for (i=0; i<2*
nface-1; i++) {
1146 edgeList[i].next = &edgeList[i+1];
1148 edgeList[2*
nface-1].next =
nullptr;
1152 G4int iface, iedge, nedge, i1, i2, k1, k2;
1153 edgeListMember *prev, *cur;
1155 for(iface=1; iface<=
nface; iface++) {
1156 nedge = (
pF[iface].edge[3].v == 0) ? 3 : 4;
1157 for (iedge=0; iedge<nedge; iedge++) {
1159 i2 = (iedge < nedge-1) ? iedge+1 : 0;
1160 i1 = std::abs(
pF[iface].edge[i1].v);
1161 i2 = std::abs(
pF[iface].edge[i2].v);
1162 k1 = (i1 < i2) ? i1 : i2;
1163 k2 = (i1 > i2) ? i1 : i2;
1167 if (cur ==
nullptr) {
1168 headList[k1] = freeList;
1169 if (freeList ==
nullptr) {
1171 <<
"Polyhedron::SetReferences: bad link "
1175 freeList = freeList->next;
1177 cur->next =
nullptr;
1184 if (cur->v2 == k2) {
1185 headList[k1] = cur->next;
1186 cur->next = freeList;
1188 pF[iface].edge[iedge].f = cur->iface;
1189 pF[cur->iface].edge[cur->iedge].f = iface;
1190 i1 = (
pF[iface].edge[iedge].v < 0) ? -1 : 1;
1191 i2 = (
pF[cur->iface].edge[cur->iedge].v < 0) ? -1 : 1;
1194 <<
"Polyhedron::SetReferences: different edge visibility "
1195 << iface <<
"/" << iedge <<
"/"
1196 <<
pF[iface].edge[iedge].v <<
" and "
1197 << cur->iface <<
"/" << cur->iedge <<
"/"
1198 <<
pF[cur->iface].edge[cur->iedge].v
1208 if (cur ==
nullptr) {
1209 prev->next = freeList;
1210 if (freeList ==
nullptr) {
1212 <<
"Polyhedron::SetReferences: bad link "
1216 freeList = freeList->next;
1218 cur->next =
nullptr;
1225 if (cur->v2 == k2) {
1226 prev->next = cur->next;
1227 cur->next = freeList;
1229 pF[iface].edge[iedge].f = cur->iface;
1230 pF[cur->iface].edge[cur->iedge].f = iface;
1231 i1 = (
pF[iface].edge[iedge].v < 0) ? -1 : 1;
1232 i2 = (
pF[cur->iface].edge[cur->iedge].v < 0) ? -1 : 1;
1235 <<
"Polyhedron::SetReferences: different edge visibility "
1236 << iface <<
"/" << iedge <<
"/"
1237 <<
pF[iface].edge[iedge].v <<
" and "
1238 << cur->iface <<
"/" << cur->iedge <<
"/"
1239 <<
pF[cur->iface].edge[cur->iedge].v
1250 for (i=0; i<
nvert; i++) {
1251 if (headList[i] !=
nullptr) {
1253 <<
"Polyhedron::SetReferences: List " << i <<
" is not empty"
1279 if (
pF[icur].edge[0].v == 0)
continue;
1280 if (
pF[icur].edge[3].v != 0)
continue;
1282 if (
pF[icur].edge[0].f < icur &&
1283 pF[icur].edge[1].f < icur &&
1284 pF[icur].edge[2].f < icur)
continue;
1288 G4int vcur0 = std::abs(
pF[icur].edge[0].v);
1289 G4int vcur1 = std::abs(
pF[icur].edge[1].v);
1290 G4int vcur2 = std::abs(
pF[icur].edge[2].v);
1292 G4int kcheck = 0, icheck = 0, vcheck = 0;
1294 for (
G4int k = 0; k < 3; ++k)
1296 G4int itmp =
pF[icur].edge[k].f;
1298 if (itmp < icur)
continue;
1299 if (
pF[itmp].edge[0].v == 0 ||
1300 pF[itmp].edge[3].v != 0)
continue;
1303 for (
G4int j = 0; j < 3; ++j)
1305 vtmp = std::abs(
pF[itmp].edge[j].v);
1306 if (vtmp != vcur0 && vtmp != vcur1 && vtmp != vcur2)
break;
1310 if (dtmp > tolerance || dtmp >= dist)
continue;
1316 if (icheck == 0)
continue;
1319 pF[icheck].edge[0].v = 0;
1322 pF[icur].edge[3].v =
pF[icur].edge[2].v;
1323 pF[icur].edge[2].v =
pF[icur].edge[1].v;
1324 pF[icur].edge[1].v = vcheck;
1326 else if (kcheck == 1)
1328 pF[icur].edge[3].v =
pF[icur].edge[2].v;
1329 pF[icur].edge[2].v = vcheck;
1333 pF[icur].edge[3].v = vcheck;
1336 if (njoin == 0)
return;
1342 if (
pF[icur].edge[0].v == 0)
continue;
1344 pF[nnew].edge[0].v =
pF[icur].edge[0].v;
1345 pF[nnew].edge[1].v =
pF[icur].edge[1].v;
1346 pF[nnew].edge[2].v =
pF[icur].edge[2].v;
1347 pF[nnew].edge[3].v =
pF[icur].edge[3].v;
1363 if (
nface <= 0)
return;
1364 G4int i, k, nnode, v[4],f[4];
1365 for (i=1; i<=
nface; i++) {
1366 nnode = (
pF[i].edge[3].v == 0) ? 3 : 4;
1367 for (k=0; k<nnode; k++) {
1368 v[k] = (k+1 == nnode) ?
pF[i].edge[0].v :
pF[i].edge[k+1].v;
1369 if (v[k] *
pF[i].edge[k].v < 0) v[k] = -v[k];
1370 f[k] =
pF[i].edge[k].f;
1372 for (k=0; k<nnode; k++) {
1373 pF[i].edge[nnode-1-k].v = v[k];
1374 pF[i].edge[nnode-1-k].f = f[k];
1416 G4int vIndex = pF[iFace].edge[iQVertex].v;
1418 edgeFlag = (vIndex > 0) ? 1 : 0;
1419 index = std::abs(vIndex);
1421 if (iQVertex >= 3 || pF[iFace].edge[iQVertex+1].v == 0) {
1423 if (++iFace > nface) iFace = 1;
1441 if (index <= 0 || index > nvert) {
1443 <<
"HepPolyhedron::GetVertex: irrelevant index " << index
1464 G4bool rep = GetNextVertexIndex(index, edgeFlag);
1485 if (nface == 0)
return false;
1487 G4int k = pF[iFace].edge[iNode].v;
1488 if (k > 0) { edgeFlag = 1; }
else { edgeFlag = -1; k = -k; }
1490 normal = FindNodeNormal(iFace,k);
1491 if (iNode >= 3 || pF[iFace].edge[iNode+1].v == 0) {
1493 if (++iFace > nface) iFace = 1;
1516 G4int k1, k2, kflag, kface1, kface2;
1518 if (iFace == 1 && iQVertex == 0) {
1519 k2 = pF[nface].edge[0].v;
1520 k1 = pF[nface].edge[3].v;
1521 if (k1 == 0) k1 = pF[nface].edge[2].v;
1522 if (std::abs(k1) > std::abs(k2)) iOrder = -1;
1526 k1 = pF[iFace].edge[iQVertex].v;
1530 kface2 = pF[iFace].edge[iQVertex].f;
1531 if (iQVertex >= 3 || pF[iFace].edge[iQVertex+1].v == 0) {
1533 k2 = std::abs(pF[iFace].edge[iQVertex].v);
1537 k2 = std::abs(pF[iFace].edge[iQVertex].v);
1539 }
while (iOrder*k1 > iOrder*k2);
1541 i1 = k1; i2 = k2; edgeFlag = (kflag > 0) ? 1 : 0;
1542 iface1 = kface1; iface2 = kface2;
1544 if (iFace > nface) {
1545 iFace = 1; iOrder = 1;
1564 G4int kface1, kface2;
1565 return GetNextEdgeIndices(i1, i2, edgeFlag, kface1, kface2);
1571 G4int &edgeFlag)
const
1583 G4bool rep = GetNextEdgeIndices(i1,i2,edgeFlag);
1604 G4bool rep = GetNextEdgeIndices(i1,i2,edgeFlag,iface1,iface2);
1621 if (iFace < 1 || iFace > nface) {
1623 <<
"HepPolyhedron::GetFacet: irrelevant index " << iFace
1628 for (i=0; i<4; i++) {
1629 k = pF[iFace].edge[i].v;
1631 if (iFaces !=
nullptr) iFaces[i] = pF[iFace].edge[i].f;
1634 if (edgeFlags !=
nullptr) edgeFlags[i] = 1;
1637 if (edgeFlags !=
nullptr) edgeFlags[i] = -1;
1656 GetFacet(index, n, iNodes, edgeFlags);
1658 for (
G4int i=0; i<n; i++) {
1659 nodes[i] = pV[iNodes[i]];
1660 if (normals !=
nullptr) normals[i] = FindNodeNormal(index,iNodes[i]);
1680 if (edgeFlags ==
nullptr) {
1681 GetFacet(iFace, n, nodes);
1682 }
else if (normals ==
nullptr) {
1683 GetFacet(iFace, n, nodes, edgeFlags);
1685 GetFacet(iFace, n, nodes, edgeFlags, normals);
1688 if (++iFace > nface) {
1706 if (iFace < 1 || iFace > nface) {
1708 <<
"HepPolyhedron::GetNormal: irrelevant index " << iFace
1713 G4int i0 = std::abs(pF[iFace].edge[0].v);
1714 G4int i1 = std::abs(pF[iFace].edge[1].v);
1715 G4int i2 = std::abs(pF[iFace].edge[2].v);
1716 G4int i3 = std::abs(pF[iFace].edge[3].v);
1717 if (i3 == 0) i3 = i0;
1718 return (pV[i2] - pV[i0]).cross(pV[i3] - pV[i1]);
1731 if (iFace < 1 || iFace > nface) {
1733 <<
"HepPolyhedron::GetUnitNormal: irrelevant index " << iFace
1738 G4int i0 = std::abs(pF[iFace].edge[0].v);
1739 G4int i1 = std::abs(pF[iFace].edge[1].v);
1740 G4int i2 = std::abs(pF[iFace].edge[2].v);
1741 G4int i3 = std::abs(pF[iFace].edge[3].v);
1742 if (i3 == 0) i3 = i0;
1743 return ((pV[i2] - pV[i0]).cross(pV[i3] - pV[i1])).unit();
1758 normal = GetNormal(iFace);
1759 if (++iFace > nface) {
1777 G4bool rep = GetNextNormal(normal);
1778 normal = normal.unit();
1794 G4int i0 = std::abs(
pF[iFace].edge[0].v);
1795 G4int i1 = std::abs(
pF[iFace].edge[1].v);
1796 G4int i2 = std::abs(
pF[iFace].edge[2].v);
1797 G4int i3 = std::abs(
pF[iFace].edge[3].v);
1798 if (i3 == 0) i3 = i0;
1799 srf += ((
pV[i2] -
pV[i0]).cross(
pV[i3] -
pV[i1])).mag();
1816 G4int i0 = std::abs(
pF[iFace].edge[0].v);
1817 G4int i1 = std::abs(
pF[iFace].edge[1].v);
1818 G4int i2 = std::abs(
pF[iFace].edge[2].v);
1819 G4int i3 = std::abs(
pF[iFace].edge[3].v);
1823 pt = (
pV[i0]+
pV[i1]+
pV[i2]) * (1./3.);
1825 pt = (
pV[i0]+
pV[i1]+
pV[i2]+
pV[i3]) * 0.25;
1827 v += ((
pV[i2] -
pV[i0]).cross(
pV[i3] -
pV[i1])).dot(pt);
1867 enum {DUMMY, BOTTOM,
1868 LEFT_BOTTOM, LEFT_FRONT, LEFT_TOP, LEFT_BACK,
1869 BACK_BOTTOM, BACK_LEFT, BACK_TOP, BACK_RIGHT,
1870 RIGHT_BOTTOM, RIGHT_BACK, RIGHT_TOP, RIGHT_FRONT,
1871 FRONT_BOTTOM, FRONT_RIGHT, FRONT_TOP, FRONT_LEFT,
1874 pF[ 1]=
G4Facet(1,LEFT_BOTTOM, 4,BACK_BOTTOM, 3,RIGHT_BOTTOM, 2,FRONT_BOTTOM);
1876 pF[ 2]=
G4Facet(4,BOTTOM, -1,LEFT_FRONT, -12,LEFT_BACK, 0,0);
1877 pF[ 3]=
G4Facet(1,FRONT_LEFT, -5,LEFT_TOP, -12,LEFT_BOTTOM, 0,0);
1878 pF[ 4]=
G4Facet(5,TOP, -8,LEFT_BACK, -12,LEFT_FRONT, 0,0);
1879 pF[ 5]=
G4Facet(8,BACK_LEFT, -4,LEFT_BOTTOM, -12,LEFT_TOP, 0,0);
1881 pF[ 6]=
G4Facet(3,BOTTOM, -4,BACK_LEFT, -11,BACK_RIGHT, 0,0);
1882 pF[ 7]=
G4Facet(4,LEFT_BACK, -8,BACK_TOP, -11,BACK_BOTTOM, 0,0);
1883 pF[ 8]=
G4Facet(8,TOP, -7,BACK_RIGHT, -11,BACK_LEFT, 0,0);
1884 pF[ 9]=
G4Facet(7,RIGHT_BACK, -3,BACK_BOTTOM, -11,BACK_TOP, 0,0);
1886 pF[10]=
G4Facet(2,BOTTOM, -3,RIGHT_BACK, -10,RIGHT_FRONT, 0,0);
1887 pF[11]=
G4Facet(3,BACK_RIGHT, -7,RIGHT_TOP, -10,RIGHT_BOTTOM, 0,0);
1888 pF[12]=
G4Facet(7,TOP, -6,RIGHT_FRONT, -10,RIGHT_BACK, 0,0);
1889 pF[13]=
G4Facet(6,FRONT_RIGHT,-2,RIGHT_BOTTOM,-10,RIGHT_TOP, 0,0);
1891 pF[14]=
G4Facet(1,BOTTOM, -2,FRONT_RIGHT, -9,FRONT_LEFT, 0,0);
1892 pF[15]=
G4Facet(2,RIGHT_FRONT,-6,FRONT_TOP, -9,FRONT_BOTTOM, 0,0);
1893 pF[16]=
G4Facet(6,TOP, -5,FRONT_LEFT, -9,FRONT_RIGHT, 0,0);
1894 pF[17]=
G4Facet(5,LEFT_FRONT, -1,FRONT_BOTTOM, -9,FRONT_TOP, 0,0);
1896 pF[18]=
G4Facet(5,FRONT_TOP, 6,RIGHT_TOP, 7,BACK_TOP, 8,LEFT_TOP);
1904 const G4int faces[][4])
1920 if (
nvert == 0)
return 1;
1922 for (
G4int i=0; i<Nnodes; i++) {
1923 pV[i+1] =
G4Point3D(xyz[i][0], xyz[i][1], xyz[i][2]);
1925 for (
G4int k=0; k<Nfaces; k++) {
1926 pF[k+1] =
G4Facet(faces[k][0],0,faces[k][1],0,faces[k][2],0,faces[k][3],0);
2011 G4double DzTthetaCphi = Dz*std::tan(Theta)*std::cos(Phi);
2012 G4double DzTthetaSphi = Dz*std::tan(Theta)*std::sin(Phi);
2013 G4double Dy1Talp1 = Dy1*std::tan(Alp1);
2014 G4double Dy2Talp2 = Dy2*std::tan(Alp2);
2018 pV[1] =
G4Point3D(-DzTthetaCphi-Dy1Talp1-Dx1,-DzTthetaSphi-Dy1,-Dz);
2019 pV[2] =
G4Point3D(-DzTthetaCphi-Dy1Talp1+Dx1,-DzTthetaSphi-Dy1,-Dz);
2020 pV[3] =
G4Point3D(-DzTthetaCphi+Dy1Talp1+Dx2,-DzTthetaSphi+Dy1,-Dz);
2021 pV[4] =
G4Point3D(-DzTthetaCphi+Dy1Talp1-Dx2,-DzTthetaSphi+Dy1,-Dz);
2022 pV[5] =
G4Point3D( DzTthetaCphi-Dy2Talp2-Dx3, DzTthetaSphi-Dy2, Dz);
2023 pV[6] =
G4Point3D( DzTthetaCphi-Dy2Talp2+Dx3, DzTthetaSphi-Dy2, Dz);
2024 pV[7] =
G4Point3D( DzTthetaCphi+Dy2Talp2+Dx4, DzTthetaSphi+Dy2, Dz);
2025 pV[8] =
G4Point3D( DzTthetaCphi+Dy2Talp2-Dx4, DzTthetaSphi+Dy2, Dz);
2035 :
HepPolyhedronTrap(Dz, Theta, Phi, Dy, Dx, Dx,
Alpha, Dy, Dx, Dx,
Alpha) {}
2059 static const G4double wholeCircle=twopi;
2064 if (r1 < 0. || r2 <= 0.) k = 1;
2066 if (dz <= 0.) k += 2;
2072 phi2 = sPhi; phi1 = phi2 + dPhi;
2076 phi1 = sPhi; phi2 = phi1 + wholeCircle;
2080 phi1 = sPhi; phi2 = phi1 + dPhi;
2084 if (std::abs(dphi-wholeCircle) < perMillion) dphi = wholeCircle;
2085 if (dphi > wholeCircle) k += 4;
2088 std::cerr <<
"HepPolyhedronParaboloid: error in input parameters";
2089 if ((k & 1) != 0) std::cerr <<
" (radiuses)";
2090 if ((k & 2) != 0) std::cerr <<
" (half-length)";
2091 if ((k & 4) != 0) std::cerr <<
" (angles)";
2092 std::cerr << std::endl;
2093 std::cerr <<
" r1=" << r1;
2094 std::cerr <<
" r2=" << r2;
2095 std::cerr <<
" dz=" << dz <<
" sPhi=" << sPhi <<
" dPhi=" << dPhi
2104 G4double k1 = (r2*r2 - r1*r1) / 2 / dz;
2112 for(
G4int i = 1; i < n - 1; i++)
2114 rr[i] = rr[i-1] - dl;
2115 zz[i] = (rr[i]*rr[i] - k2) / k1;
2164 static const G4double wholeCircle = twopi;
2169 if (r1 < 0. || r2 < 0. || r1 >= r2) k = 1;
2170 if (halfZ <= 0.) k += 2;
2171 if (sqrtan1 < 0.|| sqrtan2 < 0.) k += 4;
2175 std::cerr <<
"HepPolyhedronHype: error in input parameters";
2176 if ((k & 1) != 0) std::cerr <<
" (radiuses)";
2177 if ((k & 2) != 0) std::cerr <<
" (half-length)";
2178 if ((k & 4) != 0) std::cerr <<
" (angles)";
2179 std::cerr << std::endl;
2180 std::cerr <<
" r1=" << r1 <<
" r2=" << r2;
2181 std::cerr <<
" halfZ=" << halfZ <<
" sqrTan1=" << sqrtan1
2182 <<
" sqrTan2=" << sqrtan2
2190 G4int nz1 = (sqrtan1 == 0.) ? 2 :
ns + 1;
2191 G4int nz2 = (sqrtan2 == 0.) ? 2 :
ns + 1;
2197 for(
G4int i = 0; i < nz2; ++i)
2199 zz[i] = halfZ - dz2*i;
2200 rr[i] = std::sqrt(sqrtan2*zz[i]*zz[i] + r2*r2);
2205 for(
G4int i = 0; i < nz1; ++i)
2208 zz[j] = halfZ - dz1*i;
2209 rr[j] = std::sqrt(sqrtan1*zz[j]*zz[j] + r1*r1);
2214 RotateAroundZ(0, 0., wholeCircle, nz2, nz1, zz, rr, -1, -1);
2245 static const G4double wholeCircle=twopi;
2250 if (Rmn1 < 0. || Rmx1 < 0. || Rmn2 < 0. || Rmx2 < 0.) k = 1;
2251 if (Rmn1 > Rmx1 || Rmn2 > Rmx2) k = 1;
2252 if (Rmn1 == Rmx1 && Rmn2 == Rmx2) k = 1;
2254 if (Dz <= 0.) k += 2;
2258 phi2 = Phi1; phi1 = phi2 - Dphi;
2259 }
else if (Dphi == 0.) {
2260 phi1 = Phi1; phi2 = phi1 + wholeCircle;
2262 phi1 = Phi1; phi2 = phi1 + Dphi;
2265 if (std::abs(dphi-wholeCircle) < perMillion) dphi = wholeCircle;
2266 if (dphi > wholeCircle) k += 4;
2269 std::cerr <<
"HepPolyhedronCone(s)/Tube(s): error in input parameters";
2270 if ((k & 1) != 0) std::cerr <<
" (radiuses)";
2271 if ((k & 2) != 0) std::cerr <<
" (half-length)";
2272 if ((k & 4) != 0) std::cerr <<
" (angles)";
2273 std::cerr << std::endl;
2274 std::cerr <<
" Rmn1=" << Rmn1 <<
" Rmx1=" << Rmx1;
2275 std::cerr <<
" Rmn2=" << Rmn2 <<
" Rmx2=" << Rmx2;
2276 std::cerr <<
" Dz=" << Dz <<
" Phi1=" << Phi1 <<
" Dphi=" << Dphi
2347 if (dphi <= 0. || dphi > twopi) {
2349 <<
"HepPolyhedronPgon/Pcon: wrong delta phi = " << dphi
2356 <<
"HepPolyhedronPgon/Pcon: number of z-planes less than two = " << nz
2363 <<
"HepPolyhedronPgon/Pcon: error in number of phi-steps =" << npdv
2369 for (i=0; i<nz; i++) {
2370 if (rmin[i] < 0. || rmax[i] < 0. || rmin[i] > rmax[i]) {
2372 <<
"HepPolyhedronPgon: error in radiuses rmin[" << i <<
"]="
2373 << rmin[i] <<
" rmax[" << i <<
"]=" << rmax[i]
2385 if (z[0] > z[nz-1]) {
2386 for (i=0; i<nz; i++) {
2393 for (i=0; i<nz; i++) {
2395 rr[i] = rmax[nz-i-1];
2396 zz[i+nz] = z[nz-i-1];
2397 rr[i+nz] = rmin[nz-i-1];
2404 G4int edgeVis = (npdv == 0) ? -1 : 1;
2405 RotateAroundZ(npdv, phi, dphi, nz, nz, zz, rr, nodeVis, edgeVis);
2415 const std::vector<G4TwoVector> &rz)
2432 if (dphi <= 0. || dphi > twopi) {
2434 <<
"HepPolyhedronPgon/Pcon: wrong delta phi = " << dphi
2441 <<
"HepPolyhedronPgon/Pcon: error in number of phi-steps = " << npdv
2449 <<
"HepPolyhedronPgon/Pcon: invalid number of nodes in rz-contour = " << nrz
2457 G4int edgeVis = (npdv == 0) ? -1 : 1;
2471 const std::vector<G4TwoVector> &rz)
2497 if (dphi <= 0. || dphi > twopi) {
2499 <<
"HepPolyhedronSphere: wrong delta phi = " << dphi
2504 if (the < 0. || the > pi) {
2506 <<
"HepPolyhedronSphere: wrong theta = " << the
2511 if (dthe <= 0. || dthe > pi) {
2513 <<
"HepPolyhedronSphere: wrong delta theta = " << dthe
2518 if (the+dthe > pi) {
2520 <<
"HepPolyhedronSphere: wrong theta + delta theta = "
2521 << the <<
" " << dthe
2526 if (rmin < 0. || rmin >= rmax) {
2528 <<
"HepPolyhedronSphere: error in radiuses"
2529 <<
" rmin=" << rmin <<
" rmax=" << rmax
2538 if (np1 <= 1) np1 = 2;
2547 for (
G4int i=0; i<np1; i++) {
2548 cosa = std::cos(the+i*a);
2549 sina = std::sin(the+i*a);
2553 zz[i+np1] = rmin*cosa;
2554 rr[i+np1] = rmin*sina;
2595 if (dphi <= 0. || dphi > twopi) {
2597 <<
"HepPolyhedronTorus: wrong delta phi = " << dphi
2602 if (rmin < 0. || rmin >= rmax || rmax >= rtor) {
2604 <<
"HepPolyhedronTorus: error in radiuses"
2605 <<
" rmin=" << rmin <<
" rmax=" << rmax <<
" rtorus=" << rtor
2621 for (
G4int i=0; i<np1; i++) {
2622 cosa = std::cos(i*a);
2623 sina = std::sin(i*a);
2625 rr[i] = rtor+rmax*sina;
2627 zz[i+np1] = rmin*cosa;
2628 rr[i+np1] = rtor+rmin*sina;
2665 pV[1].
set(p0[0], p0[1], p0[2]);
2666 pV[2].
set(p1[0], p1[1], p1[2]);
2667 pV[3].
set(p2[0], p2[1], p2[2]);
2668 pV[4].
set(p3[0], p3[1], p3[2]);
2674 if (v1.
cross(v2).dot(v3) < 0.)
2676 pV[3].
set(p3[0], p3[1], p3[2]);
2677 pV[4].
set(p2[0], p2[1], p2[2]);
2709 if (zCut1 >= cz || zCut2 <= -cz || zCut1 > zCut2) {
2710 std::cerr <<
"HepPolyhedronEllipsoid: wrong zCut1 = " << zCut1
2711 <<
" zCut2 = " << zCut2
2712 <<
" for given cz = " << cz << std::endl;
2716 std::cerr <<
"HepPolyhedronEllipsoid: bad z semi-axis: cz = " << cz
2724 G4double sthe = std::acos(zCut2/cz);
2725 G4double dthe = std::acos(zCut1/cz) - sthe;
2728 if (np1 <= 1) np1 = 2;
2734 if ((zz ==
nullptr) || (rr ==
nullptr))
2736 G4Exception(
"HepPolyhedronEllipsoid::HepPolyhedronEllipsoid",
2742 for (
G4int i = 0; i < np1; ++i)
2744 cosa = std::cos(sthe + i*a);
2745 sina = std::sin(sthe + i*a);
2749 zz[np1 + 0] = zCut2;
2751 zz[np1 + 1] = zCut1;
2795 if ( (ax <= 0.) || (ay <= 0.) || (h <= 0.) || (zTopCut <= 0.) ) { k = 1; }
2798 std::cerr <<
"HepPolyhedronCone: error in input parameters";
2799 std::cerr << std::endl;
2805 zTopCut = (h >= zTopCut ? zTopCut : h);
2814 rr[0] = (h-zTopCut);
2815 rr[1] = (h+zTopCut);
2831 p->
setX( p->
x() * ax );
2832 p->
setY( p->
y() * ay );
2864 G4double maxAng = (
A == 0.) ? 0. : std::acosh(1. + H/
A);
2865 G4double delAng = maxAng/(np1 - 1);
2873 for (
G4int iz = 1; iz < np1 - 1; ++iz)
2876 zz[iz] =
A*std::cosh(ang) -
A;
2877 rr[iz] =
B*std::sinh(ang);
2920 <<
"HepPolyhedronTetMesh: Empty tetrahedron mesh" << std::endl;
2923 G4int ntet = nnodes/4;
2924 if (nnodes != ntet*4)
2926 std::cerr <<
"HepPolyhedronTetMesh: Number of nodes = " << nnodes
2927 <<
" in tetrahedron mesh is NOT multiple of 4"
2935 std::vector<G4int> iheads(nnodes, -1);
2936 std::vector<std::pair<G4int,G4int>> ipairs(nnodes,std::pair(-1,-1));
2937 for (
G4int i = 0; i < nnodes; ++i)
2941 auto key = std::hash<G4double>()(point.
x());
2942 key ^= std::hash<G4double>()(point.
y());
2943 key ^= std::hash<G4double>()(point.
z());
2946 if (iheads[key] < 0)
2949 ipairs[i].first = i;
2953 for (
G4int icur = iheads[key], iprev = 0;;)
2955 G4int icheck = ipairs[icur].first;
2956 if (tetrahedra[icheck] == point)
2958 ipairs[i].first = icheck;
2962 icur = ipairs[icur].second;
2966 ipairs[i].first = i;
2967 ipairs[iprev].second = i;
2977 facet() : i1(0), i2(0), i3(0) {};
2980 G4int nfacets = nnodes;
2981 std::vector<facet> ifacets(nfacets);
2982 for (
G4int i = 0; i < nfacets; i += 4)
2984 G4int i0 = ipairs[i + 0].first;
2985 G4int i1 = ipairs[i + 1].first;
2986 G4int i2 = ipairs[i + 2].first;
2987 G4int i3 = ipairs[i + 3].first;
2988 if (i0 > i1) std::swap(i0, i1);
2989 if (i0 > i2) std::swap(i0, i2);
2990 if (i0 > i3) std::swap(i0, i3);
2991 if (i1 > i2) std::swap(i1, i2);
2992 if (i1 > i3) std::swap(i1, i3);
2997 if (volume > 0.) std::swap(i2, i3);
2998 ifacets[i + 0] = facet(i0, i1, i2);
2999 ifacets[i + 1] = facet(i0, i2, i3);
3000 ifacets[i + 2] = facet(i0, i3, i1);
3001 ifacets[i + 3] = facet(i1, i3, i2);
3005 std::fill(iheads.begin(), iheads.end(), -1);
3006 std::fill(ipairs.begin(), ipairs.end(), std::pair(-1,-1));
3007 for (
G4int i = 0; i < nfacets; ++i)
3010 G4int key = ifacets[i].i1;
3011 if (iheads[key] < 0)
3014 ipairs[i].first = i;
3018 G4int i2 = ifacets[i].i2, i3 = ifacets[i].i3;
3019 for (
G4int icur = iheads[key], iprev = -1;;)
3021 G4int icheck = ipairs[icur].first;
3022 if (ifacets[icheck].i2 == i3 && ifacets[icheck].i3 == i2)
3026 iheads[key] = ipairs[icur].second;
3030 ipairs[iprev].second = ipairs[icur].second;
3032 ipairs[icur].first = -1;
3033 ipairs[icur].second = -1;
3037 icur = ipairs[icur].second;
3041 ipairs[i].first = i;
3042 ipairs[iprev].second = i;
3049 std::fill(iheads.begin(), iheads.end(), -1);
3050 G4int nver = 0, nfac = 0;
3051 for (
G4int i = 0; i < nfacets; ++i)
3053 if (ipairs[i].first < 0)
continue;
3054 G4int i1 = ifacets[i].i1;
3055 G4int i2 = ifacets[i].i2;
3056 G4int i3 = ifacets[i].i3;
3057 if (iheads[i1] < 0) iheads[i1] = nver++;
3058 if (iheads[i2] < 0) iheads[i2] = nver++;
3059 if (iheads[i3] < 0) iheads[i3] = nver++;
3065 for (
G4int i = 0; i < nnodes; ++i)
3067 G4int k = iheads[i];
3068 if (k >= 0)
SetVertex(k + 1, tetrahedra[i]);
3070 for (
G4int i = 0, k = 0; i < nfacets; ++i)
3072 if (ipairs[i].first < 0)
continue;
3073 G4int i1 = iheads[ifacets[i].i1] + 1;
3074 G4int i2 = iheads[ifacets[i].i2] + 1;
3075 G4int i3 = iheads[ifacets[i].i3] + 1;
3085 const std::vector<G4ThreeVector>& positions)
3101 std::cerr <<
"HepPolyhedronBoxMesh: Empty box mesh" << std::endl;
3105 G4double invx = 1./sizeX, invy = 1./sizeY, invz = 1./sizeZ;
3108 for (
const auto& p: positions)
3110 if (pmin.
x() > p.x()) pmin.
setX(p.x());
3111 if (pmin.
y() > p.y()) pmin.
setY(p.y());
3112 if (pmin.
z() > p.z()) pmin.
setZ(p.z());
3113 if (pmax.x() < p.x()) pmax.setX(p.x());
3114 if (pmax.y() < p.y()) pmax.setY(p.y());
3115 if (pmax.z() < p.z()) pmax.setZ(p.z());
3118 G4int nx = (pmax.x() - pmin.
x())*invx + 1.5;
3119 G4int ny = (pmax.y() - pmin.
y())*invy + 1.5;
3120 G4int nz = (pmax.z() - pmin.
z())*invz + 1.5;
3122 std::vector<char> voxels(nx*ny*nz, 0);
3123 std::vector<G4int> indices((nx+1)*(ny+1)*(nz+1), 0);
3125 G4int kx = ny*nz, ky = nz;
3126 for (
const auto& p: positions)
3128 G4int ix = (p.x() - pmin.
x())*invx + 0.5;
3129 G4int iy = (p.y() - pmin.
y())*invy + 0.5;
3130 G4int iz = (p.z() - pmin.
z())*invz + 0.5;
3131 G4int i = ix*kx + iy*ky + iz;
3136 G4int kvx = (ny + 1)*(nz + 1), kvy = nz + 1;
3137 G4int nver = 0, nfac = 0;
3138 for (
const auto& p: positions)
3140 G4int ix = (p.x() - pmin.
x())*invx + 0.5;
3141 G4int iy = (p.y() - pmin.
y())*invy + 0.5;
3142 G4int iz = (p.z() - pmin.
z())*invz + 0.5;
3156 vcheck = (ix == 0) ? 0 : voxels[(ix-1)*kx + iy*ky + iz];
3160 G4int i1 = (ix+0)*kvx + (iy+0)*kvy + (iz+0);
3161 G4int i2 = (ix+0)*kvx + (iy+0)*kvy + (iz+1);
3162 G4int i3 = (ix+0)*kvx + (iy+1)*kvy + (iz+1);
3163 G4int i4 = (ix+0)*kvx + (iy+1)*kvy + (iz+0);
3164 if (indices[i1] == 0) indices[i1] = ++nver;
3165 if (indices[i2] == 0) indices[i2] = ++nver;
3166 if (indices[i3] == 0) indices[i3] = ++nver;
3167 if (indices[i4] == 0) indices[i4] = ++nver;
3170 vcheck = (ix == nx - 1) ? 0 : voxels[(ix+1)*kx + iy*ky + iz];
3174 G4int i1 = (ix+1)*kvx + (iy+1)*kvy + (iz+0);
3175 G4int i2 = (ix+1)*kvx + (iy+1)*kvy + (iz+1);
3176 G4int i3 = (ix+1)*kvx + (iy+0)*kvy + (iz+1);
3177 G4int i4 = (ix+1)*kvx + (iy+0)*kvy + (iz+0);
3178 if (indices[i1] == 0) indices[i1] = ++nver;
3179 if (indices[i2] == 0) indices[i2] = ++nver;
3180 if (indices[i3] == 0) indices[i3] = ++nver;
3181 if (indices[i4] == 0) indices[i4] = ++nver;
3184 vcheck = (iy == 0) ? 0 : voxels[ix*kx + (iy-1)*ky + iz];
3188 G4int i1 = (ix+0)*kvx + (iy+0)*kvy + (iz+0);
3189 G4int i2 = (ix+1)*kvx + (iy+0)*kvy + (iz+0);
3190 G4int i3 = (ix+1)*kvx + (iy+0)*kvy + (iz+1);
3191 G4int i4 = (ix+0)*kvx + (iy+0)*kvy + (iz+1);
3192 if (indices[i1] == 0) indices[i1] = ++nver;
3193 if (indices[i2] == 0) indices[i2] = ++nver;
3194 if (indices[i3] == 0) indices[i3] = ++nver;
3195 if (indices[i4] == 0) indices[i4] = ++nver;
3198 vcheck = (iy == ny - 1) ? 0 : voxels[ix*kx + (iy+1)*ky + iz];
3202 G4int i1 = (ix+0)*kvx + (iy+1)*kvy + (iz+0);
3203 G4int i2 = (ix+0)*kvx + (iy+1)*kvy + (iz+1);
3204 G4int i3 = (ix+1)*kvx + (iy+1)*kvy + (iz+1);
3205 G4int i4 = (ix+1)*kvx + (iy+1)*kvy + (iz+0);
3206 if (indices[i1] == 0) indices[i1] = ++nver;
3207 if (indices[i2] == 0) indices[i2] = ++nver;
3208 if (indices[i3] == 0) indices[i3] = ++nver;
3209 if (indices[i4] == 0) indices[i4] = ++nver;
3212 vcheck = (iz == 0) ? 0 : voxels[ix*kx + iy*ky + (iz-1)];
3216 G4int i1 = (ix+0)*kvx + (iy+0)*kvy + (iz+0);
3217 G4int i2 = (ix+0)*kvx + (iy+1)*kvy + (iz+0);
3218 G4int i3 = (ix+1)*kvx + (iy+1)*kvy + (iz+0);
3219 G4int i4 = (ix+1)*kvx + (iy+0)*kvy + (iz+0);
3220 if (indices[i1] == 0) indices[i1] = ++nver;
3221 if (indices[i2] == 0) indices[i2] = ++nver;
3222 if (indices[i3] == 0) indices[i3] = ++nver;
3223 if (indices[i4] == 0) indices[i4] = ++nver;
3226 vcheck = (iz == nz - 1) ? 0 : voxels[ix*kx + iy*ky + (iz+1)];
3230 G4int i1 = (ix+0)*kvx + (iy+0)*kvy + (iz+1);
3231 G4int i2 = (ix+1)*kvx + (iy+0)*kvy + (iz+1);
3232 G4int i3 = (ix+1)*kvx + (iy+1)*kvy + (iz+1);
3233 G4int i4 = (ix+0)*kvx + (iy+1)*kvy + (iz+1);
3234 if (indices[i1] == 0) indices[i1] = ++nver;
3235 if (indices[i2] == 0) indices[i2] = ++nver;
3236 if (indices[i3] == 0) indices[i3] = ++nver;
3237 if (indices[i4] == 0) indices[i4] = ++nver;
3242 G4ThreeVector p0(pmin.
x() - 0.5*sizeX, pmin.
y() - 0.5*sizeY, pmin.
z() - 0.5*sizeZ);
3243 for (
G4int ix = 0; ix <= nx; ++ix)
3245 for (
G4int iy = 0; iy <= ny; ++iy)
3247 for (
G4int iz = 0; iz <= nz; ++iz)
3249 G4int i = ix*kvx + iy*kvy + iz;
3250 if (indices[i] == 0)
continue;
3256 for (
const auto& p: positions)
3258 G4int ix = (p.x() - pmin.
x())*invx + 0.5;
3259 G4int iy = (p.y() - pmin.
y())*invy + 0.5;
3260 G4int iz = (p.z() - pmin.
z())*invz + 0.5;
3263 vcheck = (ix == 0) ? 0 : voxels[(ix-1)*kx + iy*ky + iz];
3266 G4int i1 = (ix+0)*kvx + (iy+0)*kvy + (iz+0);
3267 G4int i2 = (ix+0)*kvx + (iy+0)*kvy + (iz+1);
3268 G4int i3 = (ix+0)*kvx + (iy+1)*kvy + (iz+1);
3269 G4int i4 = (ix+0)*kvx + (iy+1)*kvy + (iz+0);
3270 SetFacet(++nfac, indices[i1], indices[i2], indices[i3], indices[i4]);
3273 vcheck = (ix == nx - 1) ? 0 : voxels[(ix+1)*kx + iy*ky + iz];
3276 G4int i1 = (ix+1)*kvx + (iy+1)*kvy + (iz+0);
3277 G4int i2 = (ix+1)*kvx + (iy+1)*kvy + (iz+1);
3278 G4int i3 = (ix+1)*kvx + (iy+0)*kvy + (iz+1);
3279 G4int i4 = (ix+1)*kvx + (iy+0)*kvy + (iz+0);
3280 SetFacet(++nfac, indices[i1], indices[i2], indices[i3], indices[i4]);
3284 vcheck = (iy == 0) ? 0 : voxels[ix*kx + (iy-1)*ky + iz];
3287 G4int i1 = (ix+0)*kvx + (iy+0)*kvy + (iz+0);
3288 G4int i2 = (ix+1)*kvx + (iy+0)*kvy + (iz+0);
3289 G4int i3 = (ix+1)*kvx + (iy+0)*kvy + (iz+1);
3290 G4int i4 = (ix+0)*kvx + (iy+0)*kvy + (iz+1);
3291 SetFacet(++nfac, indices[i1], indices[i2], indices[i3], indices[i4]);
3294 vcheck = (iy == ny - 1) ? 0 : voxels[ix*kx + (iy+1)*ky + iz];
3297 G4int i1 = (ix+0)*kvx + (iy+1)*kvy + (iz+0);
3298 G4int i2 = (ix+0)*kvx + (iy+1)*kvy + (iz+1);
3299 G4int i3 = (ix+1)*kvx + (iy+1)*kvy + (iz+1);
3300 G4int i4 = (ix+1)*kvx + (iy+1)*kvy + (iz+0);
3301 SetFacet(++nfac, indices[i1], indices[i2], indices[i3], indices[i4]);
3304 vcheck = (iz == 0) ? 0 : voxels[ix*kx + iy*ky + (iz-1)];
3307 G4int i1 = (ix+0)*kvx + (iy+0)*kvy + (iz+0);
3308 G4int i2 = (ix+0)*kvx + (iy+1)*kvy + (iz+0);
3309 G4int i3 = (ix+1)*kvx + (iy+1)*kvy + (iz+0);
3310 G4int i4 = (ix+1)*kvx + (iy+0)*kvy + (iz+0);
3311 SetFacet(++nfac, indices[i1], indices[i2], indices[i3], indices[i4]);
3314 vcheck = (iz == nz - 1) ? 0 : voxels[ix*kx + iy*ky + (iz+1)];
3317 G4int i1 = (ix+0)*kvx + (iy+0)*kvy + (iz+1);
3318 G4int i2 = (ix+1)*kvx + (iy+0)*kvy + (iz+1);
3319 G4int i3 = (ix+1)*kvx + (iy+1)*kvy + (iz+1);
3320 G4int i4 = (ix+0)*kvx + (iy+1)*kvy + (iz+1);
3321 SetFacet(++nfac, indices[i1], indices[i2], indices[i3], indices[i4]);
3340#include "BooleanProcessor.src"
3353 BooleanProcessor processor;
3354 return processor.execute(OP_UNION, *
this, p,ierr);
3368 BooleanProcessor processor;
3369 return processor.execute(OP_INTERSECTION, *
this, p,ierr);
3383 BooleanProcessor processor;
3384 return processor.execute(OP_SUBTRACTION, *
this, p,ierr);
3392#include "HepPolyhedronProcessor.src"
const G4double kCarTolerance
G4double B(G4double temperature)
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
HepGeom::Normal3D< G4double > G4Normal3D
HepGeom::Point3D< G4double > G4Point3D
CLHEP::Hep3Vector G4ThreeVector
HepGeom::Vector3D< G4double > G4Vector3D
std::ostream & operator<<(std::ostream &ostr, const G4Facet &facet)
const G4double spatialTolerance
#define DEFAULT_NUMBER_OF_STEPS
Hep3Vector cross(const Hep3Vector &) const
BasicVector3D< T > cross(const BasicVector3D< T > &v) const
BasicVector3D< T > unit() const
void set(T x1, T y1, T z1)
T dot(const BasicVector3D< T > &v) const
~HepPolyhedronBoxMesh() override
HepPolyhedronBoxMesh(G4double sizeX, G4double sizeY, G4double sizeZ, const std::vector< G4ThreeVector > &positions)
HepPolyhedronBox(G4double Dx, G4double Dy, G4double Dz)
~HepPolyhedronBox() override
~HepPolyhedronCone() override
HepPolyhedronCone(G4double Rmn1, G4double Rmx1, G4double Rmn2, G4double Rmx2, G4double Dz)
~HepPolyhedronCons() override
HepPolyhedronCons(G4double Rmn1, G4double Rmx1, G4double Rmn2, G4double Rmx2, G4double Dz, G4double Phi1, G4double Dphi)
~HepPolyhedronEllipsoid() override
HepPolyhedronEllipsoid(G4double dx, G4double dy, G4double dz, G4double zcut1, G4double zcut2)
HepPolyhedronEllipticalCone(G4double dx, G4double dy, G4double z, G4double zcut1)
~HepPolyhedronEllipticalCone() override
HepPolyhedronHype(G4double r1, G4double r2, G4double tan1, G4double tan2, G4double halfZ)
~HepPolyhedronHype() override
~HepPolyhedronHyperbolicMirror() override
HepPolyhedronHyperbolicMirror(G4double a, G4double h, G4double r)
~HepPolyhedronPara() override
HepPolyhedronPara(G4double Dx, G4double Dy, G4double Dz, G4double Alpha, G4double Theta, G4double Phi)
~HepPolyhedronParaboloid() override
HepPolyhedronParaboloid(G4double r1, G4double r2, G4double dz, G4double Phi1, G4double Dphi)
~HepPolyhedronPcon() override
HepPolyhedronPcon(G4double phi, G4double dphi, G4int nz, const G4double *z, const G4double *rmin, const G4double *rmax)
~HepPolyhedronPgon() override
HepPolyhedronPgon(G4double phi, G4double dphi, G4int npdv, G4int nz, const G4double *z, const G4double *rmin, const G4double *rmax)
~HepPolyhedronSphere() override
HepPolyhedronSphere(G4double rmin, G4double rmax, G4double phi, G4double dphi, G4double the, G4double dthe)
~HepPolyhedronTetMesh() override
HepPolyhedronTetMesh(const std::vector< G4ThreeVector > &tetrahedra)
HepPolyhedronTet(const G4double p0[3], const G4double p1[3], const G4double p2[3], const G4double p3[3])
~HepPolyhedronTet() override
HepPolyhedronTorus(G4double rmin, G4double rmax, G4double rtor, G4double phi, G4double dphi)
~HepPolyhedronTorus() override
~HepPolyhedronTrap() override
HepPolyhedronTrap(G4double Dz, G4double Theta, G4double Phi, G4double Dy1, G4double Dx1, G4double Dx2, G4double Alp1, G4double Dy2, G4double Dx3, G4double Dx4, G4double Alp2)
HepPolyhedronTrd1(G4double Dx1, G4double Dx2, G4double Dy, G4double Dz)
~HepPolyhedronTrd1() override
HepPolyhedronTrd2(G4double Dx1, G4double Dx2, G4double Dy1, G4double Dy2, G4double Dz)
~HepPolyhedronTrd2() override
~HepPolyhedronTube() override
HepPolyhedronTube(G4double Rmin, G4double Rmax, G4double Dz)
HepPolyhedronTubs(G4double Rmin, G4double Rmax, G4double Dz, G4double Phi1, G4double Dphi)
~HepPolyhedronTubs() override
static void SetNumberOfRotationSteps(G4int n)
void RotateAroundZ(G4int nstep, G4double phi, G4double dphi, G4int np1, G4int np2, const G4double *z, G4double *r, G4int nodeVis, G4int edgeVis)
G4bool GetNextEdgeIndices(G4int &i1, G4int &i2, G4int &edgeFlag, G4int &iface1, G4int &iface2) const
G4Normal3D GetUnitNormal(G4int iFace) const
G4int createTwistedTrap(G4double Dz, const G4double xy1[][2], const G4double xy2[][2])
G4bool GetNextNormal(G4Normal3D &normal) const
HepPolyhedron & operator=(const HepPolyhedron &from)
G4Normal3D FindNodeNormal(G4int iFace, G4int iNode) const
static G4int GetNumberOfRotationSteps()
G4Normal3D GetNormal(G4int iFace) const
G4int FindNeighbour(G4int iFace, G4int iNode, G4int iOrder) const
G4bool TriangulatePolygon(const std::vector< G4TwoVector > &polygon, std::vector< G4int > &result)
void SetVertex(G4int index, const G4Point3D &v)
void RotateContourAroundZ(G4int nstep, G4double phi, G4double dphi, const std::vector< G4TwoVector > &rz, G4int nodeVis, G4int edgeVis)
void SetFacet(G4int index, G4int iv1, G4int iv2, G4int iv3, G4int iv4=0)
G4Point3D GetVertex(G4int index) const
G4double GetSurfaceArea() const
HepPolyhedron subtract(const HepPolyhedron &p) const
G4bool GetNextVertex(G4Point3D &vertex, G4int &edgeFlag) const
void GetFacet(G4int iFace, G4int &n, G4int *iNodes, G4int *edgeFlags=nullptr, G4int *iFaces=nullptr) const
G4double GetVolume() const
HepPolyhedron intersect(const HepPolyhedron &p) const
HepPolyhedron & Transform(const G4Transform3D &t)
G4int createPolyhedron(G4int Nnodes, G4int Nfaces, const G4double xyz[][3], const G4int faces[][4])
void AllocateMemory(G4int Nvert, G4int Nface)
G4bool GetNextUnitNormal(G4Normal3D &normal) const
static void ResetNumberOfRotationSteps()
G4bool CheckSnip(const std::vector< G4TwoVector > &contour, G4int a, G4int b, G4int c, G4int n, const G4int *V)
void RotateEdge(G4int k1, G4int k2, G4double r1, G4double r2, G4int v1, G4int v2, G4int vEdge, G4bool ifWholeCircle, G4int ns, G4int &kface)
static G4ThreadLocal G4int fNumberOfRotationSteps
G4bool GetNextVertexIndex(G4int &index, G4int &edgeFlag) const
G4bool GetNextFacet(G4int &n, G4Point3D *nodes, G4int *edgeFlags=nullptr, G4Normal3D *normals=nullptr) const
void JoinCoplanarFacets(G4double tolerance)
HepPolyhedron add(const HepPolyhedron &p) const
G4bool GetNextEdge(G4Point3D &p1, G4Point3D &p2, G4int &edgeFlag) const
void SetSideFacets(G4int ii[4], G4int vv[4], G4int *kk, G4double *r, G4double dphi, G4int ns, G4int &kface)