2 #include "GeoModelKernel/GeoPolyhedron.h" 7 #define perMillion 0.000001 8 #define deg (M_PI/180.0) 16 return a < 0 ? -a : a;
21 return a < 0.0f ? -a : a;
88 std::ostream & operator<< (std::ostream & ostr,
const GeoFacet & facet)
90 for (
int k = 0; k < 4; k++)
92 ostr <<
" " << facet.m_edge[k].v <<
"/" << facet.m_edge[k].f;
97 std::ostream & operator<< (std::ostream & ostr,
const GeoPolyhedron & ph)
100 ostr <<
"Nverteces=" << ph.m_nvert <<
", Nfacets=" << ph.m_nface << std::endl;
102 for (i = 1; i <= ph.m_nvert; i++)
104 ostr <<
"xyz(" << i <<
")=" 105 << ph.m_pV[i][0] <<
' ' << ph.m_pV[i][1] <<
' ' << ph.m_pV[i][2]
108 for (i = 1; i <= ph.m_nface; i++)
110 ostr <<
"face(" << i <<
")=" << ph.m_pF[i] << std::endl;
123 if (from.m_nvert > 0 && from.m_nface > 0)
125 m_nvert = from.m_nvert;
126 m_nface = from.m_nface;
127 m_pV =
new GeoTrf::Vector3D[m_nvert + 1];
130 for (i = 0; i <= m_nvert; i++)
131 m_pV[i] = from.m_pV[i];
132 for (i = 0; i <= m_nface; i++)
133 m_pF[i] = from.m_pF[i];
158 if (from.m_nvert > 0 && from.m_nface > 0)
160 m_nvert = from.m_nvert;
161 m_nface = from.m_nface;
162 m_pV =
new GeoTrf::Vector3D[m_nvert + 1];
166 for (i = 1; i <= m_nvert; i++)
167 m_pV[i] = from.m_pV[i];
168 for (i = 1; i <= m_nface; i++)
169 m_pF[i] = from.m_pF[i];
182 GeoPolyhedron::FindNeighbour (
int iFace,
int iNode,
int iOrder)
const 193 for (i = 0; i < 4; i++)
195 if (iNode == iabs (m_pF[iFace].m_edge[i].v))
201 <<
"GeoPolyhedron::FindNeighbour: face " << iFace
202 <<
" has no node " << iNode << std::endl;
209 if (m_pF[iFace].m_edge[i].v == 0)
212 return (m_pF[iFace].m_edge[i].v > 0) ? 0 : m_pF[iFace].m_edge[i].f;
215 GeoTrf::Vector3D GeoPolyhedron::FindNodeNormal (
int iFace,
int iNode)
const 227 GetUnitNormal (iFace);
238 k = FindNeighbour (k, iNode, iOrder);
244 normal += GetUnitNormal (k);
254 return normal.normalized();
258 GeoPolyhedron::SetNumberOfRotationSteps (
int n)
272 <<
"GeoPolyhedron::SetNumberOfRotationSteps: attempt to set the\n" 273 <<
"number of steps per circle < " << nMin <<
"; forced to " << nMin
275 s_fNumberOfRotationSteps = nMin;
279 s_fNumberOfRotationSteps = n;
284 GeoPolyhedron::AllocateMemory (
int Nvert,
int Nface)
299 m_pV =
new GeoTrf::Vector3D[m_nvert + 1];
304 GeoPolyhedron::CreatePrism ()
315 { DUMMY, BOTTOM, LEFT, BACK, RIGHT, FRONT, TOP };
317 m_pF[1] =
GeoFacet (1, LEFT, 4, BACK, 3, RIGHT, 2, FRONT);
318 m_pF[2] =
GeoFacet (5, TOP, 8, BACK, 4, BOTTOM, 1, FRONT);
319 m_pF[3] =
GeoFacet (8, TOP, 7, RIGHT, 3, BOTTOM, 4, LEFT);
320 m_pF[4] =
GeoFacet (7, TOP, 6, FRONT, 2, BOTTOM, 3, BACK);
321 m_pF[5] =
GeoFacet (6, TOP, 5, LEFT, 1, BOTTOM, 2, RIGHT);
322 m_pF[6] =
GeoFacet (5, FRONT, 6, RIGHT, 7, BACK, 8, LEFT);
326 GeoPolyhedron::RotateEdge (
int k1,
int k2,
double r1,
double r2,
327 int v1,
int v2,
int vEdge,
328 bool ifWholeCircle,
int ns,
int &kface)
348 if (r1 == 0. && r2 == 0)
354 int ii1 = ifWholeCircle ? i1 : i1 + ns;
355 int ii2 = ifWholeCircle ? i2 : i2 + ns;
356 int vv = ifWholeCircle ? vEdge : 1;
362 m_pF[kface++] =
GeoFacet (i1, 0, v2 * i2, 0, (i2 + 1), 0);
366 m_pF[kface++] =
GeoFacet (i1, 0, i2, 0, v1 * (i1 + 1), 0);
371 GeoFacet (i1, 0, v2 * i2, 0, (i2 + 1), 0, v1 * (i1 + 1), 0);
379 GeoFacet (vv * i1, 0, v2 * i2, 0, vEdge * (i2 + 1), 0);
380 for (i2++, i = 1; i < ns - 1; i2++, i++)
383 GeoFacet (vEdge * i1, 0, v2 * i2, 0, vEdge * (i2 + 1), 0);
385 m_pF[kface++] =
GeoFacet (vEdge * i1, 0, v2 * i2, 0, vv * ii2, 0);
390 GeoFacet (vv * i1, 0, vEdge * i2, 0, v1 * (i1 + 1), 0);
391 for (i1++, i = 1; i < ns - 1; i1++, i++)
394 GeoFacet (vEdge * i1, 0, vEdge * i2, 0, v1 * (i1 + 1), 0);
396 m_pF[kface++] =
GeoFacet (vEdge * i1, 0, vv * i2, 0, v1 * ii1, 0);
401 GeoFacet (vv * i1, 0, v2 * i2, 0, vEdge * (i2 + 1), 0,
403 for (i1++, i2++, i = 1; i < ns - 1; i1++, i2++, i++)
406 GeoFacet (vEdge * i1, 0, v2 * i2, 0, vEdge * (i2 + 1), 0,
410 GeoFacet (vEdge * i1, 0, v2 * i2, 0, vv * ii2, 0, v1 * ii1, 0);
416 GeoPolyhedron::SetSideFacets (
int ii[4],
int vv[4],
418 double dphi,
int ns,
int &kface)
437 if (fabs (dphi - M_PI) < perMillion)
439 for (
int i = 0; i < 4; i++)
442 k2 = (i == 3) ? ii[0] : ii[i + 1];
443 if (r[k1] == 0. && r[k2] == 0.)
453 m_pF[kface++] =
GeoFacet (vv[0] * k1, 0, vv[2] * k2, 0, vv[3] * k3, 0);
460 m_pF[kface++] =
GeoFacet (vv[2] * k3, 0, vv[0] * k2, 0, vv[3] * k1, 0);
462 else if (kk[ii[0]] == kk[ii[1]])
467 m_pF[kface++] =
GeoFacet (vv[1] * k1, 0, vv[2] * k2, 0, vv[3] * k3, 0);
474 m_pF[kface++] =
GeoFacet (vv[2] * k3, 0, vv[1] * k2, 0, vv[3] * k1, 0);
476 else if (kk[ii[2]] == kk[ii[3]])
481 m_pF[kface++] =
GeoFacet (vv[0] * k1, 0, vv[1] * k2, 0, vv[3] * k3, 0);
488 m_pF[kface++] =
GeoFacet (vv[1] * k3, 0, vv[0] * k2, 0, vv[3] * k1, 0);
497 GeoFacet (vv[0] * k1, 0, vv[1] * k2, 0, vv[2] * k3, 0, vv[3] * k4, 0);
507 GeoFacet (vv[2] * k4, 0, vv[1] * k3, 0, vv[0] * k2, 0, vv[3] * k1, 0);
512 GeoPolyhedron::RotateAroundZ (
int nstep,
double phi,
double dphi,
514 const double *z,
double *r,
515 int nodeVis,
int edgeVis)
538 static double wholeCircle = 2 * M_PI;
542 bool ifWholeCircle = (fabs (dphi - wholeCircle) < perMillion) ?
544 double delPhi = ifWholeCircle ? wholeCircle : dphi;
545 int nSphi = (nstep > 0) ?
546 nstep :
int (delPhi * GetNumberOfRotationSteps () / wholeCircle + .5);
549 int nVphi = ifWholeCircle ? nSphi : nSphi + 1;
550 bool ifClosed = np1 > 0 ?
false :
true;
554 int absNp1 = iabs (np1);
555 int absNp2 = iabs (np2);
557 int i1end = absNp1 - 1;
559 int i2end = absNp1 + absNp2 - 1;
562 for (i = i1beg; i <= i2end; i++)
564 if (fabs (r[i]) < perMillion)
569 for (i = i1beg; i <= i1end; i++)
571 j += (r[i] == 0.) ? 1 : nVphi;
574 bool ifSide1 =
false;
575 bool ifSide2 =
false;
577 if (r[i2beg] != r[i1beg] || z[i2beg] != z[i1beg])
579 j += (r[i2beg] == 0.) ? 1 : nVphi;
583 for (i = i2beg + 1; i < i2end; i++)
585 j += (r[i] == 0.) ? 1 : nVphi;
588 if (r[i2end] != r[i1end] || z[i2end] != z[i1end])
591 j += (r[i2end] == 0.) ? 1 : nVphi;
597 k = ifClosed ? absNp1 * nSphi : (absNp1 - 1) * nSphi;
601 for (i = i2beg; i < i2end; i++)
603 if (r[i] > 0. || r[i + 1] > 0.)
609 if (r[i2end] > 0. || r[i2beg] > 0.)
616 if (ifSide1 && (r[i1beg] > 0. || r[i2beg] > 0.))
618 if (ifSide2 && (r[i1end] > 0. || r[i2end] > 0.))
624 k += ifClosed ? 2 * absNp1 : 2 * (absNp1 - 1);
629 AllocateMemory (j, k);
634 kk =
new int[absNp1 + absNp2];
637 for (i = i1beg; i <= i1end; i++)
642 m_pV[k++] = GeoTrf::Vector3D (0, 0, z[i]);
656 m_pV[k++] = GeoTrf::Vector3D (0, 0, z[i]);
668 for (i = i2beg + 1; i < i2end; i++)
673 m_pV[k++] = GeoTrf::Vector3D (0, 0, z[i]);
688 m_pV[k] = GeoTrf::Vector3D (0, 0, z[i]);
696 double cosPhi, sinPhi;
698 double fac = delPhi / nSphi;
699 for (j = 0; j < nVphi; j++)
701 cosPhi = cos (phi + j * fac);
702 sinPhi = sin (phi + j * fac);
703 for (i = i1beg; i <= i2end; i++)
706 m_pV[kk[i] + j] = GeoTrf::Vector3D (r[i] * cosPhi, r[i] * sinPhi, z[i]);
715 v2 = ifClosed ? nodeVis : 1;
716 for (i = i1beg; i < i1end; i++)
719 if (!ifClosed && i == i1end - 1)
725 v2 = (r[i] == r[i + 1] && r[i + 1] == r[i + 2]) ? -1 : nodeVis;
727 RotateEdge (kk[i], kk[i + 1], r[i], r[i + 1], v1, v2,
728 edgeVis, ifWholeCircle, nSphi, k);
732 RotateEdge (kk[i1end], kk[i1beg], r[i1end], r[i1beg], nodeVis, nodeVis,
733 edgeVis, ifWholeCircle, nSphi, k);
740 v2 = ifClosed ? nodeVis : 1;
741 for (i = i2beg; i < i2end; i++)
744 if (!ifClosed && i == i2end - 1)
750 v2 = (r[i] == r[i + 1] && r[i + 1] == r[i + 2]) ? -1 : nodeVis;
752 RotateEdge (kk[i + 1], kk[i], r[i + 1], r[i], v2, v1,
753 edgeVis, ifWholeCircle, nSphi, k);
757 RotateEdge (kk[i2beg], kk[i2end], r[i2beg], r[i2end], nodeVis,
758 nodeVis, edgeVis, ifWholeCircle, nSphi, k);
768 RotateEdge (kk[i2beg], kk[i1beg], r[i2beg], r[i1beg], 1, 1,
769 -1, ifWholeCircle, nSphi, k);
773 RotateEdge (kk[i1end], kk[i2end], r[i1end], r[i2end], 1, 1,
774 -1, ifWholeCircle, nSphi, k);
787 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;
797 SetSideFacets (ii, vv, kk, r, dphi, nSphi, k);
802 for (i = i1beg; i < i1end; i++)
806 ii[1] = (absNp2 == 1) ? i2beg : ii[0] + absNp1;
807 ii[2] = (absNp2 == 1) ? i2beg : ii[3] + absNp1;
808 vv[0] = (i == i1beg) ? 1 : -1;
810 vv[2] = (i == i1end - 1) ? 1 : -1;
812 SetSideFacets (ii, vv, kk, r, dphi, nSphi, k);
819 if (k - 1 != m_nface)
822 <<
"Polyhedron::RotateAroundZ: number of generated faces (" 823 << k - 1 <<
") is not equal to the number of allocated faces (" 824 << m_nface <<
")" << std::endl;
829 GeoPolyhedron::SetReferences ()
842 struct edgeListMember
844 edgeListMember *next;
849 *edgeList, *freeList, **headList;
854 edgeList =
new edgeListMember[2 * m_nface];
855 headList =
new edgeListMember *[m_nvert];
858 for (i = 0; i < m_nvert; i++)
863 for (i = 0; i < 2 * m_nface - 1; i++)
865 edgeList[i].next = &edgeList[i + 1];
867 edgeList[2 * m_nface - 1].next = 0;
871 int iface, iedge, nedge, i1, i2, k1, k2;
872 edgeListMember *prev, *cur;
874 for (iface = 1; iface <= m_nface; iface++)
876 nedge = (m_pF[iface].m_edge[3].v == 0) ? 3 : 4;
877 for (iedge = 0; iedge < nedge; iedge++)
880 i2 = (iedge < nedge - 1) ? iedge + 1 : 0;
881 i1 = iabs (m_pF[iface].m_edge[i1].v);
882 i2 = iabs (m_pF[iface].m_edge[i2].v);
883 k1 = (i1 < i2) ? i1 : i2;
884 k2 = (i1 > i2) ? i1 : i2;
890 headList[k1] = freeList;
891 freeList = freeList->next;
902 headList[k1] = cur->next;
903 cur->next = freeList;
905 m_pF[iface].m_edge[iedge].f = cur->iface;
906 m_pF[cur->iface].m_edge[cur->iedge].f = iface;
907 i1 = (m_pF[iface].m_edge[iedge].v < 0) ? -1 : 1;
908 i2 = (m_pF[cur->iface].m_edge[cur->iedge].v < 0) ? -1 : 1;
912 <<
"Polyhedron::SetReferences: different edge visibility " 913 << iface <<
"/" << iedge <<
"/" 914 << m_pF[iface].m_edge[iedge].v <<
" and " 915 << cur->iface <<
"/" << cur->iedge <<
"/" 916 << m_pF[cur->iface].m_edge[cur->iedge].v << std::endl;
928 prev->next = freeList;
929 freeList = freeList->next;
940 prev->next = cur->next;
941 cur->next = freeList;
943 m_pF[iface].m_edge[iedge].f = cur->iface;
944 m_pF[cur->iface].m_edge[cur->iedge].f = iface;
945 i1 = (m_pF[iface].m_edge[iedge].v < 0) ? -1 : 1;
946 i2 = (m_pF[cur->iface].m_edge[cur->iedge].v < 0) ? -1 : 1;
951 "Polyhedron::SetReferences: different edge visibility " 952 << iface <<
"/" << iedge <<
"/" << m_pF[iface].
953 m_edge[iedge].v <<
" and " << cur->iface <<
"/" << cur->
954 iedge <<
"/" << m_pF[cur->iface].m_edge[cur->iedge].
965 for (i = 0; i < m_nvert; i++)
967 if (headList[i] != 0)
970 <<
"Polyhedron::SetReferences: List " << i <<
" is not empty" 982 GeoPolyhedron::InvertFacets ()
994 int i, k, nnode, v[4]={0}, f[4]={0};
995 for (i = 1; i <= m_nface; i++)
997 nnode = (m_pF[i].m_edge[3].v == 0) ? 3 : 4;
998 for (k = 0; k < nnode; k++)
1000 v[k] = (k + 1 == nnode) ? m_pF[i].m_edge[0].v : m_pF[i].m_edge[k + 1].v;
1001 if (v[k] * m_pF[i].m_edge[k].v < 0)
1003 f[k] = m_pF[i].m_edge[k].f;
1005 for (k = 0; k < nnode; k++)
1007 m_pF[i].m_edge[nnode - 1 - k].v = v[k];
1008 m_pF[i].m_edge[nnode - 1 - k].f = f[k];
1013 GeoPolyhedron & GeoPolyhedron::Transform (
const GeoTrf::RotationMatrix3D& rotation,
1014 const GeoTrf::Vector3D & translation)
1026 for (
int i = 1; i <= m_nvert; i++)
1028 m_pV[i] = rotation * m_pV[i] + translation;
1034 GeoTrf::Vector3D x = rotation * GeoTrf::Vector3D (1, 0, 0);
1035 GeoTrf::Vector3D y = rotation * GeoTrf::Vector3D (0, 1, 0);
1036 GeoTrf::Vector3D z = rotation * GeoTrf::Vector3D (0, 0, 1);
1037 if ((x.cross (y)).dot (z) < 0)
1043 bool GeoPolyhedron::GetNextVertexIndex (
int &index,
int &edgeFlag)
const 1065 edgeFlag = (vIndex > 0) ? 1 : 0;
1066 index = iabs (vIndex);
1068 if (iQVertex >= 3 || m_pF[iFace].m_edge[iQVertex + 1].v == 0)
1071 if (++iFace > m_nface)
1082 GeoTrf::Vector3D GeoPolyhedron::GetVertex (
int index)
const 1092 if (index <= 0 || index > m_nvert)
1095 <<
"GeoPolyhedron::GetVertex: irrelevant index " << index
1097 return GeoTrf::Vector3D ();
1103 GeoPolyhedron::GetNextVertex (GeoTrf::Vector3D & vertex,
int &edgeFlag)
const 1116 bool rep = GetNextVertexIndex (index, edgeFlag);
1117 vertex = m_pV[index];
1122 GeoPolyhedron::GetNextVertex (GeoTrf::Vector3D & vertex,
int &edgeFlag,
1123 GeoTrf::Vector3D & normal)
const 1135 static int iFace = 1;
1136 static int iNode = 0;
1141 int k = m_pF[iFace].m_edge[iNode].v;
1152 normal = FindNodeNormal (iFace, k);
1153 if (iNode >= 3 || m_pF[iFace].m_edge[iNode + 1].v == 0)
1156 if (++iFace > m_nface)
1168 GeoPolyhedron::GetNextEdgeIndeces (
int &i1,
int &i2,
int &edgeFlag,
1169 int &iface1,
int &iface2)
const 1181 static int iFace = 1;
1182 static int iQVertex = 0;
1183 static int iOrder = 1;
1184 int k1, k2, kflag, kface1, kface2;
1186 if (iFace == 1 && iQVertex == 0)
1188 k2 = m_pF[m_nface].m_edge[0].v;
1189 k1 = m_pF[m_nface].m_edge[3].v;
1191 k1 = m_pF[m_nface].m_edge[2].v;
1192 if (iabs (k1) > iabs (k2))
1198 k1 = m_pF[iFace].m_edge[iQVertex].v;
1202 kface2 = m_pF[iFace].m_edge[iQVertex].f;
1203 if (iQVertex >= 3 || m_pF[iFace].m_edge[iQVertex + 1].v == 0)
1206 k2 = iabs (m_pF[iFace].m_edge[iQVertex].v);
1212 k2 = iabs (m_pF[iFace].m_edge[iQVertex].v);
1215 while (iOrder * k1 > iOrder * k2);
1219 edgeFlag = (kflag > 0) ? 1 : 0;
1223 if (iFace > m_nface)
1236 GeoPolyhedron::GetNextEdgeIndeces (
int &i1,
int &i2,
int &edgeFlag)
const 1248 return GetNextEdgeIndeces (i1, i2, edgeFlag, kface1, kface2);
1252 GeoPolyhedron::GetNextEdge (GeoTrf::Vector3D & p1,
1253 GeoTrf::Vector3D & p2,
int &edgeFlag)
const 1265 bool rep = GetNextEdgeIndeces (i1, i2, edgeFlag);
1272 GeoPolyhedron::GetNextEdge (GeoTrf::Vector3D & p1, GeoTrf::Vector3D & p2,
1273 int &edgeFlag,
int &iface1,
int &iface2)
const 1286 bool rep = GetNextEdgeIndeces (i1, i2, edgeFlag, iface1, iface2);
1293 GeoPolyhedron::GetFacet (
int iFace,
int &n,
int *iNodes,
1294 int *edgeFlags,
int *iFaces)
const 1304 if (iFace < 1 || iFace > m_nface)
1307 <<
"GeoPolyhedron::GetFacet: irrelevant index " << iFace << std::endl;
1313 for (i = 0; i < 4; i++)
1315 k = m_pF[iFace].m_edge[i].v;
1319 iFaces[i] = m_pF[iFace].m_edge[i].f;
1338 GeoPolyhedron::GetFacet (
int index,
int &n, GeoTrf::Vector3D * nodes,
1339 int *edgeFlags, GeoTrf::Vector3D * normals)
const 1350 GetFacet (index, n, iNodes, edgeFlags);
1353 for (
int i = 0; i < 4; i++)
1355 nodes[i] = m_pV[iNodes[i]];
1357 normals[i] = FindNodeNormal (index, iNodes[i]);
1363 GeoPolyhedron::GetNextFacet (
int &n, GeoTrf::Vector3D * nodes,
1364 int *edgeFlags, GeoTrf::Vector3D * normals)
const 1375 static int iFace = 1;
1379 GetFacet (iFace, n, nodes);
1381 else if (normals == 0)
1383 GetFacet (iFace, n, nodes, edgeFlags);
1387 GetFacet (iFace, n, nodes, edgeFlags, normals);
1390 if (++iFace > m_nface)
1401 GeoTrf::Vector3D GeoPolyhedron::GetNormal (
int iFace)
const 1411 if (iFace < 1 || iFace > m_nface)
1414 <<
"GeoPolyhedron::GetNormal: irrelevant index " << iFace
1416 return GeoTrf::Vector3D ();
1421 iabs (m_pF[iFace].m_edge[0].v);
1424 iabs (m_pF[iFace].m_edge[1].v);
1427 iabs (m_pF[iFace].m_edge[2].v);
1430 iabs (m_pF[iFace].m_edge[3].v);
1433 return (m_pV[i2] - m_pV[i0]).cross (m_pV[i3] - m_pV[i1]);
1436 GeoTrf::Vector3D GeoPolyhedron::GetUnitNormal (
int iFace)
const 1446 if (iFace < 1 || iFace > m_nface)
1449 <<
"GeoPolyhedron::GetUnitNormal: irrelevant index " << iFace
1451 return GeoTrf::Vector3D ();
1456 iabs (m_pF[iFace].m_edge[0].v);
1459 iabs (m_pF[iFace].m_edge[1].v);
1462 iabs (m_pF[iFace].m_edge[2].v);
1465 iabs (m_pF[iFace].m_edge[3].v);
1469 nm = (m_pV[i2] - m_pV[i0]).
1470 cross (m_pV[i3] - m_pV[i1]);
1471 return nm.normalized();
1474 bool GeoPolyhedron::GetNextNormal (GeoTrf::Vector3D & normal)
const 1488 normal = GetNormal (iFace);
1489 if (++iFace > m_nface)
1500 bool GeoPolyhedron::GetNextUnitNormal (GeoTrf::Vector3D & normal)
const 1513 GetNextNormal (normal);
1514 normal = normal.normalized();
1519 GeoPolyhedron::GetSurfaceArea () const
1530 for (
int iFace = 1; iFace <= m_nface; iFace++)
1532 int i0 = iabs (m_pF[iFace].m_edge[0].v);
1533 int i1 = iabs (m_pF[iFace].m_edge[1].v);
1534 int i2 = iabs (m_pF[iFace].m_edge[2].v);
1535 int i3 = iabs (m_pF[iFace].m_edge[3].v);
1538 s += ((m_pV[i2] - m_pV[i0]).cross (m_pV[i3] - m_pV[i1])).norm();
1544 GeoPolyhedron::GetVolume () const
1555 for (
int iFace = 1; iFace <= m_nface; iFace++)
1557 int i0 = iabs (m_pF[iFace].m_edge[0].v);
1558 int i1 = iabs (m_pF[iFace].m_edge[1].v);
1559 int i2 = iabs (m_pF[iFace].m_edge[2].v);
1560 int i3 = iabs (m_pF[iFace].m_edge[3].v);
1565 g = (m_pV[i0] + m_pV[i1] + m_pV[i2]) * (1.0f / 3.0f);
1569 g = (m_pV[i0] + m_pV[i1] + m_pV[i2] + m_pV[i3]) * 0.25f;
1571 v += ((m_pV[i2] - m_pV[i0]).cross (m_pV[i3] - m_pV[i1])).dot (g);
1576 GeoPolyhedronTrd2::GeoPolyhedronTrd2 (
double Dx1,
double Dx2,
1577 double Dy1,
double Dy2,
double Dz)
1593 AllocateMemory (8, 6);
1595 m_pV[1] = GeoTrf::Vector3D (-Dx1, -Dy1, -Dz);
1596 m_pV[2] = GeoTrf::Vector3D (Dx1, -Dy1, -Dz);
1597 m_pV[3] = GeoTrf::Vector3D (Dx1, Dy1, -Dz);
1598 m_pV[4] = GeoTrf::Vector3D (-Dx1, Dy1, -Dz);
1599 m_pV[5] = GeoTrf::Vector3D (-Dx2, -Dy2, Dz);
1600 m_pV[6] = GeoTrf::Vector3D (Dx2, -Dy2, Dz);
1601 m_pV[7] = GeoTrf::Vector3D (Dx2, Dy2, Dz);
1602 m_pV[8] = GeoTrf::Vector3D (-Dx2, Dy2, Dz);
1607 GeoPolyhedronTrd2::~GeoPolyhedronTrd2 ()
1611 GeoPolyhedronTrd1::GeoPolyhedronTrd1 (
double Dx1,
double Dx2,
1612 double Dy,
double Dz):
1617 GeoPolyhedronTrd1::~GeoPolyhedronTrd1 ()
1621 GeoPolyhedronBox::GeoPolyhedronBox (
double Dx,
double Dy,
double Dz):
1626 GeoPolyhedronBox::~GeoPolyhedronBox ()
1630 GeoPolyhedronTrap::GeoPolyhedronTrap (
double Dz,
1638 double Dx3,
double Dx4,
double Alp2)
1662 double DzTthetaCphi = Dz * tan (Theta) * cos (Phi);
1663 double DzTthetaSphi = Dz * tan (Theta) * sin (Phi);
1664 double Dy1Talp1 = Dy1 * tan (Alp1);
1665 double Dy2Talp2 = Dy2 * tan (Alp2);
1667 AllocateMemory (8, 6);
1670 GeoTrf::Vector3D (-DzTthetaCphi - Dy1Talp1 - Dx1, -DzTthetaSphi - Dy1, -Dz);
1672 GeoTrf::Vector3D (-DzTthetaCphi - Dy1Talp1 + Dx1, -DzTthetaSphi - Dy1, -Dz);
1674 GeoTrf::Vector3D (-DzTthetaCphi + Dy1Talp1 + Dx2, -DzTthetaSphi + Dy1, -Dz);
1676 GeoTrf::Vector3D (-DzTthetaCphi + Dy1Talp1 - Dx2, -DzTthetaSphi + Dy1, -Dz);
1677 m_pV[5] = GeoTrf::Vector3D (DzTthetaCphi - Dy2Talp2 - Dx3, DzTthetaSphi - Dy2, Dz);
1678 m_pV[6] = GeoTrf::Vector3D (DzTthetaCphi - Dy2Talp2 + Dx3, DzTthetaSphi - Dy2, Dz);
1679 m_pV[7] = GeoTrf::Vector3D (DzTthetaCphi + Dy2Talp2 + Dx4, DzTthetaSphi + Dy2, Dz);
1680 m_pV[8] = GeoTrf::Vector3D (DzTthetaCphi + Dy2Talp2 - Dx4, DzTthetaSphi + Dy2, Dz);
1685 GeoPolyhedronTrap::~GeoPolyhedronTrap ()
1689 GeoPolyhedronPara::GeoPolyhedronPara (
double Dx,
double Dy,
double Dz,
1690 double Alpha,
double Theta,
double Phi):
1691 GeoPolyhedronTrap (Dz, Theta, Phi, Dy, Dx, Dx, Alpha, Dy, Dx, Dx, Alpha)
1695 GeoPolyhedronPara::~GeoPolyhedronPara ()
1699 GeoPolyhedronCons::GeoPolyhedronCons (
double Rmn1,
1703 double Dz,
double Phi1,
double Dphi)
1719 static double wholeCircle = 2 * M_PI;
1724 if (Rmn1 < 0. || Rmx1 < 0. || Rmn2 < 0. || Rmx2 < 0.)
1726 if (Rmn1 > Rmx1 || Rmn2 > Rmx2)
1728 if (Rmn1 == Rmx1 && Rmn2 == Rmx2)
1734 double phi1, phi2, dphi;
1740 else if (Dphi == 0.)
1743 phi2 = phi1 + wholeCircle;
1751 if (fabs (dphi - wholeCircle) < perMillion)
1753 if (dphi > wholeCircle)
1758 std::cerr <<
"GeoPolyhedronCone(s)/Tube(s): error in input parameters";
1760 std::cerr <<
" (radiuses)";
1762 std::cerr <<
" (half-length)";
1764 std::cerr <<
" (angles)";
1765 std::cerr << std::endl;
1766 std::cerr <<
" Rmn1=" << Rmn1 <<
" Rmx1=" << Rmx1;
1767 std::cerr <<
" Rmn2=" << Rmn2 <<
" Rmx2=" << Rmx2;
1768 std::cerr <<
" Dz=" << Dz <<
" Phi1=" << Phi1 <<
" Dphi=" << Dphi
1775 double zz[4], rr[4];
1787 RotateAroundZ (0, phi1, dphi, 2, 2, zz, rr, -1, -1);
1791 GeoPolyhedronCons::~GeoPolyhedronCons ()
1795 GeoPolyhedronCone::GeoPolyhedronCone (
double Rmn1,
double Rmx1,
1796 double Rmn2,
double Rmx2,
double Dz):
1801 GeoPolyhedronCone::~GeoPolyhedronCone ()
1805 GeoPolyhedronTubs::GeoPolyhedronTubs (
double Rmin,
double Rmax,
1806 double Dz,
double Phi1,
double Dphi):
1811 GeoPolyhedronTubs::~GeoPolyhedronTubs ()
1815 GeoPolyhedronTube::GeoPolyhedronTube (
double Rmin,
double Rmax,
double Dz):
1820 GeoPolyhedronTube::~GeoPolyhedronTube ()
1824 GeoPolyhedronPgon::GeoPolyhedronPgon (
double phi,
1829 const double *rmin,
const double *rmax)
1849 if (dphi <= 0. || dphi > 2 * M_PI)
1852 <<
"GeoPolyhedronPgon/Pcon: wrong delta phi = " << dphi << std::endl;
1859 <<
"GeoPolyhedronPgon/Pcon: number of z-planes less than two = " << nz
1867 <<
"GeoPolyhedronPgon/Pcon: error in number of phi-steps =" << npdv
1873 for (i = 0; i < nz; i++)
1875 if (rmin[i] < 0. || rmax[i] < 0. || rmin[i] > rmax[i])
1878 <<
"GeoPolyhedronPgon: error in radiuses rmin[" << i <<
"]=" 1879 << rmin[i] <<
" rmax[" << i <<
"]=" << rmax[i] << std::endl;
1887 zz =
new double[2 * nz];
1888 rr =
new double[2 * nz];
1890 if (z[0] > z[nz - 1])
1892 for (i = 0; i < nz; i++)
1897 rr[i + nz] = rmin[i];
1902 for (i = 0; i < nz; i++)
1904 zz[i] = z[nz - i - 1];
1905 rr[i] = rmax[nz - i - 1];
1906 zz[i + nz] = z[nz - i - 1];
1907 rr[i + nz] = rmin[nz - i - 1];
1913 RotateAroundZ (npdv, phi, dphi, nz, nz, zz, rr, -1, (npdv == 0) ? -1 : 1);
1920 GeoPolyhedronPgon::~GeoPolyhedronPgon ()
1924 GeoPolyhedronPcon::GeoPolyhedronPcon (
double phi,
double dphi,
int nz,
1926 const double *rmin,
const double *rmax):
1931 GeoPolyhedronPcon::~GeoPolyhedronPcon ()
1935 GeoPolyhedronSphere::GeoPolyhedronSphere (
double rmin,
double rmax,
1936 double phi,
double dphi,
1937 double the,
double dthe)
1956 if (dphi <= 0. || dphi > 2 * M_PI)
1959 <<
"GeoPolyhedronSphere: wrong delta phi = " << dphi << std::endl;
1963 if (the < 0. || the > M_PI)
1965 std::cerr <<
"GeoPolyhedronSphere: wrong theta = " << the << std::endl;
1969 if (dthe <= 0. || dthe > M_PI)
1972 <<
"GeoPolyhedronSphere: wrong delta theta = " << dthe << std::endl;
1976 if ((the + dthe >= M_PI) && (the + dthe < M_PI + 2 * DBL_EPSILON))
1979 if (the + dthe > M_PI)
1982 <<
"GeoPolyhedronSphere: wrong theta + delta theta = " 1983 << the <<
" " << dthe << std::endl;
1987 if (rmin < 0. || rmin >= rmax)
1990 <<
"GeoPolyhedronSphere: error in radiuses" 1991 <<
" rmin=" << rmin <<
" rmax=" << rmax << std::endl;
1997 int ns = (GetNumberOfRotationSteps () + 1) / 2;
1998 int np1 = int (dthe * ns * M_1_PI + .5) + 1;
2001 int np2 = rmin < perMillion ? 1 : np1;
2004 zz =
new double[np1 + np2];
2005 rr =
new double[np1 + np2];
2007 double a = dthe / (np1 - 1);
2009 for (
int i = 0; i < np1; i++)
2011 cosa = cos (the + i * a);
2012 sina = sin (the + i * a);
2013 zz[i] = rmax * cosa;
2014 rr[i] = rmax * sina;
2017 zz[i + np1] = rmin * cosa;
2018 rr[i + np1] = rmin * sina;
2029 RotateAroundZ (0, phi, dphi, np1, np2, zz, rr, -1, -1);
2036 GeoPolyhedronSphere::~GeoPolyhedronSphere ()
2040 GeoPolyhedronTorus::GeoPolyhedronTorus (
double rmin,
2042 double rtor,
double phi,
double dphi)
2060 if (dphi <= 0. || dphi > 2 * M_PI)
2063 <<
"GeoPolyhedronTorus: wrong delta phi = " << dphi << std::endl;
2067 if (rmin < 0. || rmin >= rmax || rmax >= rtor)
2070 <<
"GeoPolyhedronTorus: error in radiuses" 2071 <<
" rmin=" << rmin <<
" rmax=" << rmax <<
" rtorus=" << rtor
2078 int np1 = GetNumberOfRotationSteps ();
2079 int np2 = rmin < perMillion ? 1 : np1;
2081 std::vector<double> rr (np1+np2, 0);
2082 std::vector<double> zz (np1+np2, 0);
2084 double a = 2 * M_PI / np1;
2086 for (
int i = 0; i < np1; i++)
2090 zz[i] = rmax * cosa;
2091 rr[i] = rtor + rmax * sina;
2094 zz[i + np1] = rmin * cosa;
2095 rr[i + np1] = rtor + rmin * sina;
2107 RotateAroundZ (0, phi, dphi, -np1, -np2, zz.data(), rr.data(), -1, -1);
2111 GeoPolyhedronTorus::~GeoPolyhedronTorus ()
2116 GeoPolyhedron::s_fNumberOfRotationSteps =
2117 DEFAULT_NUMBER_OF_STEPS;
2127 #include "BooleanProcessor.src" 2129 Geo_BooleanProcessor
2142 return processor.execute (OP_UNION, *
this, p);
2155 return processor.execute (OP_INTERSECTION, *
this, p);
2168 return processor.execute (OP_SUBTRACTION, *
this, p);
Base class for GeoModel Facets Two implementations exist: