1 // Created on: 1997-03-03
2 // Created by: Jean-Pierre COMBE
3 // Copyright (c) 1997-1999 Matra Datavision
4 // Copyright (c) 1999-2012 OPEN CASCADE SAS
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
23 #include <Standard_NotImplemented.hxx>
25 #include <AIS_IdenticRelation.ixx>
28 #include <AIS_Shape.hxx>
29 #include <AIS_Drawer.hxx>
31 #include <BRep_Tool.hxx>
33 #include <DsgPrs_IdenticPresentation.hxx>
37 #include <Geom_Circle.hxx>
38 #include <Geom_Line.hxx>
39 #include <Geom_Plane.hxx>
40 #include <Geom_TrimmedCurve.hxx>
42 #include <Precision.hxx>
44 #include <Prs3d_Drawer.hxx>
45 #include <Prs3d_LineAspect.hxx>
47 #include <Select3D_SensitiveCurve.hxx>
48 #include <Select3D_SensitiveSegment.hxx>
49 #include <SelectMgr_EntityOwner.hxx>
51 #include <TColStd_ListIteratorOfListOfTransient.hxx>
53 #include <StdPrs_WFDeflectionShape.hxx>
55 #include <TCollection_ExtendedString.hxx>
60 #include <TopoDS_Edge.hxx>
61 #include <TopoDS_Vertex.hxx>
62 #include <TopoDS_Wire.hxx>
63 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
64 #include <TopTools_ListIteratorOfListOfShape.hxx>
72 #include <Geom_Ellipse.hxx>
73 #include <GeomAPI_ProjectPointOnCurve.hxx>
75 static Standard_Real Modulo2PI(const Standard_Real ANGLE)
77 if ( ANGLE < 0 ) return Modulo2PI(ANGLE + 2*M_PI);
78 else if ( ANGLE >= 2*M_PI ) return Modulo2PI(ANGLE - 2*M_PI);
82 static Standard_Boolean IsEqual2PI(const Standard_Real angle1,
83 const Standard_Real angle2, const Standard_Real precision)
85 Standard_Real diff = Abs(angle1-angle2);
86 if ( diff < precision ) return Standard_True;
87 else if ( Abs(diff-2*M_PI) < precision ) return Standard_True;
88 return Standard_False;
92 //=======================================================================
94 //purpose : sort an array of parameters <tab1> in increasing order
95 // updates <tab2> and <tab3> according to <tab1>
96 //=======================================================================
97 static void AIS_Sort(Standard_Real tab1[4],
99 Standard_Integer tab3[4])
101 Standard_Boolean found = Standard_True;
102 Standard_Real cur; gp_Pnt cur1; Standard_Integer cur2;
105 found = Standard_False;
106 for (Standard_Integer i=0; i< 3; i++) {
107 if (tab1[i+1] < tab1[i]) {
108 found = Standard_True;
109 cur = tab1[i]; cur1 = tab2[i]; cur2 = tab3[i];
110 tab1[i] = tab1[i+1]; tab2[i] = tab2[i+1]; tab3[i] = tab3[i+1];
111 tab1[i+1] = cur; tab2[i+1] = cur1; tab3[i+1] = cur2;
117 //=======================================================================
118 //function : ConnectedEdges
120 //=======================================================================
121 static Standard_Boolean ConnectedEdges(const TopoDS_Wire& WIRE,
122 const TopoDS_Vertex& V,
126 TopTools_IndexedDataMapOfShapeListOfShape vertexMap;
127 TopExp::MapShapesAndAncestors (WIRE,TopAbs_VERTEX,TopAbs_EDGE,vertexMap);
129 Standard_Boolean found(Standard_False);
130 TopoDS_Vertex theVertex;
131 for (Standard_Integer i=1; i<=vertexMap.Extent() && !found; i++) {
132 if (vertexMap.FindKey(i).IsSame(V)) {
133 theVertex = TopoDS::Vertex(vertexMap.FindKey(i));
134 found = Standard_True;
140 return Standard_False;
143 TopTools_ListIteratorOfListOfShape iterator(vertexMap.FindFromKey(theVertex));
144 if (iterator.More()) {
145 E1 = TopoDS::Edge(iterator.Value());
150 return Standard_False;
153 if (iterator.More()) {
154 E2 = TopoDS::Edge(iterator.Value());
159 return Standard_False;
162 if (iterator.More()) {
165 return Standard_False;
167 return Standard_True;
171 //=======================================================================
172 //function : ComputeAttach
173 //purpose : Compute a point on the arc of <thecirc>
174 // between <aFAttach> and <aSAttach>
175 // corresponding to <aPosition>
176 // Returns result into <aPosition>
177 // Note : This function is to be used only in the case of circles.
178 // The <aPosition> parameter is in/out.
179 //=======================================================================
180 static Standard_Boolean ComputeAttach(const gp_Circ& thecirc,
181 const gp_Pnt& aFAttach,
182 const gp_Pnt& aSAttach,
185 gp_Pnt curpos = aPosition;
187 // Case of confusion between the current position and the center
188 // of the circle -> we move the current position
189 Standard_Real confusion (Precision::Confusion());
190 gp_Pnt aCenter = thecirc.Location();
191 if ( aCenter.Distance(curpos) <= confusion )
193 gp_Vec vprec(aCenter, aFAttach);
195 curpos.Translate(vprec*1e-5);
198 Standard_Real pcurpos = ElCLib::Parameter(thecirc,curpos);
199 Standard_Real pFAttach = ElCLib::Parameter(thecirc,aFAttach);
200 Standard_Real pSAttach = ElCLib::Parameter(thecirc,aSAttach);
202 Standard_Real pSAttachM = pSAttach;
203 Standard_Real deltap = pSAttachM - pFAttach;
207 pSAttachM += 2 * M_PI;
209 pSAttachM -= pFAttach;
211 Standard_Real pmiddleout = pSAttachM/2.0 + M_PI;
213 Standard_Real pcurpos1 = pcurpos;
214 // define where curpos lays
215 if ( pcurpos1 < pFAttach )
217 pcurpos1 = pcurpos1 + 2 * M_PI - pFAttach;
218 if ( pcurpos1 > pSAttachM ) // out
220 if ( pcurpos1 > pmiddleout ) pcurpos = pFAttach;
221 else pcurpos = pSAttach;
224 else if ( pcurpos1 > (pFAttach + deltap) ) // out
226 pcurpos1 -= pFAttach;
227 if ( pcurpos1 > pmiddleout ) pcurpos = pFAttach;
228 else pcurpos = pSAttach;
231 aPosition = ElCLib::Value(pcurpos,thecirc);
232 return Standard_True;
235 //=======================================================================
236 //function : ComputeAttach
237 //purpose : Compute a point on the arc of ellipse <theEll>
238 // between <aFAttach> and <aSAttach>
239 // corresponding to <aPosition>
240 // Returns result into <aPosition>
241 // Note : This function is to be used only in the case of ellipses.
242 // The <aPosition> parameter is in/out.
243 //=======================================================================
244 static Standard_Boolean ComputeAttach(const gp_Elips& theEll,
245 const gp_Pnt& aFAttach,
246 const gp_Pnt& aSAttach,
249 gp_Pnt curpos = aPosition;
251 // Case of confusion between the current position and the center
252 // of the circle -> we move the current position
253 Standard_Real confusion (Precision::Confusion());
254 gp_Pnt aCenter = theEll.Location();
255 if ( aCenter.Distance(curpos) <= confusion )
257 gp_Vec vprec(aCenter, aFAttach);
259 curpos.Translate(vprec*1e-5);
262 // for ellipses it's not good Standard_Real pcurpos = ElCLib::Parameter(theEll,curpos);
263 Handle(Geom_Ellipse) theEllg = new Geom_Ellipse(theEll);
264 GeomAPI_ProjectPointOnCurve aProj (curpos, theEllg);
265 Standard_Real pcurpos = aProj.LowerDistanceParameter();
267 Standard_Real pFAttach = ElCLib::Parameter(theEll,aFAttach);
268 Standard_Real pSAttach = ElCLib::Parameter(theEll,aSAttach);
270 Standard_Real pSAttachM = pSAttach;
271 Standard_Real deltap = pSAttachM - pFAttach;
275 pSAttachM += 2 * M_PI;
277 pSAttachM -= pFAttach;
279 Standard_Real pmiddleout = pSAttachM/2.0 + M_PI;
281 Standard_Real pcurpos1 = pcurpos;
282 // define where curpos lays
283 if ( pcurpos1 < pFAttach )
285 pcurpos1 = pcurpos1 + 2 * M_PI - pFAttach;
286 if ( pcurpos1 > pSAttachM ) // out
288 if ( pcurpos1 > pmiddleout ) pcurpos = pFAttach;
289 else pcurpos = pSAttach;
292 else if ( pcurpos1 > (pFAttach + deltap) ) // out
294 pcurpos1 -= pFAttach;
295 if ( pcurpos1 > pmiddleout ) pcurpos = pFAttach;
296 else pcurpos = pSAttach;
299 aPosition = ElCLib::Value(pcurpos,theEll);
300 return Standard_True;
302 // jfa 16/10/2000 end
304 //=======================================================================
305 //function : AIS_IdenticRelation
307 //=======================================================================
308 AIS_IdenticRelation::AIS_IdenticRelation(const TopoDS_Shape& FirstShape,
309 const TopoDS_Shape& SecondShape,
310 const Handle(Geom_Plane)& aPlane)
311 :isCircle(Standard_False)
313 myFShape = FirstShape;
314 mySShape = SecondShape;
318 //=======================================================================
321 //=======================================================================
322 void AIS_IdenticRelation::Compute(const Handle(PrsMgr_PresentationManager3d)&,
323 const Handle(Prs3d_Presentation)& aprs,
324 const Standard_Integer)
328 switch ( myFShape.ShapeType() ) {
332 switch ( mySShape.ShapeType() ) {
335 ComputeTwoVerticesPresentation(aprs);
340 ComputeOneEdgeOVertexPresentation(aprs);
351 switch ( mySShape.ShapeType() ) {
354 ComputeOneEdgeOVertexPresentation(aprs);
359 ComputeTwoEdgesPresentation(aprs);
371 //=======================================================================
374 //=======================================================================
375 void AIS_IdenticRelation::Compute(const Handle(Prs3d_Projector)& aProjector,
376 const Handle(Prs3d_Presentation)& aPresentation)
378 // Standard_NotImplemented::Raise("AIS_IdenticRelation::Compute(const Handle(Prs3d_Projector)&,const Handle(Prs3d_Presentation)&)");
379 PrsMgr_PresentableObject::Compute( aProjector , aPresentation ) ;
382 //=======================================================================
385 //=======================================================================
386 void AIS_IdenticRelation::Compute(const Handle(PrsMgr_PresentationManager2d)& aPresentationManager2d,
387 const Handle(Graphic2d_GraphicObject)& aGraphicObject,
388 const Standard_Integer anInteger)
390 // Standard_NotImplemented::Raise("AIS_IdenticRelation::Compute(const Handle(PrsMgr_PresentationManager2d)&,const Handle(Graphic2d_GraphicObject)&,const Standard_Integer)");
391 PrsMgr_PresentableObject::Compute( aPresentationManager2d ,aGraphicObject,anInteger) ;
394 void AIS_IdenticRelation::Compute(const Handle_Prs3d_Projector& aProjector, const Handle_Geom_Transformation& aTransformation, const Handle_Prs3d_Presentation& aPresentation)
396 // Standard_NotImplemented::Raise("AIS_IdenticRelation::Compute(const Handle_Prs3d_Projector&, const Handle_Geom_Transformation&, const Handle_Prs3d_Presentation&)");
397 PrsMgr_PresentableObject::Compute( aProjector , aTransformation , aPresentation ) ;
400 //=======================================================================
401 //function : ComputeSelection
402 //purpose : function used to compute the selection associated to the
403 // "identic" presentation
404 // note : if we are in the case of lines, we create a segment between
405 // myFAttach and mySAttach. In the case of Circles, we create
406 // an arc of circle between the sames points. We Add a segment
407 // to link Position to its projection on the curve described
409 //=======================================================================
411 void AIS_IdenticRelation::ComputeSelection(const Handle(SelectMgr_Selection)& aSelection,
412 const Standard_Integer)
414 Handle(SelectMgr_EntityOwner) own = new SelectMgr_EntityOwner(this,7);
416 Handle(Select3D_SensitiveSegment) seg;
417 // attachement point of the segment linking position to the curve
419 Standard_Real confusion (Precision::Confusion());
421 if ( myFAttach.IsEqual(mySAttach, confusion) )
428 if ( myFShape.ShapeType() == TopAbs_EDGE )
430 Handle(Geom_Curve) curv1,curv2;
431 gp_Pnt firstp1,lastp1,firstp2,lastp2;
432 Standard_Boolean isInfinite1,isInfinite2;
433 Handle(Geom_Curve) extCurv;
434 if ( !AIS::ComputeGeometry(TopoDS::Edge(myFShape),TopoDS::Edge(mySShape),
435 myExtShape,curv1,curv2,
436 firstp1,lastp1,firstp2,lastp2,
437 extCurv,isInfinite1,isInfinite2,myPlane) ) return;
439 if ( isCircle ) // case of Circles
441 Handle(Geom_Circle) thecirc = (Handle(Geom_Circle)&) curv1;
442 Standard_Real udeb = ElCLib::Parameter(thecirc->Circ(),myFAttach);
443 Standard_Real ufin = ElCLib::Parameter(thecirc->Circ(),mySAttach);
444 Handle(Geom_TrimmedCurve) thecu = new Geom_TrimmedCurve(thecirc,udeb,ufin);
446 Handle(Select3D_SensitiveCurve) scurv = new Select3D_SensitiveCurve(own, thecu);
447 aSelection->Add(scurv);
450 ComputeAttach(thecirc->Circ(),myFAttach,mySAttach,attach);
452 else if ( curv1->IsInstance(STANDARD_TYPE(Geom_Ellipse)) ) // case of ellipses
454 Handle(Geom_Ellipse) theEll = (Handle(Geom_Ellipse)&) curv1;
456 Standard_Real udeb = ElCLib::Parameter(theEll->Elips(),myFAttach);
457 Standard_Real ufin = ElCLib::Parameter(theEll->Elips(),mySAttach);
458 Handle(Geom_TrimmedCurve) thecu = new Geom_TrimmedCurve(theEll,udeb,ufin);
460 Handle(Select3D_SensitiveCurve) scurv = new Select3D_SensitiveCurve(own, thecu);
461 aSelection->Add(scurv);
464 ComputeAttach(theEll->Elips(),myFAttach,mySAttach,attach);
466 else if ( curv1->IsInstance(STANDARD_TYPE(Geom_Line)) ) // case of Lines
468 seg = new Select3D_SensitiveSegment(own, myFAttach, mySAttach);
469 aSelection->Add(seg);
471 //attach = projection of Position() on the curve;
472 gp_Vec v1 (myFAttach, mySAttach);
473 gp_Vec v2 (myFAttach, myPosition);
474 if ( v1.IsParallel(v2, Precision::Angular()) )
480 gp_Lin ll (myFAttach, gp_Dir(v1));
481 attach = ElCLib::Value(ElCLib::Parameter(ll,myPosition), ll);
486 // else if ( myFShape.ShapeType() == TopAbs_VERTEX )
489 // jfa 24/10/2000 end
492 // Creation of the segment linking the attachement point with the
494 if ( !attach.IsEqual(myPosition, confusion) )
496 seg = new Select3D_SensitiveSegment(own, attach, myPosition);
497 aSelection->Add(seg);
501 //=======================================================================
502 //function : ComputeTwoEdgesPresentation
504 //=======================================================================
505 void AIS_IdenticRelation::ComputeTwoEdgesPresentation(const Handle(Prs3d_Presentation)& aPrs)
507 Handle(Geom_Curve) curv1,curv2;
508 gp_Pnt firstp1,lastp1,firstp2,lastp2;
509 Standard_Boolean isInfinite1,isInfinite2;
511 Handle(Geom_Curve) extCurv;
512 if (!AIS::ComputeGeometry(TopoDS::Edge(myFShape),
513 TopoDS::Edge(mySShape),
522 isInfinite1,isInfinite2,
525 aPrs->SetInfiniteState((isInfinite1 || isInfinite2) && myExtShape != 0);
527 // Treatement of the case of lines
528 if ( curv1->IsInstance(STANDARD_TYPE(Geom_Line)) && curv2->IsInstance(STANDARD_TYPE(Geom_Line)) ) {
529 // we take the line curv1 like support
530 Handle(Geom_Line) thelin;
531 if (isInfinite1 && !isInfinite2) thelin = (Handle(Geom_Line)&) curv2;
532 else if (!isInfinite1 && isInfinite2) thelin = (Handle(Geom_Line)&) curv1;
533 else thelin = (Handle(Geom_Line)&) curv1;
534 ComputeTwoLinesPresentation(aPrs, thelin, firstp1, lastp1, firstp2, lastp2, isInfinite1, isInfinite2);
537 // Treatement of the case of circles
538 else if ( curv1->IsInstance(STANDARD_TYPE(Geom_Circle)) && curv2->IsInstance(STANDARD_TYPE(Geom_Circle)) ) {
540 isCircle = Standard_True; // useful for ComputeSelection
541 const Handle(Geom_Circle)& thecirc = (Handle(Geom_Circle)&) curv1;
542 ComputeTwoCirclesPresentation(aPrs, thecirc, firstp1, lastp1, firstp2, lastp2);
546 // Treatement of the case of ellipses
547 else if ( curv1->IsInstance(STANDARD_TYPE(Geom_Ellipse)) && curv2->IsInstance(STANDARD_TYPE(Geom_Ellipse)) )
549 const Handle(Geom_Ellipse)& theEll = (Handle(Geom_Ellipse)&) curv1;
550 ComputeTwoEllipsesPresentation(aPrs, theEll, firstp1, lastp1, firstp2, lastp2);
552 // jfa 10/10/2000 end
556 // Calculate presentation of projected edges
557 if ( (myExtShape != 0) && !extCurv.IsNull()) {
558 if (myExtShape == 1 )
559 ComputeProjEdgePresentation(aPrs, TopoDS::Edge(myFShape), curv1, firstp1, lastp1);
561 ComputeProjEdgePresentation(aPrs, TopoDS::Edge(mySShape), curv2, firstp2, lastp2);
565 //=======================================================================
566 //function : ComputeTwoLinesPresentation
567 //purpose : Compute the presentation of the 'identic' constraint
568 // between two lines ( which are equal)
569 //input : <thelin> : the
570 // <firstp1>: first extremity of the 1st curve of the constraint
571 // <lastp1> : last extremity of the 1st curve of the constraint
572 // <firstp2>: first extremity of the 2nd curve of the constraint
573 // <lastp2> :last extremity of the 2nd curve of the constraint
574 //=======================================================================
575 void AIS_IdenticRelation::ComputeTwoLinesPresentation(const Handle(Prs3d_Presentation)& aPrs,
576 const Handle(Geom_Line)& thelin,
581 const Standard_Boolean isInfinite1,
582 const Standard_Boolean isInfinite2)
584 if (isInfinite1 && isInfinite2) {
585 if ( myAutomaticPosition ) {
586 myFAttach = mySAttach = thelin->Lin().Location();
588 gp_Pln pln(myPlane->Pln());
589 gp_Dir dir(pln.XAxis().Direction());
590 gp_Vec transvec = gp_Vec(dir)*myArrowSize;
591 curpos = myFAttach.Translated(transvec);;
593 myAutomaticPosition = Standard_True;
596 myFAttach = mySAttach = ElCLib::Value(ElCLib::Parameter(thelin->Lin(),myPosition),thelin->Lin());
598 TCollection_ExtendedString vals(" ==");
599 DsgPrs_IdenticPresentation::Add(aPrs,
606 // Computation of the parameters of the 4 points on the line <thelin>
607 Standard_Real pf1, pf2, pl1, pl2;
609 pf1 = ElCLib::Parameter(thelin->Lin(), firstp1);
610 pl1 = ElCLib::Parameter(thelin->Lin(), lastp1);
612 pf2 = ElCLib::Parameter(thelin->Lin(), firstp2);
613 pl2 = ElCLib::Parameter(thelin->Lin(), lastp2);
621 else if (isInfinite2) {
628 Standard_Real tabRang1[4]; // array taht contains the parameters of the 4 points
629 // ordered by increasing abscisses.
631 gp_Pnt tabRang2[4]; // array containing the points corresponding to the
632 // parameters in tabRang1
634 Standard_Integer tabRang3[4]; // array containing the number of the curve( 1 or 2)
635 // of which belongs each point of tabRang2
637 // Filling of the arrays
638 tabRang1[0] = pf1; tabRang2[0] = firstp1; tabRang3[0] = 1;
639 tabRang1[1] = pf2; tabRang2[1] = firstp2; tabRang3[1] = 2;
640 tabRang1[2] = pl1; tabRang2[2] = lastp1; tabRang3[2] = 1;
641 tabRang1[3] = pl2; tabRang2[3] = lastp2; tabRang3[3] = 2;
643 // Sort of the array of parameters (tabRang1)
644 AIS_Sort(tabRang1, tabRang2, tabRang3);
646 // Computation of myFAttach and mySAttach according to the
647 // position of the 2 linear edges
651 if ( (tabRang1[0] == tabRang1[1]) && (tabRang1[2] == tabRang1[3]) ) {
652 middle.SetXYZ((tabRang2[1].XYZ() + tabRang2[2].XYZ())/2. );
653 Standard_Real pmiddle = (tabRang1[1] + tabRang1[2]) / 2.;
654 Standard_Real delta = (tabRang1[3] - tabRang1[0])/ 5.;
655 myFAttach = ElCLib::Value(pmiddle-delta, thelin->Lin());
656 mySAttach = ElCLib::Value(pmiddle+delta, thelin->Lin());
659 else if ( tabRang1[1] == tabRang1[2] ) {
660 middle = tabRang2[1];
661 Standard_Real delta1 = tabRang1[1] - tabRang1[0];
662 Standard_Real delta2 = tabRang1[3] - tabRang1[2];
663 if ( delta1 > delta2 ) delta1 = delta2;
664 myFAttach = ElCLib::Value(tabRang1[1]-delta1/2., thelin->Lin());
665 mySAttach = ElCLib::Value(tabRang1[1]+delta1/2., thelin->Lin());
668 // Case of 2 disconnected segments -> the symbol completes the gap
669 // between the 2 edges
670 //--------------------------------
671 else if ( (tabRang3[0] == tabRang3[1]) && (tabRang1[1] != tabRang1[2])) {
672 middle.SetXYZ((tabRang2[1].XYZ() + tabRang2[2].XYZ())/2. );
673 myFAttach = tabRang2[1];
674 mySAttach = tabRang2[2];
676 else if ( (tabRang3[0] != tabRang3[1])
677 && (tabRang3[1] != tabRang3[2]) // Intersection
678 && (tabRang1[1] != tabRang1[2]) ) {
679 middle.SetXYZ((tabRang2[1].XYZ() + tabRang2[2].XYZ())/2. );
680 myFAttach = tabRang2[1];
681 mySAttach = tabRang2[2];
684 myFAttach.SetXYZ((tabRang2[0].XYZ() + tabRang2[1].XYZ())/2. );
685 mySAttach.SetXYZ((tabRang2[1].XYZ() + tabRang2[2].XYZ())/2. );
686 middle.SetXYZ( (myFAttach.XYZ() + mySAttach.XYZ() )/2.);
690 if ( myAutomaticPosition ) {
692 gp_Vec vtrans(myFAttach, mySAttach);
694 vtrans.Cross(gp_Vec(myPlane->Pln().Axis().Direction()));
695 vtrans *= ComputeSegSize();
696 curpos = middle.Translated(vtrans);
698 myAutomaticPosition = Standard_True;
704 Standard_Real pcurpos = ElCLib::Parameter(thelin->Lin() ,curpos);
705 Standard_Real dist = thelin->Lin().Distance(curpos);
706 gp_Pnt proj = ElCLib::Value( pcurpos, thelin->Lin());
708 Standard_Real confusion(Precision::Confusion());
709 if ( dist >= confusion ) {
710 trans = gp_Vec(proj, curpos);
713 Standard_Real pf = ElCLib::Parameter(thelin->Lin() ,myFAttach);
714 Standard_Real pl = ElCLib::Parameter(thelin->Lin() ,mySAttach);
715 if ( pcurpos <= pf ) {
717 curpos = ElCLib::Value( pcurpos, thelin->Lin());
718 if ( dist >= confusion ) curpos.Translate(trans*dist);
720 else if ( pcurpos >= pl ) {
722 curpos = ElCLib::Value( pcurpos, thelin->Lin());
723 if ( dist >= confusion ) curpos.Translate(trans*dist);
728 // Display of the presentation
729 TCollection_ExtendedString vals(" ==");
730 DsgPrs_IdenticPresentation::Add(aPrs,
740 //=======================================================================
741 //function : ComputeTwoCirclesPresentation
742 //purpose : Compute the presentation of the 'identic' constraint
743 // between two circles ( which are equal)
744 //input : <thecirc>: the circle
745 // <firstp1>: first extremity of the 1st curve of the constraint
746 // <lastp1> : last extremity of the 1st curve of the constraint
747 // <firstp2>: first extremity of the 2nd curve of the constraint
748 // <lastp2> :last extremity of the 2nd curve of the constraint
749 //=======================================================================
750 void AIS_IdenticRelation::ComputeTwoCirclesPresentation(const Handle(Prs3d_Presentation)& aPrs,
751 const Handle(Geom_Circle)& thecirc,
752 const gp_Pnt& firstp1,
753 const gp_Pnt& lastp1,
754 const gp_Pnt& firstp2,
755 const gp_Pnt& lastp2)
757 Standard_Real confusion (Precision::Confusion());
759 // Searching of complete circles
760 Standard_Boolean circ1complete = (firstp1.IsEqual(lastp1, confusion));
761 Standard_Boolean circ2complete = (firstp2.IsEqual(lastp2, confusion));
763 myCenter = thecirc->Location();
764 Standard_Real aSegSize = thecirc->Radius()/5.0;
765 Standard_Real rad = M_PI / 5.0;
767 // I. Case of 2 complete circles
768 if ( circ1complete && circ2complete )
770 if (myAutomaticPosition)
772 Standard_Real pfirst1 = ElCLib::Parameter(thecirc->Circ(), firstp1);
773 myFAttach = ElCLib::Value(Modulo2PI(pfirst1-rad), thecirc->Circ());
774 mySAttach = ElCLib::Value(Modulo2PI(pfirst1+rad), thecirc->Circ());
776 gp_Pnt curpos = ElCLib::Value(pfirst1,thecirc->Circ());
777 gp_Vec vtrans(myCenter, curpos);
780 curpos.Translate(vtrans);
783 else ComputeNotAutoCircPresentation(thecirc);
786 // II. Case of one complete circle and one arc
787 else if ( (circ1complete && !circ2complete) || (!circ1complete && circ2complete) )
789 gp_Pnt firstp, lastp;
790 if ( circ1complete && !circ2complete)
801 if (myAutomaticPosition)
803 ComputeAutoArcPresentation(thecirc, firstp, lastp);
807 ComputeNotAutoArcPresentation(thecirc, firstp, lastp);
811 // III and IV. Case of two arcs
812 else if ( !circ1complete && !circ2complete )
814 // We project all the points on the circle
815 Standard_Real pf1, pf2, pl1, pl2;
816 pf1 = ElCLib::Parameter(thecirc->Circ(), firstp1);
817 pf2 = ElCLib::Parameter(thecirc->Circ(), firstp2);
818 pl1 = ElCLib::Parameter(thecirc->Circ(), lastp1);
819 pl2 = ElCLib::Parameter(thecirc->Circ(), lastp2);
821 // III. Arcs with common ends
822 // III.1. First of one and last of another
823 if ( IsEqual2PI(pl1,pf2,confusion) || IsEqual2PI(pf1,pl2,confusion) )
825 gp_Pnt curpos(0.,0.,0.);
826 Standard_Real att=0.;
827 if ( IsEqual2PI(pl1,pf2,confusion) )
832 else if ( IsEqual2PI(pf1,pl2,confusion) )
837 Standard_Real maxrad = Min(Modulo2PI(pl1 - pf1),Modulo2PI(pl2 - pf2))*3/4;
838 if ( rad > maxrad ) rad = maxrad;
839 Standard_Real pFAttach = Modulo2PI(att - rad);
840 Standard_Real pSAttach = Modulo2PI(att + rad);
841 myFAttach = ElCLib::Value(pFAttach, thecirc->Circ());
842 mySAttach = ElCLib::Value(pSAttach, thecirc->Circ());
843 if ( myAutomaticPosition )
845 gp_Vec vtrans(myCenter,curpos);
848 curpos.Translate(vtrans);
852 // III.2. Two first or two last
853 else if ( IsEqual2PI(pf1,pf2,confusion) || IsEqual2PI(pl1,pl2,confusion) )
855 Standard_Real l1 = Modulo2PI(pl1 - pf1);
856 Standard_Real l2 = Modulo2PI(pl2 - pf2);
869 if ( myAutomaticPosition )
871 ComputeAutoArcPresentation(thecirc, firstp, lastp);
875 ComputeNotAutoArcPresentation(thecirc, firstp, lastp);
878 // IV. All others arcs (without common ends)
881 // order the parameters; first will be pf1
882 Standard_Real pl1m = Modulo2PI(pl1 - pf1);
883 Standard_Real pf2m = Modulo2PI(pf2 - pf1);
884 Standard_Real pl2m = Modulo2PI(pl2 - pf1);
886 Standard_Boolean case1 = Standard_False;
887 // 1 - not intersecting arcs
888 // 2 - intersecting arcs, but one doesn't contain another
889 // 3a - first arc contains the second one
890 // 3b - second arc contains the first one
891 // 4 - two intersections
893 gp_Pnt firstp, lastp;
895 if ( pl1m < pf2m ) // 1 or 2b or 3b
897 if ( pl1m < pl2m ) // 1 or 3b
899 if ( pl2m < pf2m ) // 3b
906 case1 = Standard_True;
907 Standard_Real deltap1 = Modulo2PI(pf1 - pl2);
908 Standard_Real deltap2 = Modulo2PI(pf2 - pl1);
909 if ( ((deltap1 < deltap2) && (deltap1 < 2*rad)) ||
910 ((deltap2 < deltap1) && (deltap2 > 2*rad)) ) // deltap2
928 else // 2a or 3a or 4
930 if ( pl1m < pl2m ) // 2a
937 if ( pl2m > pf2m ) // 3a
944 Standard_Real deltap1 = Modulo2PI(pl1 - pf2);
945 Standard_Real deltap2 = Modulo2PI(pl2 - pf1);
946 if ( ((deltap1 < deltap2) && (deltap1 < 2*rad)) ||
947 ((deltap2 < deltap1) && (deltap2 > 2*rad)) ) // deltap2
961 if ( myAutomaticPosition )
963 ComputeAutoArcPresentation(thecirc,firstp,lastp,case1);
972 else ComputeNotAutoArcPresentation(thecirc, firstp, lastp);
977 // Display of the presentation
978 TCollection_ExtendedString vals(" ==");
979 gp_Pnt attach = myPosition;
980 ComputeAttach(thecirc->Circ(),myFAttach,mySAttach,attach);
981 DsgPrs_IdenticPresentation::Add(aPrs,
984 myPlane->Pln().Position().Ax2(),
992 //=======================================================================
993 //function : ComputeAutoArcPresentation
994 //purpose : Compute the presentation of the constraint where we are
995 // not in the case of dragging.
996 //=======================================================================
997 void AIS_IdenticRelation::ComputeAutoArcPresentation(const Handle(Geom_Circle)& thecirc,
998 const gp_Pnt& firstp,
1000 const Standard_Boolean isstatic)
1002 Standard_Real aSegSize = thecirc->Radius()/5.0;
1003 Standard_Real rad = M_PI / 5.0;
1005 Standard_Real pFA = ElCLib::Parameter(thecirc->Circ(),firstp);
1006 Standard_Real pSA = ElCLib::Parameter(thecirc->Circ(),lastp);
1007 Standard_Real maxrad = Modulo2PI(pSA - pFA)/2.0;
1009 if ( (rad > maxrad) || isstatic ) rad = maxrad;
1010 Standard_Real pmiddle = Modulo2PI(pFA + Modulo2PI(pSA - pFA)/2.0);
1012 myFAttach = ElCLib::Value(Modulo2PI(pmiddle - rad),thecirc->Circ());
1013 mySAttach = ElCLib::Value(Modulo2PI(pmiddle + rad),thecirc->Circ());
1015 gp_Pnt curpos = ElCLib::Value(pmiddle,thecirc->Circ());
1016 gp_Vec vtrans(myCenter, curpos);
1019 myPosition = curpos.Translated(vtrans);
1022 //=======================================================================
1023 //function : ComputeNotAutoCircPresentation
1024 //purpose : Compute the presentation of the constraint where we are
1025 // in the case of dragging.
1026 // Note : This function is to be used only in the case of full circles.
1027 // The symbol of the constraint moves together with arc
1028 // representing the constraint around all the circle.
1029 //=======================================================================
1030 void AIS_IdenticRelation::ComputeNotAutoCircPresentation(const Handle(Geom_Circle)& thecirc)
1032 gp_Pnt curpos = myPosition;
1034 Handle(Geom_Circle) cirNotAuto = new Geom_Circle(thecirc->Circ());
1036 // Case of confusion between the current position and the center
1037 // of the circle -> we move the current position
1038 Standard_Real confusion (Precision::Confusion());
1039 if ( myCenter.Distance(curpos) <= confusion )
1041 gp_Vec vprec(myCenter, myFAttach);
1043 curpos.Translate(vprec*1e-5);
1046 Standard_Real rad = M_PI / 5.0;
1047 Standard_Real pcurpos = ElCLib::Parameter(cirNotAuto->Circ(),curpos);
1048 Standard_Real pFAttach = pcurpos - rad;
1049 Standard_Real pSAttach = pcurpos + rad;
1050 myFAttach = ElCLib::Value(pFAttach,cirNotAuto->Circ());
1051 mySAttach = ElCLib::Value(pSAttach,cirNotAuto->Circ());
1054 //=======================================================================
1055 //function : ComputeNotAutoArcPresentation
1056 //purpose : Compute the presentation of the constraint where we are
1057 // in the case of dragging.
1058 // Note : This function is to be used only in the case of circles.
1059 // The symbol of the constraint moves only between myFAttach
1061 //=======================================================================
1062 void AIS_IdenticRelation::ComputeNotAutoArcPresentation(const Handle(Geom_Circle)& thecirc,
1063 const gp_Pnt& pntfirst,
1064 const gp_Pnt& pntlast)
1066 gp_Pnt curpos = myPosition;
1068 gp_Circ cirNotAuto = thecirc->Circ();
1070 Standard_Real pFPnt = ElCLib::Parameter(cirNotAuto, pntfirst);
1071 Standard_Real pSPnt = ElCLib::Parameter(cirNotAuto, pntlast);
1072 Standard_Real deltap = Modulo2PI(pSPnt - pFPnt)/2.0;
1074 Standard_Real rad = M_PI / 5;
1077 myFAttach = pntfirst;
1078 mySAttach = pntlast;
1082 gp_Pnt aFPnt = ElCLib::Value(Modulo2PI(pFPnt + rad), cirNotAuto);
1083 gp_Pnt aSPnt = ElCLib::Value(Modulo2PI(pSPnt - rad), cirNotAuto);
1085 ComputeAttach(cirNotAuto,aFPnt,aSPnt,curpos);
1087 Standard_Real pcurpos = ElCLib::Parameter(cirNotAuto,curpos);
1088 myFAttach = ElCLib::Value(pcurpos - rad, cirNotAuto);
1089 mySAttach = ElCLib::Value(pcurpos + rad, cirNotAuto);
1092 // jfa 17/10/2000 end
1095 //=======================================================================
1096 //function : ComputeTwoEllipsesPresentation
1097 //purpose : Compute the presentation of the 'identic' constraint
1098 // between two ellipses (which are equal)
1099 //input : <theEll>: the ellipse
1100 // <firstp1>: first extremity of the 1st curve of the constraint
1101 // <lastp1> : last extremity of the 1st curve of the constraint
1102 // <firstp2>: first extremity of the 2nd curve of the constraint
1103 // <lastp2> :last extremity of the 2nd curve of the constraint
1104 //=======================================================================
1105 void AIS_IdenticRelation::ComputeTwoEllipsesPresentation(const Handle(Prs3d_Presentation)& aPrs,
1106 const Handle(Geom_Ellipse)& theEll,
1107 const gp_Pnt& firstp1,
1108 const gp_Pnt& lastp1,
1109 const gp_Pnt& firstp2,
1110 const gp_Pnt& lastp2)
1112 Standard_Real confusion (Precision::Confusion());
1114 // Searching of complete ellipses
1115 Standard_Boolean circ1complete = (firstp1.IsEqual(lastp1, confusion));
1116 Standard_Boolean circ2complete = (firstp2.IsEqual(lastp2, confusion));
1118 myCenter = theEll->Location();
1119 Standard_Real aSegSize = theEll->MajorRadius()/5.0;
1120 Standard_Real rad = M_PI / 5.0;
1122 // I. Case of 2 complete ellipses
1123 if ( circ1complete && circ2complete )
1125 if (myAutomaticPosition)
1127 Standard_Real pfirst1 = ElCLib::Parameter(theEll->Elips(), firstp1);
1128 myFAttach = ElCLib::Value(Modulo2PI(pfirst1-rad), theEll->Elips());
1129 mySAttach = ElCLib::Value(Modulo2PI(pfirst1+rad), theEll->Elips());
1131 gp_Pnt curpos = ElCLib::Value(pfirst1,theEll->Elips());
1132 gp_Vec vtrans(myCenter, curpos);
1135 curpos.Translate(vtrans);
1136 myPosition = curpos;
1138 else ComputeNotAutoElipsPresentation(theEll);
1141 // II. Case of one complete circle and one arc
1142 else if ( (circ1complete && !circ2complete) || (!circ1complete && circ2complete) )
1144 gp_Pnt firstp, lastp;
1145 if ( circ1complete && !circ2complete)
1156 if (myAutomaticPosition)
1158 ComputeAutoArcPresentation(theEll, firstp, lastp);
1162 ComputeNotAutoArcPresentation(theEll, firstp, lastp);
1166 // III and IV. Case of two arcs
1167 else if ( !circ1complete && !circ2complete )
1169 // We project all the points on the circle
1170 Standard_Real pf1, pf2, pl1, pl2;
1171 pf1 = ElCLib::Parameter(theEll->Elips(), firstp1);
1172 pf2 = ElCLib::Parameter(theEll->Elips(), firstp2);
1173 pl1 = ElCLib::Parameter(theEll->Elips(), lastp1);
1174 pl2 = ElCLib::Parameter(theEll->Elips(), lastp2);
1176 // III. Arcs with common ends
1177 // III.1. First of one and last of another
1178 if ( IsEqual2PI(pl1,pf2,confusion) || IsEqual2PI(pf1,pl2,confusion) )
1181 Standard_Real att=0.;
1182 if ( IsEqual2PI(pl1,pf2,confusion) )
1187 else if ( IsEqual2PI(pf1,pl2,confusion) )
1192 Standard_Real maxrad = Min(Modulo2PI(pl1 - pf1),Modulo2PI(pl2 - pf2))*3/4;
1193 if ( rad > maxrad ) rad = maxrad;
1194 Standard_Real pFAttach = Modulo2PI(att - rad);
1195 Standard_Real pSAttach = Modulo2PI(att + rad);
1196 myFAttach = ElCLib::Value(pFAttach, theEll->Elips());
1197 mySAttach = ElCLib::Value(pSAttach, theEll->Elips());
1198 if ( myAutomaticPosition )
1200 gp_Vec vtrans(myCenter,curpos);
1203 curpos.Translate(vtrans);
1204 myPosition = curpos;
1207 // III.2. Two first or two last
1208 else if ( IsEqual2PI(pf1,pf2,confusion) || IsEqual2PI(pl1,pl2,confusion) )
1210 Standard_Real l1 = Modulo2PI(pl1 - pf1);
1211 Standard_Real l2 = Modulo2PI(pl2 - pf2);
1212 gp_Pnt firstp,lastp;
1224 if ( myAutomaticPosition )
1226 ComputeAutoArcPresentation(theEll, firstp, lastp);
1230 ComputeNotAutoArcPresentation(theEll, firstp, lastp);
1233 // IV. All others arcs (without common ends)
1236 // order the parameters; first will be pf1
1237 Standard_Real pl1m = Modulo2PI(pl1 - pf1);
1238 Standard_Real pf2m = Modulo2PI(pf2 - pf1);
1239 Standard_Real pl2m = Modulo2PI(pl2 - pf1);
1241 Standard_Boolean case1 = Standard_False;
1242 // 1 - not intersecting arcs
1243 // 2 - intersecting arcs, but one doesn't contain another
1244 // 3a - first arc contains the second one
1245 // 3b - second arc contains the first one
1246 // 4 - two intersections
1248 gp_Pnt firstp, lastp;
1250 if ( pl1m < pf2m ) // 1 or 2b or 3b
1252 if ( pl1m < pl2m ) // 1 or 3b
1254 if ( pl2m < pf2m ) // 3b
1261 case1 = Standard_True;
1262 Standard_Real deltap1 = Modulo2PI(pf1 - pl2);
1263 Standard_Real deltap2 = Modulo2PI(pf2 - pl1);
1264 if ( ((deltap1 < deltap2) && (deltap1 < 2*rad)) ||
1265 ((deltap2 < deltap1) && (deltap2 > 2*rad)) ) // deltap2
1283 else // 2a or 3a or 4
1285 if ( pl1m < pl2m ) // 2a
1292 if ( pl2m > pf2m ) // 3a
1299 Standard_Real deltap1 = Modulo2PI(pl1 - pf2);
1300 Standard_Real deltap2 = Modulo2PI(pl2 - pf1);
1301 if ( ((deltap1 < deltap2) && (deltap1 < 2*rad)) ||
1302 ((deltap2 < deltap1) && (deltap2 > 2*rad)) ) // deltap2
1316 if ( myAutomaticPosition )
1318 ComputeAutoArcPresentation(theEll,firstp,lastp,case1);
1327 else ComputeNotAutoArcPresentation(theEll, firstp, lastp);
1332 // Display of the presentation
1333 TCollection_ExtendedString vals(" ==");
1334 gp_Pnt attach = myPosition;
1335 ComputeAttach(theEll->Elips(),myFAttach,mySAttach,attach);
1336 DsgPrs_IdenticPresentation::Add(aPrs,
1346 //=======================================================================
1347 //function : ComputeAutoArcPresentation
1348 //purpose : Compute the presentation of the constraint where we are
1349 // not in the case of dragging.
1350 //=======================================================================
1351 void AIS_IdenticRelation::ComputeAutoArcPresentation(const Handle(Geom_Ellipse)& theEll,
1352 const gp_Pnt& firstp,
1353 const gp_Pnt& lastp,
1354 const Standard_Boolean isstatic)
1356 Standard_Real aSegSize = theEll->MajorRadius()/5.0;
1357 Standard_Real rad = M_PI / 5.0;
1359 gp_Elips anEll = theEll->Elips();
1361 Standard_Real pFA = ElCLib::Parameter(anEll,firstp);
1362 Standard_Real pSA = ElCLib::Parameter(anEll,lastp);
1363 Standard_Real maxrad = Modulo2PI(pSA - pFA)/2.0;
1365 if ( (rad > maxrad) || isstatic ) rad = maxrad;
1366 Standard_Real pmiddle = Modulo2PI(pFA + Modulo2PI(pSA - pFA)/2.0);
1368 myFAttach = ElCLib::Value(Modulo2PI(pmiddle - rad),anEll);
1369 mySAttach = ElCLib::Value(Modulo2PI(pmiddle + rad),anEll);
1371 gp_Pnt curpos = ElCLib::Value(pmiddle,anEll);
1372 gp_Vec vtrans(myCenter, curpos);
1375 myPosition = curpos.Translated(vtrans);
1378 //=======================================================================
1379 //function : ComputeNotAutoElipsPresentation
1380 //purpose : Compute the presentation of the constraint where we are
1381 // in the case of dragging.
1382 // Note : This function is to be used only in the case of ellipses.
1383 // The symbol of the constraint moves only between myFAttach
1385 //=======================================================================
1386 void AIS_IdenticRelation::ComputeNotAutoElipsPresentation(const Handle(Geom_Ellipse)& theEll)
1388 gp_Pnt curpos = myPosition;
1390 gp_Elips anEll = theEll->Elips();
1392 // Case of confusion between the current position and the center
1393 // of the ellipse -> we move the current position
1394 Standard_Real confusion (Precision::Confusion());
1395 if ( myCenter.Distance(curpos) <= confusion )
1397 gp_Vec vprec(myCenter, myFAttach);
1399 curpos.Translate(vprec*1e-5);
1402 Standard_Real rad = M_PI / 5.0;
1403 // Standard_Real pcurpos = ElCLib::Parameter(anEll,curpos);
1404 GeomAPI_ProjectPointOnCurve aProj (curpos, theEll);
1405 Standard_Real pcurpos = aProj.LowerDistanceParameter();
1407 Standard_Real pFAttach = pcurpos - rad;
1408 Standard_Real pSAttach = pcurpos + rad;
1409 myFAttach = ElCLib::Value(pFAttach,anEll);
1410 mySAttach = ElCLib::Value(pSAttach,anEll);
1413 //=======================================================================
1414 //function : ComputeNotAutoArcPresentation
1415 //purpose : Compute the presentation of the constraint where we are
1416 // in the case of dragging.
1417 // Note : This function is to be used only in the case of ellipses.
1418 // The symbol of the constraint moves only between myFAttach
1420 //=======================================================================
1421 void AIS_IdenticRelation::ComputeNotAutoArcPresentation(const Handle(Geom_Ellipse)& theEll,
1422 const gp_Pnt& pntfirst,
1423 const gp_Pnt& pntlast)
1425 gp_Pnt curpos = myPosition;
1427 gp_Elips anEll = theEll->Elips();
1429 Standard_Real pFPnt = ElCLib::Parameter(anEll, pntfirst);
1430 Standard_Real pSPnt = ElCLib::Parameter(anEll, pntlast);
1431 Standard_Real deltap = Modulo2PI(pSPnt - pFPnt)/2.0;
1433 Standard_Real rad = M_PI / 5;
1436 myFAttach = pntfirst;
1437 mySAttach = pntlast;
1441 gp_Pnt aFPnt = ElCLib::Value(Modulo2PI(pFPnt + rad), anEll);
1442 gp_Pnt aSPnt = ElCLib::Value(Modulo2PI(pSPnt - rad), anEll);
1444 ComputeAttach(anEll,aFPnt,aSPnt,curpos);
1446 // Standard_Real pcurpos = ElCLib::Parameter(anEll,curpos);
1447 GeomAPI_ProjectPointOnCurve aProj (curpos, theEll);
1448 Standard_Real pcurpos = aProj.LowerDistanceParameter();
1450 myFAttach = ElCLib::Value(pcurpos - rad, anEll);
1451 mySAttach = ElCLib::Value(pcurpos + rad, anEll);
1454 // jfa 18/10/2000 end
1456 //=======================================================================
1457 //function : ComputeTwoVerticesPresentation
1459 //=======================================================================
1460 void AIS_IdenticRelation::ComputeTwoVerticesPresentation(const Handle(Prs3d_Presentation)& aPrs)
1462 Standard_Boolean isOnPlane1, isOnPlane2;
1463 const TopoDS_Vertex& FVertex = TopoDS::Vertex(myFShape);
1464 const TopoDS_Vertex& SVertex = TopoDS::Vertex(mySShape);
1466 AIS::ComputeGeometry(FVertex, myFAttach, myPlane, isOnPlane1);
1467 AIS::ComputeGeometry(SVertex, mySAttach, myPlane, isOnPlane2);
1469 if (isOnPlane1 && isOnPlane2)
1471 else if ( isOnPlane1 && !isOnPlane2)
1473 else if (!isOnPlane1 && isOnPlane2)
1479 // The attachement points are the points themselves that must be
1481 myFAttach = BRep_Tool::Pnt(FVertex);
1482 mySAttach = myFAttach;
1485 if (myAutomaticPosition)
1487 //Computation of the size of the symbol
1488 Standard_Real symbsize = ComputeSegSize();
1489 if (symbsize <= Precision::Confusion()) symbsize = 1.;
1491 // Computation of the direction of the segment of the presentation
1492 // we take the median of the edges connected to vertices
1495 TColStd_ListIteratorOfListOfTransient it(Users());
1498 const Handle(AIS_Shape)& USER = Handle(AIS_Shape)::DownCast(it.Value());
1501 const TopoDS_Shape& SH =USER->Shape();
1502 if ( (!SH.IsNull()) && (SH.ShapeType() == TopAbs_WIRE) )
1504 const TopoDS_Wire& WIRE = TopoDS::Wire(USER->Shape());
1505 Standard_Boolean done = ComputeDirection(WIRE,FVertex,dF);
1507 done = ComputeDirection(WIRE,SVertex,dS);
1514 // computation of the segment direction like average
1515 // of the 2 computed directions.
1516 if ( dF.IsParallel(dS, Precision::Angular()) )
1518 myDir = dF.Crossed(myPlane->Pln().Axis().Direction());
1522 myDir.SetXYZ(dF.XYZ() + dS.XYZ());
1524 curpos = myFAttach.Translated(gp_Vec(myDir)*symbsize) ;
1531 // jfa 11/10/2000 end
1533 myPosition = curpos;
1534 myAutomaticPosition = Standard_False;
1538 curpos = myPosition;
1541 // Presentation computation
1542 TCollection_ExtendedString vals(" ++");
1543 DsgPrs_IdenticPresentation::Add(aPrs,
1548 // Calculate the projection of vertex
1549 if ( myExtShape == 1)
1550 ComputeProjVertexPresentation(aPrs,FVertex,myFAttach);
1551 else if ( myExtShape == 2)
1552 ComputeProjVertexPresentation(aPrs,SVertex,mySAttach);
1557 //=======================================================================
1558 //function : ComputeSegSize
1560 //=======================================================================
1561 Standard_Real AIS_IdenticRelation::ComputeSegSize() const
1566 //=======================================================================
1567 //function : ComputeDirection
1568 //purpose : Compute a direction according to the different geometric
1569 // elements connected to the vertex <VERT>, in way to not have
1570 // overlap between the symbol and them.
1571 //=======================================================================
1572 Standard_Boolean AIS_IdenticRelation::ComputeDirection(const TopoDS_Wire& aWire,
1573 const TopoDS_Vertex& VERT,
1576 // we take the median of the edges connected to vertices
1577 TopoDS_Edge edg1,edg2;
1578 ConnectedEdges(aWire,VERT,edg1,edg2);
1580 if ( edg1.IsNull() && edg2.IsNull() ) {
1581 return Standard_False;
1584 Handle(Geom_Curve) curv1,curv2;
1585 gp_Pnt firstp1,lastp1,firstp2,lastp2;
1587 // Case with 2 edges connected to the vertex <VERT>
1588 if ( !edg1.IsNull() && !edg2.IsNull() ) {
1589 if ( !AIS::ComputeGeometry(edg1,edg2,
1592 firstp2, lastp2,myPlane))
1593 return Standard_False;
1596 if ( curv1->IsInstance(STANDARD_TYPE(Geom_Circle)) ) {
1597 d1 = ComputeCircleDirection((Handle(Geom_Circle)&) curv1, VERT);
1599 else if (curv1->IsInstance(STANDARD_TYPE(Geom_Line)) ) {
1600 d1 = ComputeLineDirection((Handle(Geom_Line)&) curv1, firstp1);
1603 return Standard_False;
1605 if ( curv2->IsInstance(STANDARD_TYPE(Geom_Circle)) ) {
1606 d2 = ComputeCircleDirection( (Handle(Geom_Circle)&) curv2, VERT);
1608 else if (curv2->IsInstance(STANDARD_TYPE(Geom_Line)) ) {
1609 d2 =ComputeLineDirection( (Handle(Geom_Line)&) curv2, firstp2);
1612 return Standard_False;
1614 if ( !d1.IsParallel(d2, Precision::Angular() ))
1615 dF.SetXYZ( (d1.XYZ() + d2.XYZ())/2 );
1617 dF= d1.Crossed(myPlane->Pln().Axis().Direction());
1621 // Case where <VERT> is at an extremity of a wire.
1624 if ( !edg1.IsNull() )
1626 else if (!edg2.IsNull() )
1629 return Standard_False;
1631 if ( !AIS::ComputeGeometry(VEdge, curv1, firstp1, lastp1) )
1632 return Standard_False;
1633 if ( curv1->IsInstance(STANDARD_TYPE(Geom_Circle)) ) {
1634 dF = ComputeCircleDirection( (Handle(Geom_Circle)&) curv1, VERT);
1636 else if (curv1->IsInstance(STANDARD_TYPE(Geom_Line)) ) {
1637 dF = ComputeLineDirection( (Handle(Geom_Line)&) curv1, firstp1);
1640 return Standard_False;
1643 return Standard_True;
1646 //=======================================================================
1647 //function : ComputeLineDirection
1649 //=======================================================================
1650 gp_Dir AIS_IdenticRelation::ComputeLineDirection(const Handle(Geom_Line)& lin,
1651 const gp_Pnt& firstP) const
1654 dir = lin->Lin().Direction();
1655 if ( !myFAttach.IsEqual(firstP, Precision::Confusion()) )
1660 //=======================================================================
1661 //function : ComputeCircleDirection
1663 //=======================================================================
1664 gp_Dir AIS_IdenticRelation::ComputeCircleDirection(const Handle(Geom_Circle)& circ,
1665 const TopoDS_Vertex& VERT) const
1667 gp_Vec V(circ->Location(),BRep_Tool::Pnt(VERT));
1671 //=======================================================================
1672 //function : ComputeOneEdgeOVertexPresentation
1674 //=======================================================================
1675 void AIS_IdenticRelation::ComputeOneEdgeOVertexPresentation(const Handle(Prs3d_Presentation)& aPrs)
1679 Standard_Integer numedge;
1681 if (myFShape.ShapeType() == TopAbs_VERTEX) {
1682 V = TopoDS::Vertex(myFShape);
1683 E = TopoDS::Edge(mySShape);
1684 numedge = 2;// edge = 2nd shape
1687 V = TopoDS::Vertex(mySShape);
1688 E = TopoDS::Edge(myFShape);
1689 numedge = 1; // edge = 1st shape
1691 gp_Pnt ptonedge1,ptonedge2;
1692 Handle(Geom_Curve) aCurve;
1693 Handle(Geom_Curve) extCurv;
1694 Standard_Boolean isInfinite;
1695 Standard_Boolean isOnPlanEdge, isOnPlanVertex;
1696 if (!AIS::ComputeGeometry(E,aCurve,ptonedge1,ptonedge2,extCurv,isInfinite,isOnPlanEdge,myPlane))
1698 aPrs->SetInfiniteState(isInfinite);
1699 AIS::ComputeGeometry(V, myFAttach, myPlane, isOnPlanVertex);
1701 // only the curve can be projected
1702 if (!isOnPlanEdge && !isOnPlanVertex) return;
1704 if (!isOnPlanEdge) {
1705 if (numedge == 1) myExtShape = 1;
1706 else myExtShape = 2;
1708 else if (!isOnPlanVertex) {
1709 if (numedge == 1) myExtShape = 2;
1710 else myExtShape = 1;
1712 // The attachement points are the point
1713 myFAttach = BRep_Tool::Pnt(V);
1714 mySAttach = myFAttach;
1717 if (myAutomaticPosition) {
1718 //Computation of the size of the symbol
1719 Standard_Real symbsize = ComputeSegSize();
1721 // Computation of the direction of the segment of the presentation
1722 // we take the median of the edges connected to vertices
1724 if ( aCurve->IsKind(STANDARD_TYPE(Geom_Line))) {
1725 myDir = ((Handle(Geom_Line)&) aCurve)->Lin().Direction();
1726 myDir.Cross(myPlane->Pln().Axis().Direction());
1728 else if (aCurve->IsKind(STANDARD_TYPE(Geom_Circle))) {
1729 Handle(Geom_Circle) CIR = (Handle(Geom_Circle)&) aCurve;
1730 myDir.SetXYZ(myFAttach.XYZ() - CIR->Location().XYZ());
1733 else if (aCurve->IsKind(STANDARD_TYPE(Geom_Ellipse))) {
1734 Handle(Geom_Ellipse) CIR = (Handle(Geom_Ellipse)&) aCurve;
1735 myDir.SetXYZ(myFAttach.XYZ() - CIR->Location().XYZ());
1737 // jfa 10/10/2000 end
1739 curpos = myFAttach.Translated(gp_Vec(myDir)*symbsize) ;
1740 myPosition = curpos;
1741 myAutomaticPosition = Standard_True;
1744 curpos = myPosition;
1747 // Presentation computation
1748 TCollection_ExtendedString vals(" -+-");
1749 DsgPrs_IdenticPresentation::Add(aPrs,
1754 if (myExtShape != 0) {
1755 if (!extCurv.IsNull()) { // the edge is not in the WP
1756 ComputeProjEdgePresentation(aPrs,E,(Handle(Geom_Line)&) aCurve,ptonedge1,ptonedge2);