1 // Copyright (C) 2010, Guy Barrand. All rights reserved.
2 // See the file tools.license for terms.
4 /***********************************************************************
6 * Name: BooleanProcessor Date: 10.12.99 *
7 * Author: E.Chernyaev Revised: *
9 * Function: Internal class for executing boolean operations *
12 ***********************************************************************/
14 #include "../lina/plane"
16 //#define TOOLS_HEP_BP_OUT_ERR
17 //#define TOOLS_HEP_BP_CHECK_INDEX
19 //#define TOOLS_HEP_BP_VERBOSE
20 //#define TOOLS_HEP_BP_NOT_OPT
22 #if defined(TOOLS_HEP_BP_OUT_ERR) || defined(TOOLS_HEP_BP_VERBOSE) || defined(TOOLS_HEP_BP_CHECK_INDEX)
29 typedef plane<vec3d> HVPlane3D;
31 const double GRANULARITY = 10.e+5;
34 const int OP_UNION = 0;
35 const int OP_INTERSECTION = 1;
36 const int OP_SUBTRACTION = 2;
38 // Face vs face statuses
39 const int OUT_OF_PLANE = 0;
40 const int ON_PLANE = 1;
41 const int INTERSECTION = 2;
43 const int NON_PLANAR_FACE = 4;
46 const int UNKNOWN_FACE = 0;
47 const int ORIGINAL_FACE = -1;
48 const int NEW_FACE = -2;
49 const int UNSUITABLE_FACE = -3;
50 const int DEFECTIVE_FACE = -4;
52 // -------------------------------------------- Simplified STL vector ---
57 // ---------------------------------------------------- Extended node ---
60 TOOLS_SCLASS(tools::hep::ExtNode)
67 ExtNode(HVPoint3D vertex=HVPoint3D(), int status=0)
68 : v(vertex), s(status) {
70 mem::increment(s_class().c_str());
75 mem::decrement(s_class().c_str());
79 ExtNode(const ExtNode & node) : v(node.v), s(node.s) {
81 mem::increment(s_class().c_str());
85 ExtNode & operator=(const ExtNode & node) {
92 // ---------------------------------------------------- Extended edge ---
95 TOOLS_SCLASS(tools::hep::ExtEdge)
98 int i1, i2; // end points
99 int iface1; // native face
100 int iface2; // neighbouring face
101 int ivis; // visibility: +1 (visible), -1 (invisible)
102 int inext; // index of next edge
105 ExtEdge(int k1=0, int k2=0, int kface1=0, int kface2=0, int kvis=0) :
106 i1(k1), i2(k2), iface1(kface1), iface2(kface2), ivis(kvis), inext(0) {
108 mem::increment(s_class().c_str());
114 mem::decrement(s_class().c_str());
118 ExtEdge(const ExtEdge & edge) :
119 i1(edge.i1), i2(edge.i2), iface1(edge.iface1), iface2(edge.iface2),
120 ivis(edge.ivis), inext(edge.inext) {
122 mem::increment(s_class().c_str());
126 ExtEdge & operator=(const ExtEdge & edge) {
129 iface1 = edge.iface1;
130 iface2 = edge.iface2;
138 //#define SWAP(A,B) w = A; A = B; B = w
144 // ---------------------------------------------------- Extended face ---
148 TOOLS_SCLASS(tools::hep::ExtFace)
150 std::vector<ExtEdge>& edges; //G.Barrand
152 int iedges[4]; // indices of original edges
153 HVPlane3D plane; // face plane
154 double rmin[3], rmax[3]; // bounding box
155 int iold; // head of the list of the original edges
156 int inew; // head of the list of the new edges
157 int iprev; // index of previous face
158 int inext; // index of next face
161 //G.Barrand : ExtFace(int iedge=0) : iold(iedge), inew(0), iprev(iprev), inext(0) {}
162 ExtFace(std::vector<ExtEdge>& a_edges,int iedge)
163 : edges(a_edges), iold(iedge), inew(0), iprev(0), inext(0) {
165 mem::increment(s_class().c_str());
167 //G.Barrand : initialize arrays to quiet valgrind.
168 {for (int i=0; i<4; i++) { iedges[i] = 0; }}
169 {for (int i=0; i<3; i++) { rmin[i] = 0; rmax[i] = 0; }}
173 mem::decrement(s_class().c_str());
177 ExtFace(const ExtFace & face) :
178 edges(face.edges), //G.Barrand
179 plane(face.plane), iold(face.iold), inew(face.inew),
180 iprev(face.iprev), inext(face.inext)
183 mem::increment(s_class().c_str());
186 for (i=0; i<4; i++) { iedges[i] = face.iedges[i]; }
187 for (i=0; i<3; i++) { rmin[i] = face.rmin[i]; rmax[i] = face.rmax[i]; }
190 ExtFace & operator=(const ExtFace & face) {
191 //FIXME : edges(face.edges) ???? //G.Barrand
193 for (i=0; i<4; i++) { iedges[i] = face.iedges[i]; }
195 for (i=0; i<3; i++) { rmin[i] = face.rmin[i]; rmax[i] = face.rmax[i]; }
203 bool invert(); //G.Barrand : return bool.
206 #ifdef TOOLS_HEP_BP_CHECK_INDEX
207 bool check_edge_index(const std::string& a_where,int a_index) {
209 std::cerr << "ExtFace::check_edge_index :"
210 << " " << a_where << " :"
215 if(a_index>=int(edges.size())) {
216 std::cerr << "ExtFace::check_edge_index :"
217 << " " << a_where << " :"
220 << " sz=" << edges.size()
221 << " cap=" << edges.capacity()
230 // ---------------------------------------------------- Global arrays ---
231 //G.Barrand : MacIntel : crash with g++-4.0.1 with -O on some subtract.
232 // Anyway static of objects is proved to be not safe.
233 // We put the below vector as members of BooleanProcessor.
234 //GB static std::vector<ExtNode> nodes; // vector of nodes
235 //GB static std::vector<ExtEdge> edges; // vector of edges
236 //GB static std::vector<ExtFace> faces; // vector of faces
238 // ---------------------------------------------------- List of faces ---
241 TOOLS_SCLASS(tools::hep::FaceList)
244 std::vector<ExtFace>& faces; //G.Barrad : end
250 //G.Barrand : FaceList() : ihead(0), ilast(0) {}
251 FaceList(std::vector<ExtFace>& a_faces) : faces(a_faces),ihead(0),ilast(0) {
253 mem::increment(s_class().c_str());
258 mem::decrement(s_class().c_str());
262 FaceList(const FaceList& a_from)
263 :faces(a_from.faces),ihead(0),ilast(0){
265 mem::increment(s_class().c_str());
269 FaceList& operator=(const FaceList&) {return *this;}
271 void clean() { ihead = 0; ilast = 0; }
272 int front() { return ihead; }
274 void push_back(int i) {
275 if (ilast == 0) { ihead = i; } else { faces[ilast].inext = i; }
276 ExtFace& face = faces[i]; //G.Barrand : optimize.
283 ExtFace& face = faces[i]; //G.Barrand : optimize.
287 faces[face.iprev].inext = face.inext;
292 faces[face.inext].iprev = face.iprev;
299 // --------------------- Polyhedron with extended access to
300 // its members from the BooleanProcessor class ---
301 class ExtPolyhedron : public polyhedron {
302 friend class BooleanProcessor;
303 virtual polyhedron& operator = (const polyhedron& from) {
304 return polyhedron::operator = (from);
308 // ----------------------------------------- Boolean processor class ---
309 class BooleanProcessor {
311 TOOLS_SCLASS(tools::hep::BooleanProcessor)
314 //static int ishift; //G.Barrand
315 std::vector<ExtNode> nodes; // vector of nodes //G.Barrand
316 std::vector<ExtEdge> edges; // vector of edges //G.Barrand
317 std::vector<ExtFace> faces; // vector of faces //G.Barrand
319 //int processor_error; // is set in case of error
320 int operation; // 0 (union), 1 (intersection), 2 (subtraction)
321 int ifaces1, ifaces2; // lists of faces
322 int iout1, iout2; // lists of faces with status "out"
323 int iunk1, iunk2; // lists of faces with status "unknown"
324 double rmin[3], rmax[3]; // intersection of bounding boxes
325 double del; // precision (tolerance)
327 FaceList result_faces; // list of accepted faces
328 FaceList suitable_faces; // list of suitable faces
329 FaceList unsuitable_faces; // list of unsuitable faces
330 FaceList unknown_faces; // list of unknown faces
332 std::vector<int> external_contours; // heads of external contours
333 std::vector<int> internal_contours; // heads of internal contours
337 bool takePolyhedron(const polyhedron & p, double, double, double);
339 void selectOutsideFaces(int & ifaces, int & iout);
340 int testFaceVsPlane(ExtEdge & edge);
341 void renumberNodes(int & i1, int & i2, int & i3, int & i4);
342 int testEdgeVsEdge(ExtEdge & edge1, ExtEdge & edge2);
343 void removeJunkNodes() { while(nodes.back().s != 0) nodes.pop_back(); }
344 void divideEdge(int & i1, int & i2);
345 void insertEdge(const ExtEdge & edge);
346 void caseII(ExtEdge & edge1, ExtEdge & edge2);
347 bool caseIE(ExtEdge & edge1, ExtEdge & edge2);
348 bool caseEE(ExtEdge & edge1, ExtEdge & edge2);
349 bool testFaceVsFace(int iface1, int iface2);
350 void invertNewEdges(int iface);
351 void checkDoubleEdges(int iface);
352 bool assembleFace(int what, int iface);
353 bool assembleNewFaces(int what, int ihead);
354 bool initiateLists();
355 bool assemblePolyhedra();
356 void findABC(double x1, double y1, double x2, double y2,
357 double &a, double &b, double &c) const;
358 int checkDirection(double *x, double *y) const;
359 int checkIntersection(int ix, int iy, int i1, int i2) const;
360 void mergeContours(int ix, int iy, int kext, int kint);
361 bool checkTriangle(int iedge1, int iedge2, int ix, int iy) const;
362 bool triangulateContour(int ix, int iy, int ihead);
363 bool modifyReference(int iface, int i1, int i2, int iref);
364 bool triangulateFace(int iface);
365 polyhedron createPolyhedron();
368 //G.Barrand : BooleanProcessor() {}
369 BooleanProcessor() //G.Barrand
370 //:processor_error(0) //G.Barrand
372 ,suitable_faces(faces)
373 ,unsuitable_faces(faces)
374 ,unknown_faces(faces)
377 mem::increment(s_class().c_str());
381 ~BooleanProcessor() {
383 mem::decrement(s_class().c_str());
387 BooleanProcessor(const BooleanProcessor&)
388 //:processor_error(0) //G.Barrand
390 ,suitable_faces(faces)
391 ,unsuitable_faces(faces)
392 ,unknown_faces(faces)
395 mem::increment(s_class().c_str());
398 BooleanProcessor& operator=(const BooleanProcessor&){return *this;}
400 polyhedron execute(int op,
405 //G.Barrand : begin : drawing disconnected.
407 //void draw_edge(int, int);
408 //void draw_contour(int, int, int);
409 //void draw_faces(int, int, int);
410 //void print_face(int);
411 //void print_edge(int);
414 //int get_processor_error() const {return processor_error;}
416 void dump(std::ostream&); //G.Barrand
417 static int& get_shift(); //G.Barrand
418 static void set_shift(int); //G.Barrand
419 static void inc_shift(); //G.Barrand
420 static int get_num_shift(); //G.Barrand
423 bool inc_try_count(int,const polyhedron&,const polyhedron&,int&); //GB
425 static HVPoint3D CRAZY_POINT(){return HVPoint3D(-10.e+6, -10.e+6, -10.e+6);}
426 #ifdef TOOLS_HEP_BP_OUT_ERR
427 static void PROCESSOR_ERROR(int a_what){
428 std::cerr << "BooleanProcessor: boolean operation problem (" << a_what
429 << "). Try again with other shifts."
433 static void PROCESSOR_ERROR(int){}
437 #ifdef TOOLS_HEP_BP_CHECK_INDEX
438 bool check_face_index(const std::string& a_where,int a_index) {
440 std::cerr << "BooleanProcessor::check_face_index :"
441 << " " << a_where << " :"
446 if(a_index>=int(faces.size())) {
447 std::cerr << "BooleanProcessor::check_face_index :"
448 << " " << a_where << " :"
451 << " sz=" << faces.size()
452 << " cap=" << faces.capacity()
458 bool check_edge_index(const std::string& a_where,int a_index) {
460 std::cerr << "BooleanProcessor::check_edge_index :"
461 << " " << a_where << " :"
466 if(a_index>=int(edges.size())) {
467 std::cerr << "BooleanProcessor::check_edge_index :"
468 << " " << a_where << " :"
471 << " sz=" << edges.size()
472 << " cap=" << edges.capacity()
482 inline bool ExtFace::invert() //G.Barrand : return bool.
483 /***********************************************************************
485 * Name: ExtFace::invert() Date: 28.02.00 *
486 * Author: E.Chernyaev Revised: *
488 * Function: Invert face *
490 ***********************************************************************/
492 int iEprev, iEcur, iEnext;
494 iEprev = 0; iEcur = iold;
496 #ifdef TOOLS_HEP_BP_CHECK_INDEX
497 if(!check_edge_index("ExtFace::invert(1)",iEcur)) return false;
499 ExtEdge& edge = edges[iEcur]; //G.Barrand : optimize.
506 if (iold > 0) iold = iEprev;
508 iEprev = 0; iEcur = inew;
510 #ifdef TOOLS_HEP_BP_CHECK_INDEX
511 if(!check_edge_index("ExtFace::invert(2)",iEcur)) return false;
513 ExtEdge& edge = edges[iEcur]; //G.Barrand : optimize.
520 if (inew > 0) inew = iEprev;
522 //plane = HVPlane3D(-plane.a(), -plane.b(), -plane.c(), -plane.d());
524 HVNormal3D n = plane.normal();
526 plane.set(n, -plane.distance_from_origin());
532 bool BooleanProcessor::takePolyhedron(const polyhedron & p,
533 double dx, double dy, double dz)
534 /***********************************************************************
536 * Name: BooleanProcessor::takePolyhedron Date: 16.12.99 *
537 * Author: E.Chernyaev Revised: *
539 * Function: Transfer Polyhedron to internal representation *
541 ***********************************************************************/
543 int i, k, nnode, iNodes[5], iVis[4], iFaces[4];
544 int dnode = int(nodes.size()) - 1;
545 int dface = int(faces.size()) - 1;
549 // for (i=1; i <= p.GetNoVertices(); i++) {
550 // nodes.push_back(ExtNode(p.GetVertex(i)));
554 for (i=1; i <= p.GetNoVertices(); i++) {
555 #ifndef TOOLS_HEP_BP_NOT_OPT //G.Barrand
556 nodes.push_back(ExtNode());
557 ExtNode& node = nodes.back();
558 node.v = p.GetVertexFast(i);
559 node.v.add(dx,dy,dz);
561 ppp = p.GetVertexFast(i);
562 ppp += HVPoint3D(dx,dy,dz);
563 nodes.push_back(ExtNode(ppp));
569 HVNormal3D plane_n; //G.Barrand
570 HVPoint3D plane_p; //G.Barrand
572 for (int iface=1; iface <= p.GetNoFacets(); iface++) {
573 faces.push_back(ExtFace(edges,int(edges.size())));
575 // S E T F A C E N O D E S
577 p.GetFacet(iface, nnode, iNodes, iVis, iFaces);
578 for (i=0; i<nnode; i++) {
579 //if (iNodes[i] < 1 || iNodes[i] > p.GetNoVertices()) processor_error = 1;
580 //if (iFaces[i] < 1 || iFaces[i] > p.GetNoFacets()) processor_error = 1;
582 if (iNodes[i] < 1 || iNodes[i] > p.GetNoVertices()) { //G.Barrand
583 //G.Barrand : processor_error = 1;
584 #ifdef TOOLS_HEP_BP_OUT_ERR
586 << "BooleanProcessor::takePolyhedron : problem 1."
587 << " nnode " << nnode
588 << " p.GetNoVertices() " << p.GetNoVertices()
589 << " p.GetNoFacets() " << p.GetNoFacets()
590 << " iface " << iface
592 << " iNodes[i] " << iNodes[i]
595 return false; //G.Barrand
597 if (iFaces[i] < 1 || iFaces[i] > p.GetNoFacets()) { //G.Barrand
598 //G.Barrand : processor_error = 1;
599 #ifdef TOOLS_HEP_BP_OUT_ERR
601 << "BooleanProcessor::takePolyhedron : problem 2."
602 << " p.GetNoVertices() " << p.GetNoVertices()
603 << " p.GetNoFacets() " << p.GetNoFacets()
604 << " iface " << iface
606 << " iFaces[i] " << iFaces[i]
609 return false; //G.Barrand
617 iNodes[nnode] = iNodes[0];
618 faces.back().iedges[3] = 0;
619 for (i=0; i<nnode; i++) {
620 faces.back().iedges[i] = int(edges.size());
621 edges.push_back(ExtEdge(iNodes[i], iNodes[i+1],
622 iface+dface, iFaces[i], iVis[i]));
623 edges.back().inext = int(edges.size());
625 edges.back().inext = 0;
627 // S E T F A C E M I N - M A X
629 ExtFace& face = faces.back(); //G.Barrand : optimize.
630 for (i=0; i<3; i++) {
631 face.rmin[i] = nodes[iNodes[0]].v[i];
632 face.rmax[i] = nodes[iNodes[0]].v[i];
634 for (i=1; i<nnode; i++) {
635 ExtNode& node = nodes[iNodes[i]]; //G.Barrand : optimize.
636 for (k=0; k<3; k++) {
637 if (face.rmin[k] > node.v[k])
638 face.rmin[k] = node.v[k];
639 if (face.rmax[k] < node.v[k])
640 face.rmax[k] = node.v[k];
644 // S E T F A C E P L A N E
646 (nodes[iNodes[2]].v-nodes[iNodes[0]].v).cross(nodes[iNodes[3]].v-nodes[iNodes[1]].v,plane_n);
648 plane_p.set_value(0,0,0);
649 for (i=0; i<nnode; i++) { plane_p += nodes[iNodes[i]].v; }
650 plane_p *= (1./nnode);
652 //G.Barrand : faces.back().plane = HVPlane3D(n.unit(), p);
653 faces.back().plane.set(plane_n,plane_p); //G.Barrand
655 // S E T R E F E R E N C E T O T H E N E X T F A C E
657 faces.back().inext = int(faces.size());
659 faces.back().inext = 0;
661 return true; //G.Barrand
665 double BooleanProcessor::findMinMax()
666 /***********************************************************************
668 * Name: BooleanProcessor::findMinMax Date: 16.12.99 *
669 * Author: E.Chernyaev Revised: *
671 * Function: Find min-max (bounding) boxes for polyhedra *
673 ***********************************************************************/
675 if (ifaces1 == 0 || ifaces2 == 0) return 0;
678 double rmin1[3], rmax1[3];
679 double rmin2[3], rmax2[3];
681 // F I N D B O U N D I N G B O X E S
683 for (i=0; i<3; i++) {
684 rmin1[i] = faces[ifaces1].rmin[i];
685 rmax1[i] = faces[ifaces1].rmax[i];
686 rmin2[i] = faces[ifaces2].rmin[i];
687 rmax2[i] = faces[ifaces2].rmax[i];
690 iface = faces[ifaces1].inext;
692 ExtFace& face = faces[iface]; //G.Barrand
693 for (i=0; i<3; i++) {
694 if (rmin1[i] > face.rmin[i]) rmin1[i] = face.rmin[i];
695 if (rmax1[i] < face.rmax[i]) rmax1[i] = face.rmax[i];
700 iface = faces[ifaces2].inext;
702 ExtFace& face = faces[iface]; //G.Barrand
703 for (i=0; i<3; i++) {
704 if (rmin2[i] > face.rmin[i]) rmin2[i] = face.rmin[i];
705 if (rmax2[i] < face.rmax[i]) rmax2[i] = face.rmax[i];
710 // F I N D I N T E R S E C T I O N O F B O U N D I N G B O X E S
712 for (i=0; i<3; i++) {
713 rmin[i] = (rmin1[i] > rmin2[i]) ? rmin1[i] : rmin2[i];
714 rmax[i] = (rmax1[i] < rmax2[i]) ? rmax1[i] : rmax2[i];
717 // F I N D T O L E R A N C E
721 for (i=0; i<3; i++) {
722 if ((rmax1[i]-rmin1[i]) > del1) del1 = rmax1[i]-rmin1[i];
723 if ((rmax2[i]-rmin2[i]) > del2) del2 = rmax2[i]-rmin2[i];
725 return ((del1 < del2) ? del1 : del2) / GRANULARITY;
729 void BooleanProcessor::selectOutsideFaces(int & ifaces, int & iout)
730 /***********************************************************************
732 * Name: BooleanProcessor::selectOutsideFaces Date: 10.01.00 *
733 * Author: E.Chernyaev Revised: *
735 * Function: Preselection of outside faces *
737 ***********************************************************************/
739 int i, outflag, iface = ifaces, *prev;
740 HVPoint3D mmbox[8] = { HVPoint3D(rmin[0],rmin[1],rmin[2]),
741 HVPoint3D(rmax[0],rmin[1],rmin[2]),
742 HVPoint3D(rmin[0],rmax[1],rmin[2]),
743 HVPoint3D(rmax[0],rmax[1],rmin[2]),
744 HVPoint3D(rmin[0],rmin[1],rmax[2]),
745 HVPoint3D(rmax[0],rmin[1],rmax[2]),
746 HVPoint3D(rmin[0],rmax[1],rmax[2]),
747 HVPoint3D(rmax[0],rmax[1],rmax[2]) };
751 // B O U N D I N G B O X vs B O U N D I N G B O X
754 ExtFace& face = faces[iface]; //G.Barrand : optimize.
755 for (i=0; i<3; i++) {
756 if (face.rmin[i] > rmax[i] + del) { outflag = 1; break; }
757 if (face.rmax[i] < rmin[i] - del) { outflag = 1; break; }
760 // B O U N D I N G B O X vs P L A N E
763 int npos = 0, nneg = 0;
765 for (i=0; i<8; i++) {
766 d = face.plane.distance(mmbox[i]); //G.Barrand : optimize
767 if (d > +del) npos++;
768 if (d < -del) nneg++;
770 if (npos == 8 || nneg == 8) outflag = 1;
773 // U P D A T E L I S T S
788 int BooleanProcessor::testFaceVsPlane(ExtEdge & edge)
789 /***********************************************************************
791 * Name: BooleanProcessor::testFaceVsPlane Date: 19.01.00 *
792 * Author: E.Chernyaev Revised: *
794 * Function: Find result of intersection of face by plane *
796 ***********************************************************************/
798 int iface = edge.iface1;
799 const HVPlane3D& plane = faces[edge.iface2].plane;
800 int i, nnode, npos = 0, nneg = 0, nzer = 0;
803 // F I N D D I S T A N C E S
805 nnode = (faces[iface].iedges[3] == 0) ? 3 : 4;
806 for (i=0; i<nnode; i++) {
807 dd[i] = plane.distance(nodes[edges[faces[iface].iedges[i]].i1].v);
810 }else if (dd[i] < -del) {
817 // S O M E S I M P L E C A S E S ( N O I N T E R S E C T I O N )
819 if (npos == nnode || nneg == nnode) return OUT_OF_PLANE;
820 if (nzer == 1 && nneg == 0) return OUT_OF_PLANE;
821 if (nzer == 1 && npos == 0) return OUT_OF_PLANE;
822 if (nzer == nnode) return ON_PLANE;
823 if (nzer == 3) return NON_PLANAR_FACE;
825 // F I N D I N T E R S E C T I O N
827 int ie1 = 0, ie2 = 0, s1 = 0, s2 = 0, status, nint = 0;
828 enum { PLUS_MINUS, MINUS_PLUS, ZERO_ZERO, ZERO_PLUS, ZERO_MINUS };
831 for (i=0; i<nnode; i++) {
833 if (dd[i+1] >= 0) continue;
835 }else if (dd[i] < 0) {
836 if (dd[i+1] <= 0) continue;
840 if (dd[i+1] > 0) status = ZERO_PLUS;
841 if (dd[i+1] < 0) status = ZERO_MINUS;
845 ie1 = i; s1 = status; nint++; break;
847 ie2 = i; s2 = status; nint++; break;
849 return NON_PLANAR_FACE;
852 if (nint != 2) return NON_PLANAR_FACE;
854 // F O R M I N T E R S E C T I O N S E G M E N T
856 if (s1 != ZERO_ZERO && s2 != ZERO_ZERO) {
857 if (s1 == s2) return NON_PLANAR_FACE;
858 int iedge, i1 = 0, i2 = 0, ii[2];
859 double d1 = 0., d2 = 0., ddd ;
860 ii[0] = ie1; ii[1] = ie2;
861 for (i=0; i<2; i++) {
862 iedge = faces[iface].iedges[ii[i]];
864 i1 = edges[iedge].i1;
865 i2 = edges[iedge].i2;
867 d1 = plane.distance(nodes[i1].v);
868 d2 = plane.distance(nodes[i2].v);
870 if (d2 < -del) { ii[i] = int(nodes.size()); break; } // +-
871 }else if (d1 < -del) {
872 if (d2 > del) { ii[i] = int(nodes.size()); break; } // -+
874 ii[i] = i1; break; // 0+ or 0-
876 iedge = edges[iedge].inext;
878 if (ii[i] == (int)nodes.size()) {
879 ddd = d2-d1; d1 = d1/ddd; d2 = d2/ddd;
880 nodes.push_back(ExtNode(d2*nodes[i1].v-d1*nodes[i2].v, iedge));
884 if (s1 == MINUS_PLUS || s1 == ZERO_PLUS) {
893 if (npos == nneg) return NON_PLANAR_FACE;
894 edge.inext = (s1 == ZERO_ZERO) ? ie1+1 : ie2+1;
895 if (s1 == ZERO_PLUS || s2 == ZERO_MINUS) {
896 edge.i1 = edges[faces[iface].iedges[ie2]].i1;
897 edge.i2 = edges[faces[iface].iedges[ie1]].i1;
899 edge.i1 = edges[faces[iface].iedges[ie1]].i1;
900 edge.i2 = edges[faces[iface].iedges[ie2]].i1;
907 void BooleanProcessor::renumberNodes(int & i1, int & i2, int & i3, int & i4)
908 /***********************************************************************
910 * Name: BooleanProcessor::renumberNodes Date: 19.01.00 *
911 * Author: E.Chernyaev Revised: *
913 * Function: Renumber nodes and remove last temporary node. *
914 * Remark: In principal this routine can be replaced just *
916 * Removal of temporary nodes provides additional control *
917 * on number of nodes, that is very useful for debugging. *
919 ***********************************************************************/
921 if (i1 == i2) return;
922 if (nodes[i1].s == 0 || nodes.back().s == 0) { i1 = i2; return; }
924 int ilast = int(nodes.size())-1;
925 if (i1 == ilast) { i1 = i2; nodes.pop_back(); return; }
926 if (i2 == ilast) { i2 = i1; }
927 if (i3 == ilast) { i3 = i1; }
928 if (i4 == ilast) { i4 = i1; }
929 nodes[i1] = nodes.back(); i1 = i2; nodes.pop_back();
933 int BooleanProcessor::testEdgeVsEdge(ExtEdge & edge1, ExtEdge & edge2)
934 /***********************************************************************
936 * Name: BooleanProcessor::testEdgeVsEdge Date: 19.01.00 *
937 * Author: E.Chernyaev Revised: *
939 * Function: Find common part of two edges *
941 ***********************************************************************/
946 for (i=0; i<3; i++) {
947 d = nodes[edge1.i1].v[i]-nodes[edge1.i2].v[i];
949 if (d > dd) { dd = d; ii = i; }
951 double t1 = nodes[edge1.i1].v[ii];
952 double t2 = nodes[edge1.i2].v[ii];
953 double t3 = nodes[edge2.i1].v[ii];
954 double t4 = nodes[edge2.i2].v[ii];
955 if (t2-t1 < 0.) { t1 = -t1; t2 = -t2; t3 = -t3; t4 = -t4; }
957 if (t3 <= t1+del || t4 >= t2-del) return 0;
959 renumberNodes(edge2.i1, edge1.i2, edge1.i1, edge2.i2);
960 }else if (t3 < t2-del) {
961 renumberNodes(edge1.i2, edge2.i1, edge1.i1, edge2.i2);
964 renumberNodes(edge2.i2, edge1.i1, edge1.i2, edge2.i1);
965 }else if (t4 > t1+del) {
966 renumberNodes(edge1.i1, edge2.i2, edge1.i2, edge2.i1);
972 void BooleanProcessor::divideEdge(int & i1, int & i2)
973 /***********************************************************************
975 * Name: BooleanProcessor::divideEdge Date: 24.01.00 *
976 * Author: E.Chernyaev Revised: *
978 * Function: Unify the nodes and divide edge on two parts by the node. *
980 ***********************************************************************/
983 iedges[0] = nodes[i1].s;
984 iedges[1] = nodes[i2].s;
986 // U N I F Y N O D E S
988 if (i1 < i2) { i2 = i1; }
989 else if (i1 > i2) { i1 = i2; }
990 else { iedges[1] = 0; }
991 if (iedges[0] == iedges[1]) return;
993 int ie1, ie2, inode = i1;
995 for (int i=0; i<2; i++) {
997 // F I N D C O R R E S P O N D I N G E D G E
999 if ((ie1 = iedges[i]) == 0) continue;
1000 ie2 = faces[edges[ie1].iface2].iedges[0];
1002 if (edges[ie2].i1 == edges[ie1].i2 &&
1003 edges[ie2].i2 == edges[ie1].i1) break;
1004 ie2 = edges[ie2].inext;
1007 // D I V I D E E D G E S
1009 edges.push_back(edges[ie1]);
1010 edges[ie1].inext = int(edges.size()) - 1;
1011 edges[ie1].i2 = inode;
1012 edges.back().i1 = inode;
1014 edges.push_back(edges[ie2]);
1015 edges[ie2].inext = int(edges.size()) - 1;
1016 edges[ie2].i2 = inode;
1017 edges.back().i1 = inode;
1022 void BooleanProcessor::insertEdge(const ExtEdge & edge)
1023 /***********************************************************************
1025 * Name: BooleanProcessor::insertEdge Date: 24.01.00 *
1026 * Author: E.Chernyaev Revised: *
1028 * Function: Insert edge to the list of new edges *
1030 ***********************************************************************/
1032 int iface = edge.iface1;
1033 edges.push_back(edge);
1034 edges.back().inext = faces[iface].inew;
1035 faces[iface].inew = int(edges.size()) - 1;
1039 void BooleanProcessor::caseII(ExtEdge & edge1, ExtEdge & edge2)
1040 /***********************************************************************
1042 * Name: BooleanProcessor::caseII Date: 19.01.00 *
1043 * Author: E.Chernyaev Revised: *
1045 * Function: Intersection/Intersection case *
1047 ***********************************************************************/
1049 divideEdge(edge1.i1, edge2.i2);
1050 divideEdge(edge1.i2, edge2.i1);
1058 bool BooleanProcessor::caseIE(ExtEdge &, ExtEdge &)
1059 /***********************************************************************
1061 * Name: BooleanProcessor::caseIE Date: 19.01.00 *
1062 * Author: E.Chernyaev Revised: *
1064 * Function: Intersection/Edge-touch case *
1066 ***********************************************************************/
1068 //G.Barrand : processor_error = 1;
1069 #ifdef TOOLS_HEP_BP_OUT_ERR
1071 << "BooleanProcessor::caseIE : unimplemented case"
1074 return false; //G.Barrand
1078 bool BooleanProcessor::caseEE(ExtEdge &, ExtEdge &)
1079 /***********************************************************************
1081 * Name: BooleanProcessor::caseEE Date: 19.01.00 *
1082 * Author: E.Chernyaev Revised: *
1084 * Function: Edge-touch/Edge-touch case *
1086 ***********************************************************************/
1088 //G.Barrand : processor_error = 1;
1089 #ifdef TOOLS_HEP_BP_OUT_ERR
1091 << "BooleanProcessor::caseEE : unimplemented case"
1098 bool BooleanProcessor::testFaceVsFace(int iface1, int iface2)
1099 /***********************************************************************
1101 * Name: BooleanProcessor::testFaceVsFace Date: 11.01.00 *
1102 * Author: E.Chernyaev Revised: *
1104 * Function: Find result (an edge) of intersection of two faces *
1106 ***********************************************************************/
1108 ExtEdge edge1, edge2;
1113 {const ExtFace& face_1 = faces[iface1]; //G.Barrand : optimize
1114 const ExtFace& face_2 = faces[iface2];
1115 for (int i=0; i<3; i++) {
1116 if (face_1.rmin[i] > face_2.rmax[i] + del) return true; //GB : true ?
1117 if (face_1.rmax[i] < face_2.rmin[i] - del) return true; //GB : true ?
1120 // F A C E - 1 vs P L A N E - 2
1122 edge1.iface1 = iface1;
1123 edge1.iface2 = iface2;
1124 irep1 = testFaceVsPlane(edge1);
1125 if (irep1 == OUT_OF_PLANE || irep1 == ON_PLANE) {
1127 return true; //GB : true ?
1130 // F A C E - 2 vs P L A N E - 1
1132 edge2.iface1 = iface2;
1133 edge2.iface2 = iface1;
1134 irep2 = testFaceVsPlane(edge2);
1135 if (irep2 == OUT_OF_PLANE || irep2 == ON_PLANE) {
1137 return true; //GB : true ?
1140 // C H E C K F O R N O N P L A N A R F A C E
1142 if (irep1 == NON_PLANAR_FACE || irep2 == NON_PLANAR_FACE) {
1144 return true; //GB : true ?
1147 // F I N D I N T E R S E C T I O N P A R T
1149 if (testEdgeVsEdge(edge1, edge2) == 0) {
1150 return true; //GB : true ?
1153 // C O N S I D E R D I F F E R E N T C A S E S
1155 if (irep1 == INTERSECTION && irep2 == INTERSECTION) caseII(edge1, edge2);
1156 if (irep1 == INTERSECTION && irep2 == EDGE) {
1157 if(!caseIE(edge1, edge2)) {
1158 //G.Barrand : processor_error = 1;
1159 removeJunkNodes(); //G.Barrand
1160 return false; //G.Barrand
1163 if (irep1 == EDGE && irep2 == INTERSECTION) {
1164 if(!caseIE(edge2, edge1)) {
1165 //G.Barrand : processor_error = 1;
1166 removeJunkNodes(); //G.Barrand
1167 return false; //G.Barrand
1170 if (irep1 == EDGE && irep2 == EDGE) {
1171 if(!caseEE(edge1, edge2)) {
1172 //G.Barrand : processor_error = 1;
1173 removeJunkNodes(); //G.Barrand
1174 return false; //G.Barrand
1179 return true; //G.Barrand
1183 void BooleanProcessor::invertNewEdges(int iface)
1184 /***********************************************************************
1186 * Name: BooleanProcessor::invertNewEdges Date: 04.02.00 *
1187 * Author: E.Chernyaev Revised: *
1189 * Function: Invert direction of new edges *
1191 ***********************************************************************/
1193 int iedge = faces[iface].inew;
1195 edges[iedge].invert();
1196 iedge = edges[iedge].inext;
1201 void BooleanProcessor::checkDoubleEdges(int)
1202 /***********************************************************************
1204 * Name: BooleanProcessor::checkDoubleEdges Date: 04.02.00 *
1205 * Author: E.Chernyaev Revised: *
1207 * Function: Eliminate duplication of edges *
1209 ***********************************************************************/
1215 bool BooleanProcessor::assembleFace(int what, int iface)
1216 /***********************************************************************
1218 * Name: BooleanProcessor::assembleFace Date: 19.02.00 *
1219 * Author: E.Chernyaev Revised: *
1221 * Function: Assemble face *
1223 ***********************************************************************/
1225 // A S S E M B L E N E W F A C E
1227 int ihead; // head of the list of edges for new face
1228 int icur; // current edge in the list - last edge inserted to the list
1229 int *ilink; // pointer to the current link
1230 int ifirst; // first node of a contour
1231 int *i; // pointer to the index of the current edge in a loop
1232 int ioldflag=0; // is set if an edge from iold has been taken
1234 ExtFace& face = faces[iface]; //G.Barrand : optimize.
1237 if (face.inew == 0) break;
1239 // S T A R T N E W C O N T O U R
1242 face.inew = edges[icur].inext;
1244 //INSERT_EDGE_TO_THE_LIST(icur); //G.Barrand
1245 *ilink = icur; ilink = &edges[icur].inext; *ilink = 0; //G.Barrand
1247 ifirst = edges[icur].i1;
1249 // C O N S T R U C T T H E C O N T O U R
1253 ExtEdge& edge_cur = edges[icur];
1255 ExtEdge& edge_i = edges[*i];
1256 if (edge_i.i1 == edge_cur.i2) break;
1262 ExtEdge& edge_i = edges[*i];
1263 if (edge_i.i1 == edge_cur.i2) {
1272 *i = edges[icur].inext;
1274 //INSERT_EDGE_TO_THE_LIST(icur);
1275 *ilink = icur; ilink = &edges[icur].inext; *ilink = 0; //G.Barrand
1277 if (edges[icur].i2 == ifirst) { break; } else { continue; }
1279 //G.Barrand : processor_error = 1;
1280 #ifdef TOOLS_HEP_BP_OUT_ERR
1282 << "BooleanProcessor::assembleFace(" << iface << ") : "
1283 << "could not find next edge of the contour"
1286 face.inew = DEFECTIVE_FACE;
1287 return false; //G.Barrand : false
1292 // C H E C K O R I G I N A L C O N T O U R
1296 if (what == 0 && ioldflag == 0 && iedge > 0) {
1298 if (edges[iedge].inext > 0) {
1299 if (edges[iedge].i2 == edges[edges[iedge].inext].i1) {
1300 iedge = edges[iedge].inext;
1305 if (edges[iedge].i2 == edges[face.iold].i1) {
1306 edges[iedge].inext = ihead; // set new face
1307 return true; //G.Barrand : true.
1315 // M A R K U N S U I T A B L E N E I G H B O U R I N G F A C E S
1320 iface2 = edges[iedge].iface2;
1321 if (faces[iface2].inew == 0) faces[iface2].inew = UNSUITABLE_FACE;
1322 iedge = edges[iedge].inext;
1324 face.iold = ihead; // set new face
1330 bool BooleanProcessor::assembleNewFaces(int what, int ihead)
1331 /***********************************************************************
1333 * Name: BooleanProcessor::assembleNewFaces Date: 30.01.00 *
1334 * Author: E.Chernyaev Revised: *
1336 * Function: Assemble internal or external parts of faces *
1338 ***********************************************************************/
1342 if (faces[iface].inew > 0) {
1343 if (what != 0) invertNewEdges(iface);
1344 checkDoubleEdges(iface);
1345 if(!assembleFace(what, iface)) return false; //G.Barrand : test.
1347 (faces[iface].iold == 0) ? UNSUITABLE_FACE : NEW_FACE;
1349 iface = faces[iface].inext;
1351 return true; //G.Barrand
1355 bool BooleanProcessor::initiateLists() //G.Barrand : return bool.
1356 /***********************************************************************
1358 * Name: BooleanProcessor::initiateLists Date: 28.02.00 *
1359 * Author: E.Chernyaev Revised: *
1361 * Function: Initiate lists of faces. *
1363 ***********************************************************************/
1367 // R E S E T L I S T S O F F A C E S
1369 result_faces.clean();
1370 suitable_faces.clean();
1371 unsuitable_faces.clean();
1372 unknown_faces.clean();
1374 // I N I T I A T E T H E L I S T S
1379 #ifdef TOOLS_HEP_BP_CHECK_INDEX
1380 if(!check_face_index("initiateLists(1)",i)) return false;
1382 iface = faces[i].inext;
1383 if (operation == OP_INTERSECTION) {
1384 unsuitable_faces.push_back(i);
1385 faces[i].inew = UNSUITABLE_FACE;
1387 suitable_faces.push_back(i);
1388 faces[i].inew = ORIGINAL_FACE;
1395 #ifdef TOOLS_HEP_BP_CHECK_INDEX
1396 if(!check_face_index("initiateLists(2)",i)) return false;
1398 iface = faces[i].inext;
1399 if (operation == OP_UNION) {
1400 suitable_faces.push_back(i);
1401 faces[i].inew = ORIGINAL_FACE;
1403 unsuitable_faces.push_back(i);
1404 faces[i].inew = UNSUITABLE_FACE;
1411 #ifdef TOOLS_HEP_BP_CHECK_INDEX
1412 if(!check_face_index("initiateLists(3)",i)) return false;
1414 iface = faces[i].inext;
1415 unknown_faces.push_back(i);
1420 #ifdef TOOLS_HEP_BP_CHECK_INDEX
1421 if(!check_face_index("initiateLists(4)",i)) return false;
1423 iface = faces[i].inext;
1424 if (operation == OP_SUBTRACTION) {
1425 if(!faces[i].invert()) return false; //G.Barrand
1427 unknown_faces.push_back(i);
1433 #ifdef TOOLS_HEP_BP_CHECK_INDEX
1434 if(!check_face_index("initiateLists(5)",i)) return false;
1436 iface = faces[i].inext;
1437 switch(faces[i].inew) {
1439 unknown_faces.push_back(i);
1441 case ORIGINAL_FACE: case NEW_FACE:
1442 suitable_faces.push_back(i);
1444 case UNSUITABLE_FACE:
1445 unsuitable_faces.push_back(i);
1457 iface = faces[i].inext;
1458 #ifdef TOOLS_HEP_BP_CHECK_INDEX
1459 if(!check_face_index("initiateLists(6)",i)) return false;
1462 if (operation == OP_SUBTRACTION) {
1463 if(!faces[i].invert()) return false;
1466 switch(faces[i].inew) {
1468 unknown_faces.push_back(i);
1470 case ORIGINAL_FACE: case NEW_FACE:
1471 suitable_faces.push_back(i);
1473 case UNSUITABLE_FACE:
1474 unsuitable_faces.push_back(i);
1482 ifaces1 = ifaces2 = iout1 = iout2 = iunk1 = iunk2 = 0;
1483 return true; //G.Barrand.
1487 bool BooleanProcessor::assemblePolyhedra() //G.Barrand : return bool.
1488 /***********************************************************************
1490 * Name: BooleanProcessor::assemblePolyhedra() Date: 10.12.99 *
1491 * Author: E.Chernyaev Revised: *
1493 * Function: Collect suitable faces and remove unsuitable ones. *
1495 ***********************************************************************/
1497 int i, iedge, iface;
1499 // L O O P A L O N G S U I T A B L E F A C E S
1501 iface = suitable_faces.front();
1504 #ifdef TOOLS_HEP_BP_CHECK_INDEX
1505 if(!check_face_index("assemblePolyhedra(1)",i)) return false;
1507 iedge = faces[i].iold;
1509 #ifdef TOOLS_HEP_BP_CHECK_INDEX
1510 if(!check_edge_index("assemblePolyhedra(2)",iedge)) return false;
1512 iface = edges[iedge].iface2;
1513 #ifdef TOOLS_HEP_BP_CHECK_INDEX
1514 if(!check_face_index("assemblePolyhedra(3)",iface)) return false;
1516 if (faces[iface].inew == UNKNOWN_FACE) {
1517 unknown_faces.remove(iface);
1518 suitable_faces.push_back(iface);
1519 faces[iface].inew = ORIGINAL_FACE;
1521 iedge = edges[iedge].inext;
1523 #ifdef TOOLS_HEP_BP_CHECK_INDEX
1524 if(!check_face_index("assemblePolyhedra(4)",i)) return false;
1526 iface = faces[i].inext;
1527 suitable_faces.remove(i);
1528 result_faces.push_back(i);
1530 if (unknown_faces.front() == 0) return true;
1532 // L O O P A L O N G U N S U I T A B L E F A C E S
1534 iface = unsuitable_faces.front();
1537 #ifdef TOOLS_HEP_BP_CHECK_INDEX
1538 if(!check_face_index("assemblePolyhedra(5)",i)) return false;
1540 iedge = faces[i].iold;
1542 #ifdef TOOLS_HEP_BP_CHECK_INDEX
1543 if(!check_edge_index("assemblePolyhedra(6)",iedge)) return false;
1545 iface = edges[iedge].iface2;
1546 #ifdef TOOLS_HEP_BP_CHECK_INDEX
1547 if(!check_face_index("assemblePolyhedra(7)",iface)) return false;
1549 if (faces[iface].inew == UNKNOWN_FACE) {
1550 unknown_faces.remove(iface);
1551 unsuitable_faces.push_back(iface);
1552 faces[iface].inew = UNSUITABLE_FACE;
1554 iedge = edges[iedge].inext;
1556 #ifdef TOOLS_HEP_BP_CHECK_INDEX
1557 if(!check_face_index("assemblePolyhedra(8)",i)) return false;
1559 iface = faces[i].inext;
1560 unsuitable_faces.remove(i);
1565 At last, there is a problem in the assemblePolyhedra method. At least, I
1566 think it is there. The problem deals with boolean operations on solids,
1567 when one of the two contains entirely the other one. It has no sense for
1568 intersection and union but still has sense for subtraction. In this
1569 case, faces from the inner solid are stored in the unknown_faces
1570 FaceList. And an error occurs in the execute method. This may be correct
1571 for intersection and union but in the case of subtraction, one should do
1572 that in assemblePolyhedra :
1574 // Unknown faces are actually suitable face !!!
1575 iface = unknown_faces.front();
1578 #ifdef TOOLS_HEP_BP_CHECK_INDEX
1579 if(!check_face_index("assemblePolyhedra(9)",i)) return false;
1581 faces[i].inew = ORIGINAL_FACE;
1582 iface = faces[i].inext;
1583 unknown_faces.remove(i);
1584 result_faces.push_back(i);
1587 Otherwise, the inner hole that the second solid was building in the
1588 first one does not exist. I'm not very clear on what to do for unions
1589 and intersections. I think this kind of situation should be detected and
1590 one of the solid should simply be ignored.
1598 BooleanProcessor::findABC(double x1, double y1, double x2, double y2,
1599 double &a, double &b, double &c) const
1600 /***********************************************************************
1602 * Name: BooleanProcessor::findABC Date: 07.03.00 *
1603 * Author: E.Chernyaev Revised: *
1605 * Function: Find line equation Ax+By+C=0 *
1607 ***********************************************************************/
1612 //G.Barrand : w = std::abs(a)+std::abs(b);
1613 w = ::fabs(a)+::fabs(b); //G.Barrand
1620 int BooleanProcessor::checkDirection(double *x, double *y) const
1621 /***********************************************************************
1623 * Name: BooleanProcessor::checkDirection Date: 06.03.00 *
1624 * Author: E.Chernyaev Revised: *
1626 * Function: Check direction of line 1-4 *
1628 ***********************************************************************/
1630 double a1, b1, c1, a2, b2, c2, d1, d2;
1632 // T E S T L I N E 1 - 4 V S E X T E R N A L C O N T O U R
1634 findABC(x[0], y[0], x[1], y[1], a1, b1, c1);
1635 findABC(x[1], y[1], x[2], y[2], a2, b2, c2);
1636 d1 = a1*x[4] + b1*y[4] + c1;
1637 d2 = a2*x[4] + b2*y[4] + c2;
1638 if (d1 <= del && d2 <= del) return 1;
1639 if (! (d1 > del && d2 > del)) {
1640 if ( a1*x[2] + b1*y[2] + c1 >= -del) return 1;
1643 // T E S T L I N E 1 - 4 V S I N T E R N A L C O N T O U R
1645 findABC(x[3], y[3], x[4], y[4], a1, b1, c1);
1646 findABC(x[4], y[4], x[5], y[5], a2, b2, c2);
1647 d1 = a1*x[1] + b1*y[1] + c1;
1648 d2 = a2*x[1] + b2*y[1] + c2;
1649 if (d1 <= del && d2 <= del) return 1;
1650 if (!(d1 > del && d2 > del)) {
1651 if ( a1*x[5] + b1*y[5] + c1 >= -del) return 1;
1657 int BooleanProcessor::checkIntersection(int ix, int iy, int i1, int i2) const
1658 /***********************************************************************
1660 * Name: BooleanProcessor::checkDirection Date: 06.03.00 *
1661 * Author: E.Chernyaev Revised: *
1663 * Function: Check line i1-i2 on intersection with contours *
1665 ***********************************************************************/
1667 // F I N D L I N E E Q U A T I O N
1669 double x1, y1, x2, y2, a1, b1, c1;
1670 x1 = nodes[i1].v[ix];
1671 y1 = nodes[i1].v[iy];
1672 x2 = nodes[i2].v[ix];
1673 y2 = nodes[i2].v[iy];
1674 findABC(x1, y1, x2, y2, a1, b1, c1);
1676 // L O O P A L O N G E X T E R N A L C O N T O U R S
1678 int icontour, iedge, k1, k2;
1679 double x3, y3, x4, y4, a2, b2, c2, d1, d2;
1680 for(icontour=0; icontour<(int)external_contours.size(); icontour++) {
1681 iedge = external_contours[icontour];
1683 k1 = edges[iedge].i1;
1684 k2 = edges[iedge].i2;
1685 iedge = edges[iedge].inext;
1686 if (k1 == i1 || k2 == i1) continue;
1687 if (k1 == i2 || k2 == i2) continue;
1688 x3 = nodes[k1].v[ix];
1689 y3 = nodes[k1].v[iy];
1690 x4 = nodes[k2].v[ix];
1691 y4 = nodes[k2].v[iy];
1692 d1 = a1*x3 + b1*y3 + c1;
1693 d2 = a1*x4 + b1*y4 + c1;
1694 if (d1 > del && d2 > del) continue;
1695 if (d1 < -del && d2 < -del) continue;
1697 findABC(x3, y3, x4, y4, a2, b2, c2);
1698 d1 = a2*x1 + b2*y1 + c2;
1699 d2 = a2*x2 + b2*y2 + c2;
1700 if (d1 > del && d2 > del) continue;
1701 if (d1 < -del && d2 < -del) continue;
1706 // L O O P A L O N G E X T E R N A L C O N T O U R S
1708 for(icontour=0; icontour<(int)internal_contours.size(); icontour++) {
1709 iedge = internal_contours[icontour];
1711 k1 = edges[iedge].i1;
1712 k2 = edges[iedge].i2;
1713 iedge = edges[iedge].inext;
1714 if (k1 == i1 || k2 == i1) continue;
1715 if (k1 == i2 || k2 == i2) continue;
1716 x3 = nodes[k1].v[ix];
1717 y3 = nodes[k1].v[iy];
1718 x4 = nodes[k2].v[ix];
1719 y4 = nodes[k2].v[iy];
1720 d1 = a1*x3 + b1*y3 + c1;
1721 d2 = a1*x4 + b1*y4 + c1;
1722 if (d1 > del && d2 > del) continue;
1723 if (d1 < -del && d2 < -del) continue;
1725 findABC(x3, y3, x4, y4, a2, b2, c2);
1726 d1 = a2*x1 + b2*y1 + c2;
1727 d2 = a2*x2 + b2*y2 + c2;
1728 if (d1 > del && d2 > del) continue;
1729 if (d1 < -del && d2 < -del) continue;
1737 void BooleanProcessor::mergeContours(int ix, int iy, int kext, int kint)
1738 /***********************************************************************
1740 * Name: BooleanProcessor::mergeContours Date: 06.03.00 *
1741 * Author: E.Chernyaev Revised: *
1743 * Function: Attemp to merge internal contour with external one *
1745 ***********************************************************************/
1747 int i1ext, i2ext, i1int, i2int, i, k[6];
1750 // L O O P A L O N G E X T E R N A L C O N T O U R
1752 i1ext = external_contours[kext];
1754 i2ext = edges[i1ext].inext;
1755 if (i2ext == 0) i2ext = external_contours[kext];
1756 k[0] = edges[i1ext].i1;
1757 k[1] = edges[i1ext].i2;
1758 k[2] = edges[i2ext].i2;
1759 for (i=0; i<3; i++) {
1760 x[i] = nodes[k[i]].v[ix];
1761 y[i] = nodes[k[i]].v[iy];
1764 // L O O P A L O N G I N T E R N A L C O N T O U R
1766 i1int = internal_contours[kint];
1768 i2int = edges[i1int].inext;
1769 if (i2int == 0) i2int = internal_contours[kint];
1770 k[3] = edges[i1int].i1;
1771 k[4] = edges[i1int].i2;
1772 k[5] = edges[i2int].i2;
1773 for (i=3; i<6; i++) {
1774 x[i] = nodes[k[i]].v[ix];
1775 y[i] = nodes[k[i]].v[iy];
1778 // T E S T L I N E K1 - K4
1779 // I F O K T H E N M E R G E C O N T O U R S
1781 if (checkDirection(x, y) == 0) {
1782 if (checkIntersection(ix, iy, k[1], k[4]) == 0) {
1785 if (edges[i].inext == 0) {
1786 edges[i].inext = internal_contours[kint];
1787 internal_contours[kint] = 0;
1793 i = edges[i1int].iface1;
1794 edges.push_back(ExtEdge(k[1], k[4], i, -1*(int(edges.size())+1), -1));
1795 edges.back().inext = i2int;
1796 edges.push_back(ExtEdge(k[4], k[1], i, -1*(int(edges.size())-1), -1));
1797 edges.back().inext = edges[i1ext].inext;
1798 edges[i1ext].inext = int(edges.size())-2;
1799 edges[i1int].inext = int(edges.size())-1;
1803 i1int = edges[i1int].inext;
1805 i1ext = edges[i1ext].inext;
1810 BooleanProcessor::checkTriangle(int iedge1, int iedge2, int ix, int iy) const
1811 /***********************************************************************
1813 * Name: BooleanProcessor::checkTriangle Date: 08.03.00 *
1814 * Author: E.Chernyaev Revised: *
1816 * Function: Check triangle for correctness *
1818 ***********************************************************************/
1824 k[0] = edges[iedge1].i1;
1825 k[1] = edges[iedge1].i2;
1826 k[2] = edges[iedge2].i2;
1827 for (int i=0; i<3; i++) {
1828 x[i] = nodes[k[i]].v[ix];
1829 y[i] = nodes[k[i]].v[iy];
1832 // C H E C K P R I N C I P A L C O R R E C T N E S S
1834 findABC(x[2], y[2], x[0], y[0], a1, b1, c1);
1835 if (a1*x[1]+b1*y[1]+c1 <= 0.1*del) return true;
1837 // C H E C K T H A T T H E R E I S N O P O I N T S I N S I D E
1840 double a2, b2, c2, a3, b3, c3;
1842 findABC(x[0], y[0], x[1], y[1], a2, b2, c2);
1843 findABC(x[1], y[1], x[2], y[2], a3, b3, c3);
1846 iedge = edges[iedge].inext;
1847 if (edges[iedge].inext == iedge1) return false;
1848 inode = edges[iedge].i2;
1849 if (inode == k[0]) continue;
1850 if (inode == k[1]) continue;
1851 if (inode == k[2]) continue;
1852 x[1] = nodes[inode].v[ix];
1853 y[1] = nodes[inode].v[iy];
1854 if (a1*x[1]+b1*y[1]+c1 < -0.1*del) continue;
1855 if (a2*x[1]+b2*y[1]+c2 < -0.1*del) continue;
1856 if (a3*x[1]+b3*y[1]+c3 < -0.1*del) continue;
1862 bool BooleanProcessor::triangulateContour(int ix, int iy, int ihead)
1863 /***********************************************************************
1865 * Name: BooleanProcessor::triangulateContour Date: 06.03.00 *
1866 * Author: E.Chernyaev Revised: *
1868 * Function: Triangulate external contour *
1870 ***********************************************************************/
1873 //int draw_flag = 0;
1874 //if (draw_flag) draw_contour(5, 3, ihead);
1876 // C L O S E C O N T O U R
1878 int ipnext = ihead, nnode = 1;
1880 if (edges[ipnext].inext > 0) {
1881 ipnext = edges[ipnext].inext;
1884 edges[ipnext].inext = ihead;
1889 // L O O P A L O N G C O N T O U R
1891 //std::cerr << "debug : contour : begin : =================" << std::endl;
1894 int iedge1, iedge2, iedge3, istart = 0;
1896 iedge1 = edges[ipnext].inext;
1897 iedge2 = edges[iedge1].inext;
1899 //std::cerr << "debug :"
1900 // << " ipnext " << ipnext
1901 // << " iedge1 " << iedge1
1902 // << " iedge2 " << iedge2
1903 // << " : istart " << istart
1904 // << " , nnode " << nnode
1910 iedge3 = edges[iedge2].inext;
1911 edges[iedge1].iface1 = int(faces.size());
1912 edges[iedge2].iface1 = int(faces.size());
1913 edges[iedge3].iface1 = int(faces.size());
1914 edges[iedge3].inext = 0;
1915 faces.push_back(ExtFace(edges,0)); //G.Barrand : ok ?
1916 faces.back().iold = iedge1;
1917 faces.back().inew = ORIGINAL_FACE;
1919 //if (draw_flag) draw_contour(4, 2, iedge1);
1923 }else if (istart == iedge1) {
1924 //G.Barrand processor_error = 1; //use returned status.
1925 #ifdef TOOLS_HEP_BP_OUT_ERR
1927 << "BooleanProcessor::triangulateContour : "
1928 << "could not generate a triangle (infinite loop)"
1931 return false; //G.Barrand
1934 // C H E C K C O R E C T N E S S O F T H E T R I A N G L E
1936 if(checkTriangle(iedge1,iedge2,ix,iy)) {
1937 ipnext = edges[ipnext].inext;
1941 // M O D I F Y C O N T O U R
1943 int i1 = edges[iedge1].i1;
1944 int i3 = edges[iedge2].i2;
1945 int iface1 = edges[iedge1].iface1;
1946 int iface2 = int(faces.size());
1948 edges[ipnext].inext = int(edges.size());
1949 edges.push_back(ExtEdge(i1, i3, iface1, -1*(int(edges.size())+1), -1));
1950 edges.back().inext = edges[iedge2].inext;
1952 // A D D N E W T R I A N G L E T O T H E L I S T
1954 edges[iedge2].inext = int(edges.size());
1955 edges.push_back(ExtEdge(i3, i1, iface2, -1*(int(edges.size())-1), -1));
1956 faces.push_back(ExtFace(edges,0)); //G.Barrand : ok ?
1957 faces.back().iold = iedge1;
1958 faces.back().inew = ORIGINAL_FACE;
1959 edges[iedge1].iface1 = iface2;
1960 edges[iedge2].iface1 = iface2;
1961 ipnext = edges[ipnext].inext;
1965 //if (draw_flag) draw_contour(4, 2, iedge1);
1973 bool BooleanProcessor::modifyReference(int iface, int i1, int i2, int iref)
1974 /***********************************************************************
1976 * Name: BooleanProcessor::modifyReference Date: 13.03.00 *
1977 * Author: E.Chernyaev Revised: *
1979 * Function: Modify reference to the neighbouring face *
1981 ***********************************************************************/
1983 int iedge = faces[iface].iold;
1985 if (edges[iedge].i1 == i2 && edges[iedge].i2 == i1) {
1986 edges[iedge].iface2 = iref;
1989 iedge = edges[iedge].inext;
1991 //G.Barrand : processor_error = 1;
1992 #ifdef TOOLS_HEP_BP_OUT_ERR
1994 << "BooleanProcessor::modifyReference : could not find the edge, "
1995 << "iface=" << iface << ", i1,i2=" << i1 << "," << i2 << ", iref=" << iref
1998 return false; //G.Barrand
2002 bool BooleanProcessor::triangulateFace(int iface)
2003 /***********************************************************************
2005 * Name: BooleanProcessor::triangulateFace Date: 02.03.00 *
2006 * Author: E.Chernyaev Revised: *
2008 * Function: Triangulation of an extended face *
2010 ***********************************************************************/
2013 // F I N D M A X C O M P O N E N T O F T H E N O R M A L
2016 //HVNormal3D normal = faces[iface].plane.normal();
2017 const HVNormal3D& normal = faces[iface].plane.normal();
2020 //G.Barrand : if (std::abs(normal[1]) > std::abs(normal[iz])) iz = 1;
2021 //G.Barrand : if (std::abs(normal[2]) > std::abs(normal[iz])) iz = 2;
2022 if (::fabs(normal[1]) > ::fabs(normal[iz])) iz = 1; //G.Barrand
2023 if (::fabs(normal[2]) > ::fabs(normal[iz])) iz = 2; //G.Barrand
2024 if (normal[iz] > 0) {
2025 ix = (iz+1)%3; iy = (ix+1)%3;
2027 iy = (iz+1)%3; ix = (iy+1)%3;
2030 // F I L L L I S T S O F C O N T O U R S
2032 external_contours.clear();
2033 internal_contours.clear();
2035 int i1, i2, ifirst, iedge, icontour = faces[iface].iold;
2036 while (icontour > 0) {
2038 ifirst = edges[iedge].i1;
2042 i1 = edges[iedge].i1;
2043 i2 = edges[iedge].i2;
2044 ExtNode& node_1 = nodes[i1];
2045 ExtNode& node_2 = nodes[i2];
2046 z += node_1.v[ix]*node_2.v[iy]-node_2.v[ix]*node_1.v[iy];
2048 iedge = edges[iedge].inext;
2052 external_contours.push_back(icontour);
2053 }else if (z < -del*del) {
2054 internal_contours.push_back(icontour);
2056 //G.Barrand : processor_error = 1; //use returned value.
2057 #ifdef TOOLS_HEP_BP_OUT_ERR
2059 << "BooleanProcessor::triangulateFace : too small contour"
2061 << " del*del " << del*del
2064 return false; //G.Barrand.
2066 icontour = edges[iedge].inext;
2067 edges[iedge].inext = 0;
2071 //G.Barrand : processor_error = 1; //use returned value.
2072 #ifdef TOOLS_HEP_BP_OUT_ERR
2074 << "BooleanProcessor::triangulateFace : broken contour"
2078 //G.Barrand : break;
2084 // G E T R I D O F I N T E R N A L C O N T O U R S
2087 for (kint=0; kint < (int)internal_contours.size(); kint++) {
2088 for (kext=0; kext < (int)external_contours.size(); kext++) {
2089 mergeContours(ix, iy, kext, kint);
2090 if (internal_contours[kint] == 0) break;
2092 if (kext == (int)external_contours.size()) {
2093 //G.Barrand : processor_error = 1; //use returned value.
2094 #ifdef TOOLS_HEP_BP_OUT_ERR
2096 << "BooleanProcessor::triangulateFace : "
2097 << "could not merge internal contour " << kint
2100 return false; //G.Barrand
2104 // T R I A N G U L A T E C O N T O U R S
2106 int nface = int(faces.size());
2107 for (kext=0; kext < (int)external_contours.size(); kext++) {
2108 if(!triangulateContour(ix, iy, external_contours[kext])) {
2109 //G.Barrand : processor_error = 1; //use returned value.
2110 #ifdef TOOLS_HEP_BP_OUT_ERR
2112 << "BooleanProcessor::triangulateFace : "
2113 << "triangulateContour failed."
2116 //break; //G.Barrand : ok ?
2117 //return; //G.Barrand : ok ?
2118 return false; //G.Barrand
2121 faces[iface].inew = UNSUITABLE_FACE;
2123 // M O D I F Y R E F E R E N C E S
2125 for (int ifa=nface; ifa<(int)faces.size(); ifa++) {
2126 iedge = faces[ifa].iold;
2128 if (edges[iedge].iface1 != ifa) {
2129 //G.Barrand : processor_error = 1; //use returned value.
2130 #ifdef TOOLS_HEP_BP_OUT_ERR
2132 << "BooleanProcessor::triangulateFace : wrong reference to itself, "
2133 << "iface=" << ifa << ", iface1=" << edges[iedge].iface1
2136 return false; //G.Barrand
2137 }else if (edges[iedge].iface2 > 0) {
2138 if(!modifyReference(edges[iedge].iface2,
2139 edges[iedge].i1, edges[iedge].i2, ifa)) { //G.Barrand
2140 return false; //G.Barrand
2142 }else if (edges[iedge].iface2 < 0) {
2143 edges[iedge].iface2 = edges[-edges[iedge].iface2].iface1;
2145 iedge = edges[iedge].inext;
2149 return true; //G.Barrand.
2153 polyhedron BooleanProcessor::createPolyhedron()
2154 /***********************************************************************
2156 * Name: BooleanProcessor::createPolyhedron() Date: 14.03.00 *
2157 * Author: E.Chernyaev Revised: *
2159 * Function: Create polyhedron. *
2161 ***********************************************************************/
2163 int i, iedge, nnode = 0, nface = 0;
2165 // R E N U M E R A T E N O D E S A N D F A C E S
2167 for (i=1; i<(int)nodes.size(); i++) nodes[i].s = 0;
2169 for (i=1; i<(int)faces.size(); i++) {
2170 if (faces[i].inew == ORIGINAL_FACE) {
2171 faces[i].inew = ++nface;
2172 iedge = faces[i].iold;
2174 nodes[edges[iedge].i1].s = 1;
2175 iedge = edges[iedge].inext;
2182 for (i=1; i<(int)nodes.size(); i++) {
2183 if (nodes[i].s == 1) nodes[i].s = ++nnode;
2186 // A L L O C A T E M E M O R Y
2188 ExtPolyhedron polyhedron;
2189 if (nface == 0) return polyhedron;
2190 polyhedron.AllocateMemory(nnode, nface);
2194 for (i=1; i<(int)nodes.size(); i++) {
2195 if (nodes[i].s != 0) polyhedron.pV[nodes[i].s] = nodes[i].v;
2201 for (i=1; i<(int)faces.size(); i++) {
2202 if (faces[i].inew == 0) continue;
2203 v[3] = f[3] = k = 0;
2204 iedge = faces[i].iold;
2207 #ifdef TOOLS_HEP_BP_VERBOSE
2209 << "BooleanProcessor::createPolyhedron : too many edges"
2214 v[k] = nodes[edges[iedge].i1].s;
2215 if (edges[iedge].ivis < 0) v[k] = -v[k];
2216 f[k] = faces[edges[iedge].iface2].inew;
2217 iedge = edges[iedge].inext;
2221 #ifdef TOOLS_HEP_BP_VERBOSE
2223 << "BooleanProcessor::createPolyhedron : "
2224 << "face has only " << k << " edges"
2228 //polyhedron.pF[faces[i].inew] =
2229 // SbFacet(v[0],f[0], v[1],f[1], v[2],f[2], v[3],f[3]);
2230 polyhedron.pF[faces[i].inew].set( //G.Barrand
2231 v[0],f[0], v[1],f[1], v[2],f[2], v[3],f[3]);
2237 //int BooleanProcessor::ishift = 0; //does not work with pure header code.
2238 inline int& BooleanProcessor::get_shift() { //& not thread safe.
2239 static int s_ishift;
2243 inline void BooleanProcessor::set_shift(int a_shift) {
2244 get_shift() = a_shift;
2246 inline void BooleanProcessor::inc_shift() {
2247 int i = get_shift();
2249 if(i>=get_num_shift()) i = 0;
2253 inline int BooleanProcessor::get_num_shift() { return 8;}
2258 bool BooleanProcessor::inc_try_count(
2259 #ifdef TOOLS_HEP_BP_VERBOSE
2260 int a_op,const polyhedron& a,const polyhedron& b
2262 int,const polyhedron&,const polyhedron&
2265 if(a_try_count>get_num_shift()) {
2266 #ifdef TOOLS_HEP_BP_VERBOSE
2267 std::cerr << "BooleanProcessor: "
2268 << " all shifts tried. Boolean operation (" << a_op << ") failure."
2269 << " a name \"" << a.getName() << "\""
2270 << " b name \"" << b.getName() << "\""
2273 return false; //stop
2276 #ifdef TOOLS_HEP_BP_VERBOSE
2278 << "BooleanProcessor::execute : try another tilt..."
2287 polyhedron BooleanProcessor::execute(int op,
2288 const polyhedron & a,
2289 const polyhedron & b,
2290 int& a_err) //G.Barrand
2291 /***********************************************************************
2293 * Name: BooleanProcessor::execute Date: 10.12.99 *
2294 * Author: E.Chernyaev Revised: *
2296 * Function: Execute boolean operation. *
2298 ***********************************************************************/
2300 //static int ishift = 0; //G.Barrand
2301 //static double shift[8][3] = {
2302 static double shift[/*NUM_SHIFT*/ 8][3] = { //G.Barrand
2314 //std::cerr << "BooleanProcessor::execute : ++++++++++++++++++++++"
2319 // I N I T I A T E P R O C E S S O R
2322 nodes.clear(); nodes.push_back(CRAZY_POINT());
2323 edges.clear(); edges.push_back(ExtEdge());
2324 faces.clear(); faces.push_back(ExtFace(edges,0)); //G.Barrand : ok ?
2326 // T A K E P O L Y H E D R A
2328 ifaces1 = int(faces.size());
2329 if(!takePolyhedron(a,0,0,0)){ //G.Barrand : use returned value.
2330 // corrapted polyhedron
2331 #ifdef TOOLS_HEP_BP_OUT_ERR
2333 << "BooleanProcessor: a corrapted input polyhedron"
2336 a_err = 1; //G.Barrand
2337 return polyhedron();
2340 ifaces2 = int(faces.size());
2341 if(!takePolyhedron(b,0,0,0)){
2342 // corrapted polyhedron
2343 #ifdef TOOLS_HEP_BP_OUT_ERR
2345 << "BooleanProcessor: b corrapted input polyhedron"
2348 a_err = 1; //G.Barrand
2349 return polyhedron();
2352 if (ifaces1 == ifaces2) { // a is empty
2353 a_err = 0; //G.Barrand
2354 switch (operation) {
2357 case OP_INTERSECTION:
2358 #ifdef TOOLS_HEP_BP_VERBOSE
2360 << "BooleanProcessor: intersection with empty polyhedron"
2363 return polyhedron();
2364 case OP_SUBTRACTION:
2365 #ifdef TOOLS_HEP_BP_VERBOSE
2367 << "BooleanProcessor: subtraction from empty polyhedron"
2370 return polyhedron();
2373 if (ifaces2 == (int)faces.size()) { // b is empty
2374 a_err = 0; //G.Barrand
2375 switch (operation) {
2378 case OP_INTERSECTION:
2379 #ifdef TOOLS_HEP_BP_VERBOSE
2381 << "BooleanProcessor: intersection with empty polyhedron"
2384 return polyhedron();
2385 case OP_SUBTRACTION:
2390 // S E T I N I T I A L M I N - M A X A N D T O L E R A N C E
2394 // W O R K A R O U N D T O A V O I D I E A N D E E
2397 while(true) { //G.Barrand
2399 double ddxx = del*shift[get_shift()][0];
2400 double ddyy = del*shift[get_shift()][1];
2401 double ddzz = del*shift[get_shift()][2];
2402 //ishift++; if (ishift == get_num_shift()) ishift = 0;
2406 nodes.clear(); nodes.push_back(CRAZY_POINT());
2407 edges.clear(); edges.push_back(ExtEdge());
2408 faces.clear(); faces.push_back(ExtFace(edges,0)); //G.Barrand : ok ?
2410 ifaces1 = int(faces.size());
2411 if(!takePolyhedron(a,0,0,0)) {
2412 #ifdef TOOLS_HEP_BP_OUT_ERR
2414 << "BooleanProcessor: shifted a corrapted input polyhedron"
2417 if(!inc_try_count(op,a,b,try_count)) {a_err = 1;return a;}
2418 continue; //try another shift.
2421 ifaces2 = int(faces.size());
2422 if(!takePolyhedron(b,ddxx,ddyy,ddzz)){
2423 #ifdef TOOLS_HEP_BP_OUT_ERR
2425 << "BooleanProcessor: shifted b corrapted input polyhedron"
2428 if(!inc_try_count(op,a,b,try_count)) {a_err = 1;return a;}
2429 continue; //try another shift.
2434 // P R E S E L E C T O U T S I D E F A C E S
2437 selectOutsideFaces(ifaces1, iout1);
2438 selectOutsideFaces(ifaces2, iout2);
2440 // P R E S E L E C T N O I N T E R S E C T I O N F A C E S
2444 if (iout1 != 0 || iout2 != 0) {
2448 selectOutsideFaces(ifaces1, iunk1);
2449 selectOutsideFaces(ifaces2, iunk2);
2450 if (iunk1 == ifa1 && iunk2 == ifa2) break;
2455 // F I N D N E W E D G E S
2457 {int processor_error = 0; //G.Barrand
2458 if (ifaces1 != 0 && ifaces2 != 0 ) {
2463 if(!testFaceVsFace(ifa1, ifa2)) {
2464 processor_error = 1; //G.Barrand
2467 ifa2 = faces[ifa2].inext;
2469 if(processor_error) break; //G.Barrand
2470 ifa1 = faces[ifa1].inext;
2473 if (processor_error) {
2475 if(!inc_try_count(op,a,b,try_count)) {a_err = 1;return a;}
2476 continue; //try another shift.
2479 // C O N S T R U C T N E W F A C E S
2481 if(!assembleNewFaces((operation == OP_INTERSECTION) ? 1 : 0, ifaces1)){
2484 if(!inc_try_count(op,a,b,try_count)) {a_err = 1;return a;}
2485 continue; //try another shift.
2487 if(!assembleNewFaces((operation == OP_UNION) ? 0 : 1, ifaces2)){
2490 if(!inc_try_count(op,a,b,try_count)) {a_err = 1;return a;}
2491 continue; //try another shift.
2493 // A S S E M B L E S U I T A B L E F A C E S
2495 if(!initiateLists()) { //G.Barrand : return status.
2496 #ifdef TOOLS_HEP_BP_OUT_ERR
2498 << "BooleanProcessor: initiateLists failed."
2501 if(!inc_try_count(op,a,b,try_count)) {a_err = 1;return a;}
2502 continue; //try another shift.
2505 {int processor_error = 0;
2507 if(!assemblePolyhedra()) { //G.Barrand : handle returned value.
2508 processor_error = 1;
2509 #ifdef TOOLS_HEP_BP_OUT_ERR
2511 << "BooleanProcessor: assemblePolyhedra failed."
2516 if (unknown_faces.front() != 0) {
2517 processor_error = 1;
2518 #ifdef TOOLS_HEP_BP_OUT_ERR
2520 << "BooleanProcessor::execute : unknown faces !!!"
2527 if (processor_error) {
2529 if(!inc_try_count(op,a,b,try_count)) {a_err = 1;return a;}
2530 continue; //try another shift.
2533 // T R I A N G U L A T E A C C E P T E D F A C E S
2535 {int processor_error = 0;
2536 ifa1 = result_faces.front();
2539 ifa1 = faces[ifa2].inext;
2540 if(faces[ifa2].inew == NEW_FACE) {
2541 if(!triangulateFace(ifa2)) { //G.Barrand : use returned status.
2542 processor_error = 1;
2547 if (processor_error) {
2549 if(!inc_try_count(op,a,b,try_count)) {a_err = 1;return a;}
2550 continue; //try another shift.
2553 #ifdef TOOLS_HEP_BP_VERBOSE
2556 << "BooleanProcessor::execute : had converged."
2562 } //G.Barrand : end while shift.
2564 // C R E A T E P O L Y H E D R O N
2567 return createPolyhedron();
2571 //#include <cfortran.h>
2574 //void BooleanProcessor::draw()
2575 /***********************************************************************
2577 * Name: BooleanProcessor::draw Date: 10.12.99 *
2578 * Author: E.Chernyaev Revised: *
2582 ***********************************************************************/
2586 int icol, i1, i2, iedge, iface, ilist[4];
2594 for (int i=0; i<4; i++) {
2596 if (i == 0) cout << "========= Ifaces_1" << endl;
2597 if (i == 1) cout << "========= Ifaces_2" << endl;
2598 if (i == 2) cout << "========= Iout_1" << endl;
2599 if (i == 3) cout << "========= Iout_2" << endl;
2605 cout << "iface = " << iface << endl;
2606 cout << "--- iold" << endl;
2608 iedge = faces[iface].iold;
2613 cout << " iegde = " << iedge
2614 << " i1,i2 =" << edges[iedge].i1 << "," << edges[iedge].i2
2615 << " iface1,iface2 = "
2616 << edges[iedge].iface1 << "," << edges[iedge].iface2
2619 i1 = edges[iedge].i1;
2620 p1[0] = nodes[i1].v.x();
2621 p1[1] = nodes[i1].v.y();
2622 p1[2] = nodes[i1].v.z();
2624 i2 = edges[iedge].i2;
2625 p2[0] = nodes[i2].v.x();
2626 p2[1] = nodes[i2].v.y();
2627 p2[2] = nodes[i2].v.z();
2629 // icol = (edges[iedge].ivis > 0) ? 1 : 2;
2630 IHZLIN(icol,p1[0],p1[1],p1[2], p2[0],p2[1],p2[2]);
2631 iedge = edges[iedge].inext;
2634 cout << "--- inew" << endl;
2636 iedge = faces[iface].inew;
2641 cout << " iegde = " << iedge
2642 << " i1,i2 =" << edges[iedge].i1 << "," << edges[iedge].i2
2643 << " iface1,iface2 = "
2644 << edges[iedge].iface1 << "," << edges[iedge].iface2
2647 i1 = edges[iedge].i1;
2648 p1[0] = nodes[i1].v.x();
2649 p1[1] = nodes[i1].v.y();
2650 p1[2] = nodes[i1].v.z();
2652 i2 = edges[iedge].i2;
2653 p2[0] = nodes[i2].v.x();
2654 p2[1] = nodes[i2].v.y();
2655 p2[2] = nodes[i2].v.z();
2657 // icol = (edges[iedge].ivis > 0) ? 1 : 2;
2658 IHZLIN(icol,p1[0],p1[1],p1[2], p2[0],p2[1],p2[2]);
2659 iedge = edges[iedge].inext;
2661 iface = faces[iface].inext;
2674 //--------------------------------------------------------------------
2676 BooleanProcessor::draw_edge(int icol, int iedge) {
2680 i1 = edges[iedge].i1;
2681 p1[0] = nodes[i1].v.x();
2682 p1[1] = nodes[i1].v.y();
2683 p1[2] = nodes[i1].v.z();
2685 i2 = edges[iedge].i2;
2686 p2[0] = nodes[i2].v.x();
2687 p2[1] = nodes[i2].v.y();
2688 p2[2] = nodes[i2].v.z();
2690 IHZLIN(icol,p1[0],p1[1],p1[2], p2[0],p2[1],p2[2]);
2693 //--------------------------------------------------------------------
2695 BooleanProcessor::draw_contour(int i1col, int i2col, int ihead) {
2699 icol = (edges[iedge].ivis > 0) ? i1col : i2col;
2700 draw_edge(icol, iedge);
2701 iedge = edges[iedge].inext;
2711 //--------------------------------------------------------------------
2713 BooleanProcessor::print_face(int iface) {
2715 cout << "\n====== Face N " << iface << endl;
2716 cout << "iedges[4] = "
2717 << faces[iface].iedges[0] << ", "
2718 << faces[iface].iedges[1] << ", "
2719 << faces[iface].iedges[2] << ", "
2720 << faces[iface].iedges[3] << endl;
2721 cout << "rmin[3] = "
2722 << faces[iface].rmin[0] << ", "
2723 << faces[iface].rmin[1] << ", "
2724 << faces[iface].rmin[2] << endl;
2725 cout << "rmax[3] = "
2726 << faces[iface].rmax[0] << ", "
2727 << faces[iface].rmax[1] << ", "
2728 << faces[iface].rmax[2] << endl;
2729 cout << "iprev,inext = "
2730 << faces[iface].iprev << ", "
2731 << faces[iface].inext << endl;
2732 cout << "iold = " << faces[iface].iold << endl;
2733 for(int i = faces[iface].iold; i != 0;) {
2735 i = edges[abs(i)].inext;
2739 switch (faces[iface].inew) {
2741 cout << "UNKNOWN_FACE" << endl;
2744 cout << "ORIGINAL_FACE" << endl;
2747 cout << "NEW_FACE" << endl;
2749 case UNSUITABLE_FACE:
2750 cout << "UNSUITABLE_FACE" << endl;
2752 case DEFECTIVE_FACE:
2753 cout << "DEFECTIVE_FACE" << endl;
2756 cout << faces[iface].inew << endl;
2757 for(int k = faces[iface].inew; k != 0;) {
2759 k = edges[abs(k)].inext;
2764 //--------------------------------------------------------------------
2766 BooleanProcessor::print_edge(int iedge) {
2767 cout << "==== Edge N " << iedge << endl;
2768 int i = std::abs(iedge);
2769 int i1 = edges[i].i1;
2770 int i2 = edges[i].i2;
2771 cout << "node[" << i1 << "] = "
2772 << nodes[i1].v.x() << ", "
2773 << nodes[i1].v.y() << ", "
2774 << nodes[i1].v.z() << endl;
2776 cout << "node[" << i2 << "] = "
2777 << nodes[i2].v.x() << ", "
2778 << nodes[i2].v.y() << ", "
2779 << nodes[i2].v.z() << endl;
2781 cout << "iface1,iface2,ivis,inext = "
2782 << edges[i].iface1 << ", "
2783 << edges[i].iface2 << ", "
2784 << edges[i].ivis << ", "
2785 << edges[i].inext << endl;
2789 inline void BooleanProcessor::dump(std::ostream& a_out) {//G.Barrand
2790 size_t number = nodes.size();
2791 a_out << "nodes : " << number << std::endl;
2792 for(size_t index=0;index<number;index++) {
2793 const ExtNode& node = nodes[index];
2794 a_out << " " << index
2795 << " x = " << node.v[0]
2796 << " y = " << node.v[1]
2797 << " z = " << node.v[2]