1 // Created on: 1997-03-03
2 // Created by: Jean-Pierre COMBE
3 // Copyright (c) 1997-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
19 #include <AIS_IdenticRelation.hxx>
20 #include <AIS_Shape.hxx>
21 #include <BRep_Tool.hxx>
22 #include <DsgPrs_IdenticPresentation.hxx>
24 #include <Geom_Circle.hxx>
25 #include <Geom_Ellipse.hxx>
26 #include <Geom_Line.hxx>
27 #include <Geom_Plane.hxx>
28 #include <Geom_Transformation.hxx>
29 #include <Geom_TrimmedCurve.hxx>
30 #include <GeomAPI_ProjectPointOnCurve.hxx>
35 #include <Precision.hxx>
36 #include <Prs3d_Drawer.hxx>
37 #include <Prs3d_LineAspect.hxx>
38 #include <Prs3d_Presentation.hxx>
39 #include <Prs3d_Projector.hxx>
40 #include <Select3D_SensitiveCurve.hxx>
41 #include <Select3D_SensitiveSegment.hxx>
42 #include <SelectMgr_EntityOwner.hxx>
43 #include <SelectMgr_Selection.hxx>
44 #include <Standard_NotImplemented.hxx>
45 #include <Standard_Type.hxx>
46 #include <TCollection_ExtendedString.hxx>
47 #include <TColStd_ListIteratorOfListOfTransient.hxx>
51 #include <TopoDS_Edge.hxx>
52 #include <TopoDS_Shape.hxx>
53 #include <TopoDS_Vertex.hxx>
54 #include <TopoDS_Wire.hxx>
55 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
56 #include <TopTools_ListIteratorOfListOfShape.hxx>
58 IMPLEMENT_STANDARD_RTTIEXT(AIS_IdenticRelation,AIS_Relation)
61 static Standard_Real Modulo2PI(const Standard_Real ANGLE)
63 if ( ANGLE < 0 ) return Modulo2PI(ANGLE + 2*M_PI);
64 else if ( ANGLE >= 2*M_PI ) return Modulo2PI(ANGLE - 2*M_PI);
68 static Standard_Boolean IsEqual2PI(const Standard_Real angle1,
69 const Standard_Real angle2, const Standard_Real precision)
71 Standard_Real diff = Abs(angle1-angle2);
72 if ( diff < precision ) return Standard_True;
73 else if ( Abs(diff-2*M_PI) < precision ) return Standard_True;
74 return Standard_False;
78 //=======================================================================
80 //purpose : sort an array of parameters <tab1> in increasing order
81 // updates <tab2> and <tab3> according to <tab1>
82 //=======================================================================
83 static void AIS_Sort(Standard_Real tab1[4],
85 Standard_Integer tab3[4])
87 Standard_Boolean found = Standard_True;
88 Standard_Real cur; gp_Pnt cur1; Standard_Integer cur2;
91 found = Standard_False;
92 for (Standard_Integer i=0; i< 3; i++) {
93 if (tab1[i+1] < tab1[i]) {
94 found = Standard_True;
95 cur = tab1[i]; cur1 = tab2[i]; cur2 = tab3[i];
96 tab1[i] = tab1[i+1]; tab2[i] = tab2[i+1]; tab3[i] = tab3[i+1];
97 tab1[i+1] = cur; tab2[i+1] = cur1; tab3[i+1] = cur2;
103 //=======================================================================
104 //function : ConnectedEdges
106 //=======================================================================
107 static Standard_Boolean ConnectedEdges(const TopoDS_Wire& WIRE,
108 const TopoDS_Vertex& V,
112 TopTools_IndexedDataMapOfShapeListOfShape vertexMap;
113 TopExp::MapShapesAndAncestors (WIRE,TopAbs_VERTEX,TopAbs_EDGE,vertexMap);
115 Standard_Boolean found(Standard_False);
116 TopoDS_Vertex theVertex;
117 for (Standard_Integer i=1; i<=vertexMap.Extent() && !found; i++) {
118 if (vertexMap.FindKey(i).IsSame(V)) {
119 theVertex = TopoDS::Vertex(vertexMap.FindKey(i));
120 found = Standard_True;
126 return Standard_False;
129 TopTools_ListIteratorOfListOfShape iterator(vertexMap.FindFromKey(theVertex));
130 if (iterator.More()) {
131 E1 = TopoDS::Edge(iterator.Value());
136 return Standard_False;
139 if (iterator.More()) {
140 E2 = TopoDS::Edge(iterator.Value());
145 return Standard_False;
148 if (iterator.More()) {
151 return Standard_False;
153 return Standard_True;
157 //=======================================================================
158 //function : ComputeAttach
159 //purpose : Compute a point on the arc of <thecirc>
160 // between <aFAttach> and <aSAttach>
161 // corresponding to <aPosition>
162 // Returns result into <aPosition>
163 // Note : This function is to be used only in the case of circles.
164 // The <aPosition> parameter is in/out.
165 //=======================================================================
166 static Standard_Boolean ComputeAttach(const gp_Circ& thecirc,
167 const gp_Pnt& aFAttach,
168 const gp_Pnt& aSAttach,
171 gp_Pnt curpos = aPosition;
173 // Case of confusion between the current position and the center
174 // of the circle -> we move the current position
175 Standard_Real confusion (Precision::Confusion());
176 gp_Pnt aCenter = thecirc.Location();
177 if ( aCenter.Distance(curpos) <= confusion )
179 gp_Vec vprec(aCenter, aFAttach);
181 curpos.Translate(vprec*1e-5);
184 Standard_Real pcurpos = ElCLib::Parameter(thecirc,curpos);
185 Standard_Real pFAttach = ElCLib::Parameter(thecirc,aFAttach);
186 Standard_Real pSAttach = ElCLib::Parameter(thecirc,aSAttach);
188 Standard_Real pSAttachM = pSAttach;
189 Standard_Real deltap = pSAttachM - pFAttach;
193 pSAttachM += 2 * M_PI;
195 pSAttachM -= pFAttach;
197 Standard_Real pmiddleout = pSAttachM/2.0 + M_PI;
199 Standard_Real pcurpos1 = pcurpos;
200 // define where curpos lays
201 if ( pcurpos1 < pFAttach )
203 pcurpos1 = pcurpos1 + 2 * M_PI - pFAttach;
204 if ( pcurpos1 > pSAttachM ) // out
206 if ( pcurpos1 > pmiddleout ) pcurpos = pFAttach;
207 else pcurpos = pSAttach;
210 else if ( pcurpos1 > (pFAttach + deltap) ) // out
212 pcurpos1 -= pFAttach;
213 if ( pcurpos1 > pmiddleout ) pcurpos = pFAttach;
214 else pcurpos = pSAttach;
217 aPosition = ElCLib::Value(pcurpos,thecirc);
218 return Standard_True;
221 //=======================================================================
222 //function : ComputeAttach
223 //purpose : Compute a point on the arc of ellipse <theEll>
224 // between <aFAttach> and <aSAttach>
225 // corresponding to <aPosition>
226 // Returns result into <aPosition>
227 // Note : This function is to be used only in the case of ellipses.
228 // The <aPosition> parameter is in/out.
229 //=======================================================================
230 static Standard_Boolean ComputeAttach(const gp_Elips& theEll,
231 const gp_Pnt& aFAttach,
232 const gp_Pnt& aSAttach,
235 gp_Pnt curpos = aPosition;
237 // Case of confusion between the current position and the center
238 // of the circle -> we move the current position
239 Standard_Real confusion (Precision::Confusion());
240 gp_Pnt aCenter = theEll.Location();
241 if ( aCenter.Distance(curpos) <= confusion )
243 gp_Vec vprec(aCenter, aFAttach);
245 curpos.Translate(vprec*1e-5);
248 // for ellipses it's not good Standard_Real pcurpos = ElCLib::Parameter(theEll,curpos);
249 Handle(Geom_Ellipse) theEllg = new Geom_Ellipse(theEll);
250 GeomAPI_ProjectPointOnCurve aProj (curpos, theEllg);
251 Standard_Real pcurpos = aProj.LowerDistanceParameter();
253 Standard_Real pFAttach = ElCLib::Parameter(theEll,aFAttach);
254 Standard_Real pSAttach = ElCLib::Parameter(theEll,aSAttach);
256 Standard_Real pSAttachM = pSAttach;
257 Standard_Real deltap = pSAttachM - pFAttach;
261 pSAttachM += 2 * M_PI;
263 pSAttachM -= pFAttach;
265 Standard_Real pmiddleout = pSAttachM/2.0 + M_PI;
267 Standard_Real pcurpos1 = pcurpos;
268 // define where curpos lays
269 if ( pcurpos1 < pFAttach )
271 pcurpos1 = pcurpos1 + 2 * M_PI - pFAttach;
272 if ( pcurpos1 > pSAttachM ) // out
274 if ( pcurpos1 > pmiddleout ) pcurpos = pFAttach;
275 else pcurpos = pSAttach;
278 else if ( pcurpos1 > (pFAttach + deltap) ) // out
280 pcurpos1 -= pFAttach;
281 if ( pcurpos1 > pmiddleout ) pcurpos = pFAttach;
282 else pcurpos = pSAttach;
285 aPosition = ElCLib::Value(pcurpos,theEll);
286 return Standard_True;
288 // jfa 16/10/2000 end
290 //=======================================================================
291 //function : AIS_IdenticRelation
293 //=======================================================================
294 AIS_IdenticRelation::AIS_IdenticRelation(const TopoDS_Shape& FirstShape,
295 const TopoDS_Shape& SecondShape,
296 const Handle(Geom_Plane)& aPlane)
297 :isCircle(Standard_False)
299 myFShape = FirstShape;
300 mySShape = SecondShape;
304 //=======================================================================
307 //=======================================================================
308 void AIS_IdenticRelation::Compute(const Handle(PrsMgr_PresentationManager3d)&,
309 const Handle(Prs3d_Presentation)& aprs,
310 const Standard_Integer)
312 switch ( myFShape.ShapeType() ) {
316 switch ( mySShape.ShapeType() ) {
319 ComputeTwoVerticesPresentation(aprs);
324 ComputeOneEdgeOVertexPresentation(aprs);
335 switch ( mySShape.ShapeType() ) {
338 ComputeOneEdgeOVertexPresentation(aprs);
343 ComputeTwoEdgesPresentation(aprs);
355 //=======================================================================
358 //=======================================================================
359 void AIS_IdenticRelation::Compute(const Handle(Prs3d_Projector)& aProjector,
360 const Handle(Prs3d_Presentation)& aPresentation)
362 // throw Standard_NotImplemented("AIS_IdenticRelation::Compute(const Handle(Prs3d_Projector)&,const Handle(Prs3d_Presentation)&)");
363 PrsMgr_PresentableObject::Compute( aProjector , aPresentation ) ;
366 void AIS_IdenticRelation::Compute(const Handle(Prs3d_Projector)& aProjector, const Handle(Geom_Transformation)& aTransformation, const Handle(Prs3d_Presentation)& aPresentation)
368 // throw Standard_NotImplemented("AIS_IdenticRelation::Compute(const Handle(Prs3d_Projector)&, const Handle(Geom_Transformation)&, const Handle(Prs3d_Presentation)&)");
369 PrsMgr_PresentableObject::Compute( aProjector , aTransformation , aPresentation ) ;
372 //=======================================================================
373 //function : ComputeSelection
374 //purpose : function used to compute the selection associated to the
375 // "identic" presentation
376 // note : if we are in the case of lines, we create a segment between
377 // myFAttach and mySAttach. In the case of Circles, we create
378 // an arc of circle between the sames points. We Add a segment
379 // to link Position to its projection on the curve described
381 //=======================================================================
383 void AIS_IdenticRelation::ComputeSelection(const Handle(SelectMgr_Selection)& aSelection,
384 const Standard_Integer)
386 Handle(SelectMgr_EntityOwner) own = new SelectMgr_EntityOwner(this,7);
388 Handle(Select3D_SensitiveSegment) seg;
389 // attachement point of the segment linking position to the curve
391 Standard_Real confusion (Precision::Confusion());
393 if ( myFAttach.IsEqual(mySAttach, confusion) )
400 if ( myFShape.ShapeType() == TopAbs_EDGE )
402 Handle(Geom_Curve) curv1,curv2;
403 gp_Pnt firstp1,lastp1,firstp2,lastp2;
404 Standard_Boolean isInfinite1,isInfinite2;
405 Handle(Geom_Curve) extCurv;
406 if ( !AIS::ComputeGeometry(TopoDS::Edge(myFShape),TopoDS::Edge(mySShape),
407 myExtShape,curv1,curv2,
408 firstp1,lastp1,firstp2,lastp2,
409 extCurv,isInfinite1,isInfinite2,myPlane) ) return;
411 if ( isCircle ) // case of Circles
413 Handle(Geom_Circle) thecirc = Handle(Geom_Circle)::DownCast (curv1);
414 Standard_Real udeb = ElCLib::Parameter(thecirc->Circ(),myFAttach);
415 Standard_Real ufin = ElCLib::Parameter(thecirc->Circ(),mySAttach);
416 Handle(Geom_Curve) thecu = new Geom_TrimmedCurve(thecirc,udeb,ufin);
418 Handle(Select3D_SensitiveCurve) scurv = new Select3D_SensitiveCurve(own, thecu);
419 aSelection->Add(scurv);
422 ComputeAttach(thecirc->Circ(),myFAttach,mySAttach,attach);
424 else if ( curv1->IsInstance(STANDARD_TYPE(Geom_Ellipse)) ) // case of ellipses
426 Handle(Geom_Ellipse) theEll = Handle(Geom_Ellipse)::DownCast (curv1);
428 Standard_Real udeb = ElCLib::Parameter(theEll->Elips(),myFAttach);
429 Standard_Real ufin = ElCLib::Parameter(theEll->Elips(),mySAttach);
430 Handle(Geom_Curve) thecu = new Geom_TrimmedCurve(theEll,udeb,ufin);
432 Handle(Select3D_SensitiveCurve) scurv = new Select3D_SensitiveCurve(own, thecu);
433 aSelection->Add(scurv);
436 ComputeAttach(theEll->Elips(),myFAttach,mySAttach,attach);
438 else if ( curv1->IsInstance(STANDARD_TYPE(Geom_Line)) ) // case of Lines
440 seg = new Select3D_SensitiveSegment(own, myFAttach, mySAttach);
441 aSelection->Add(seg);
443 //attach = projection of Position() on the curve;
444 gp_Vec v1 (myFAttach, mySAttach);
445 gp_Vec v2 (myFAttach, myPosition);
446 if ( v1.IsParallel(v2, Precision::Angular()) )
452 gp_Lin ll (myFAttach, gp_Dir(v1));
453 attach = ElCLib::Value(ElCLib::Parameter(ll,myPosition), ll);
458 // else if ( myFShape.ShapeType() == TopAbs_VERTEX )
461 // jfa 24/10/2000 end
464 // Creation of the segment linking the attachement point with the
466 if ( !attach.IsEqual(myPosition, confusion) )
468 seg = new Select3D_SensitiveSegment(own, attach, myPosition);
469 aSelection->Add(seg);
473 //=======================================================================
474 //function : ComputeTwoEdgesPresentation
476 //=======================================================================
477 void AIS_IdenticRelation::ComputeTwoEdgesPresentation(const Handle(Prs3d_Presentation)& aPrs)
479 Handle(Geom_Curve) curv1,curv2;
480 gp_Pnt firstp1,lastp1,firstp2,lastp2;
481 Standard_Boolean isInfinite1,isInfinite2;
483 Handle(Geom_Curve) extCurv;
484 if (!AIS::ComputeGeometry(TopoDS::Edge(myFShape),
485 TopoDS::Edge(mySShape),
494 isInfinite1,isInfinite2,
497 aPrs->SetInfiniteState((isInfinite1 || isInfinite2) && myExtShape != 0);
499 // Treatement of the case of lines
500 if ( curv1->IsInstance(STANDARD_TYPE(Geom_Line)) && curv2->IsInstance(STANDARD_TYPE(Geom_Line)) ) {
501 // we take the line curv1 like support
502 Handle(Geom_Line) thelin;
503 if (isInfinite1 && !isInfinite2) thelin = Handle(Geom_Line)::DownCast (curv2);
504 else if (!isInfinite1 && isInfinite2) thelin = Handle(Geom_Line)::DownCast (curv1);
505 else thelin = Handle(Geom_Line)::DownCast (curv1);
506 ComputeTwoLinesPresentation(aPrs, thelin, firstp1, lastp1, firstp2, lastp2, isInfinite1, isInfinite2);
509 // Treatement of the case of circles
510 else if ( curv1->IsInstance(STANDARD_TYPE(Geom_Circle)) && curv2->IsInstance(STANDARD_TYPE(Geom_Circle)) ) {
512 isCircle = Standard_True; // useful for ComputeSelection
513 Handle(Geom_Circle) thecirc (Handle(Geom_Circle)::DownCast (curv1));
514 ComputeTwoCirclesPresentation(aPrs, thecirc, firstp1, lastp1, firstp2, lastp2);
518 // Treatement of the case of ellipses
519 else if ( curv1->IsInstance(STANDARD_TYPE(Geom_Ellipse)) && curv2->IsInstance(STANDARD_TYPE(Geom_Ellipse)) )
521 Handle(Geom_Ellipse) theEll (Handle(Geom_Ellipse)::DownCast (curv1));
522 ComputeTwoEllipsesPresentation(aPrs, theEll, firstp1, lastp1, firstp2, lastp2);
524 // jfa 10/10/2000 end
528 // Calculate presentation of projected edges
529 if ( (myExtShape != 0) && !extCurv.IsNull()) {
530 if (myExtShape == 1 )
531 ComputeProjEdgePresentation(aPrs, TopoDS::Edge(myFShape), curv1, firstp1, lastp1);
533 ComputeProjEdgePresentation(aPrs, TopoDS::Edge(mySShape), curv2, firstp2, lastp2);
537 //=======================================================================
538 //function : ComputeTwoLinesPresentation
539 //purpose : Compute the presentation of the 'identic' constraint
540 // between two lines ( which are equal)
541 //input : <thelin> : the
542 // <firstp1>: first extremity of the 1st curve of the constraint
543 // <lastp1> : last extremity of the 1st curve of the constraint
544 // <firstp2>: first extremity of the 2nd curve of the constraint
545 // <lastp2> :last extremity of the 2nd curve of the constraint
546 //=======================================================================
547 void AIS_IdenticRelation::ComputeTwoLinesPresentation(const Handle(Prs3d_Presentation)& aPrs,
548 const Handle(Geom_Line)& thelin,
553 const Standard_Boolean isInfinite1,
554 const Standard_Boolean isInfinite2)
556 if (isInfinite1 && isInfinite2) {
557 if ( myAutomaticPosition ) {
558 myFAttach = mySAttach = thelin->Lin().Location();
560 gp_Pln pln(myPlane->Pln());
561 gp_Dir dir(pln.XAxis().Direction());
562 gp_Vec transvec = gp_Vec(dir)*myArrowSize;
563 curpos = myFAttach.Translated(transvec);;
565 myAutomaticPosition = Standard_True;
568 myFAttach = mySAttach = ElCLib::Value(ElCLib::Parameter(thelin->Lin(),myPosition),thelin->Lin());
570 TCollection_ExtendedString vals(" ==");
571 DsgPrs_IdenticPresentation::Add(aPrs,
578 // Computation of the parameters of the 4 points on the line <thelin>
579 Standard_Real pf1, pf2, pl1, pl2;
581 pf1 = ElCLib::Parameter(thelin->Lin(), firstp1);
582 pl1 = ElCLib::Parameter(thelin->Lin(), lastp1);
584 pf2 = ElCLib::Parameter(thelin->Lin(), firstp2);
585 pl2 = ElCLib::Parameter(thelin->Lin(), lastp2);
593 else if (isInfinite2) {
600 Standard_Real tabRang1[4]; // array taht contains the parameters of the 4 points
601 // ordered by increasing abscisses.
603 gp_Pnt tabRang2[4]; // array containing the points corresponding to the
604 // parameters in tabRang1
606 Standard_Integer tabRang3[4]; // array containing the number of the curve( 1 or 2)
607 // of which belongs each point of tabRang2
609 // Filling of the arrays
610 tabRang1[0] = pf1; tabRang2[0] = firstp1; tabRang3[0] = 1;
611 tabRang1[1] = pf2; tabRang2[1] = firstp2; tabRang3[1] = 2;
612 tabRang1[2] = pl1; tabRang2[2] = lastp1; tabRang3[2] = 1;
613 tabRang1[3] = pl2; tabRang2[3] = lastp2; tabRang3[3] = 2;
615 // Sort of the array of parameters (tabRang1)
616 AIS_Sort(tabRang1, tabRang2, tabRang3);
618 // Computation of myFAttach and mySAttach according to the
619 // position of the 2 linear edges
623 if ( (tabRang1[0] == tabRang1[1]) && (tabRang1[2] == tabRang1[3]) ) {
624 middle.SetXYZ((tabRang2[1].XYZ() + tabRang2[2].XYZ())/2. );
625 Standard_Real pmiddle = (tabRang1[1] + tabRang1[2]) / 2.;
626 Standard_Real delta = (tabRang1[3] - tabRang1[0])/ 5.;
627 myFAttach = ElCLib::Value(pmiddle-delta, thelin->Lin());
628 mySAttach = ElCLib::Value(pmiddle+delta, thelin->Lin());
631 else if ( tabRang1[1] == tabRang1[2] ) {
632 middle = tabRang2[1];
633 Standard_Real delta1 = tabRang1[1] - tabRang1[0];
634 Standard_Real delta2 = tabRang1[3] - tabRang1[2];
635 if ( delta1 > delta2 ) delta1 = delta2;
636 myFAttach = ElCLib::Value(tabRang1[1]-delta1/2., thelin->Lin());
637 mySAttach = ElCLib::Value(tabRang1[1]+delta1/2., thelin->Lin());
640 // Case of 2 disconnected segments -> the symbol completes the gap
641 // between the 2 edges
642 //--------------------------------
643 else if ( (tabRang3[0] == tabRang3[1]) && (tabRang1[1] != tabRang1[2])) {
644 middle.SetXYZ((tabRang2[1].XYZ() + tabRang2[2].XYZ())/2. );
645 myFAttach = tabRang2[1];
646 mySAttach = tabRang2[2];
648 else if ( (tabRang3[0] != tabRang3[1])
649 && (tabRang3[1] != tabRang3[2]) // Intersection
650 && (tabRang1[1] != tabRang1[2]) ) {
651 middle.SetXYZ((tabRang2[1].XYZ() + tabRang2[2].XYZ())/2. );
652 myFAttach = tabRang2[1];
653 mySAttach = tabRang2[2];
656 myFAttach.SetXYZ((tabRang2[0].XYZ() + tabRang2[1].XYZ())/2. );
657 mySAttach.SetXYZ((tabRang2[1].XYZ() + tabRang2[2].XYZ())/2. );
658 middle.SetXYZ( (myFAttach.XYZ() + mySAttach.XYZ() )/2.);
662 if ( myAutomaticPosition ) {
664 gp_Vec vtrans(myFAttach, mySAttach);
666 vtrans.Cross(gp_Vec(myPlane->Pln().Axis().Direction()));
667 vtrans *= ComputeSegSize();
668 curpos = middle.Translated(vtrans);
670 myAutomaticPosition = Standard_True;
676 Standard_Real pcurpos = ElCLib::Parameter(thelin->Lin() ,curpos);
677 Standard_Real dist = thelin->Lin().Distance(curpos);
678 gp_Pnt proj = ElCLib::Value( pcurpos, thelin->Lin());
680 Standard_Real confusion(Precision::Confusion());
681 if ( dist >= confusion ) {
682 trans = gp_Vec(proj, curpos);
685 Standard_Real pf = ElCLib::Parameter(thelin->Lin() ,myFAttach);
686 Standard_Real pl = ElCLib::Parameter(thelin->Lin() ,mySAttach);
687 if ( pcurpos <= pf ) {
689 curpos = ElCLib::Value( pcurpos, thelin->Lin());
690 if ( dist >= confusion ) curpos.Translate(trans*dist);
692 else if ( pcurpos >= pl ) {
694 curpos = ElCLib::Value( pcurpos, thelin->Lin());
695 if ( dist >= confusion ) curpos.Translate(trans*dist);
700 // Display of the presentation
701 TCollection_ExtendedString vals(" ==");
702 DsgPrs_IdenticPresentation::Add(aPrs,
712 //=======================================================================
713 //function : ComputeTwoCirclesPresentation
714 //purpose : Compute the presentation of the 'identic' constraint
715 // between two circles ( which are equal)
716 //input : <thecirc>: the circle
717 // <firstp1>: first extremity of the 1st curve of the constraint
718 // <lastp1> : last extremity of the 1st curve of the constraint
719 // <firstp2>: first extremity of the 2nd curve of the constraint
720 // <lastp2> :last extremity of the 2nd curve of the constraint
721 //=======================================================================
722 void AIS_IdenticRelation::ComputeTwoCirclesPresentation(const Handle(Prs3d_Presentation)& aPrs,
723 const Handle(Geom_Circle)& thecirc,
724 const gp_Pnt& firstp1,
725 const gp_Pnt& lastp1,
726 const gp_Pnt& firstp2,
727 const gp_Pnt& lastp2)
729 Standard_Real confusion (Precision::Confusion());
731 // Searching of complete circles
732 Standard_Boolean circ1complete = (firstp1.IsEqual(lastp1, confusion));
733 Standard_Boolean circ2complete = (firstp2.IsEqual(lastp2, confusion));
735 myCenter = thecirc->Location();
736 Standard_Real aSegSize = thecirc->Radius()/5.0;
737 Standard_Real rad = M_PI / 5.0;
739 // I. Case of 2 complete circles
740 if ( circ1complete && circ2complete )
742 if (myAutomaticPosition)
744 Standard_Real pfirst1 = ElCLib::Parameter(thecirc->Circ(), firstp1);
745 myFAttach = ElCLib::Value(Modulo2PI(pfirst1-rad), thecirc->Circ());
746 mySAttach = ElCLib::Value(Modulo2PI(pfirst1+rad), thecirc->Circ());
748 gp_Pnt curpos = ElCLib::Value(pfirst1,thecirc->Circ());
749 gp_Vec vtrans(myCenter, curpos);
752 curpos.Translate(vtrans);
755 else ComputeNotAutoCircPresentation(thecirc);
758 // II. Case of one complete circle and one arc
759 else if ( (circ1complete && !circ2complete) || (!circ1complete && circ2complete) )
761 gp_Pnt firstp, lastp;
762 if ( circ1complete && !circ2complete)
773 if (myAutomaticPosition)
775 ComputeAutoArcPresentation(thecirc, firstp, lastp);
779 ComputeNotAutoArcPresentation(thecirc, firstp, lastp);
783 // III and IV. Case of two arcs
784 else if ( !circ1complete && !circ2complete )
786 // We project all the points on the circle
787 Standard_Real pf1, pf2, pl1, pl2;
788 pf1 = ElCLib::Parameter(thecirc->Circ(), firstp1);
789 pf2 = ElCLib::Parameter(thecirc->Circ(), firstp2);
790 pl1 = ElCLib::Parameter(thecirc->Circ(), lastp1);
791 pl2 = ElCLib::Parameter(thecirc->Circ(), lastp2);
793 // III. Arcs with common ends
794 // III.1. First of one and last of another
795 if ( IsEqual2PI(pl1,pf2,confusion) || IsEqual2PI(pf1,pl2,confusion) )
797 gp_Pnt curpos(0.,0.,0.);
798 Standard_Real att=0.;
799 if ( IsEqual2PI(pl1,pf2,confusion) )
804 else if ( IsEqual2PI(pf1,pl2,confusion) )
809 Standard_Real maxrad = Min(Modulo2PI(pl1 - pf1),Modulo2PI(pl2 - pf2))*3/4;
810 if ( rad > maxrad ) rad = maxrad;
811 Standard_Real pFAttach = Modulo2PI(att - rad);
812 Standard_Real pSAttach = Modulo2PI(att + rad);
813 myFAttach = ElCLib::Value(pFAttach, thecirc->Circ());
814 mySAttach = ElCLib::Value(pSAttach, thecirc->Circ());
815 if ( myAutomaticPosition )
817 gp_Vec vtrans(myCenter,curpos);
820 curpos.Translate(vtrans);
824 // III.2. Two first or two last
825 else if ( IsEqual2PI(pf1,pf2,confusion) || IsEqual2PI(pl1,pl2,confusion) )
827 Standard_Real l1 = Modulo2PI(pl1 - pf1);
828 Standard_Real l2 = Modulo2PI(pl2 - pf2);
841 if ( myAutomaticPosition )
843 ComputeAutoArcPresentation(thecirc, firstp, lastp);
847 ComputeNotAutoArcPresentation(thecirc, firstp, lastp);
850 // IV. All others arcs (without common ends)
853 // order the parameters; first will be pf1
854 Standard_Real pl1m = Modulo2PI(pl1 - pf1);
855 Standard_Real pf2m = Modulo2PI(pf2 - pf1);
856 Standard_Real pl2m = Modulo2PI(pl2 - pf1);
858 Standard_Boolean case1 = Standard_False;
859 // 1 - not intersecting arcs
860 // 2 - intersecting arcs, but one doesn't contain another
861 // 3a - first arc contains the second one
862 // 3b - second arc contains the first one
863 // 4 - two intersections
865 gp_Pnt firstp, lastp;
867 if ( pl1m < pf2m ) // 1 or 2b or 3b
869 if ( pl1m < pl2m ) // 1 or 3b
871 if ( pl2m < pf2m ) // 3b
878 case1 = Standard_True;
879 Standard_Real deltap1 = Modulo2PI(pf1 - pl2);
880 Standard_Real deltap2 = Modulo2PI(pf2 - pl1);
881 if ( ((deltap1 < deltap2) && (deltap1 < 2*rad)) ||
882 ((deltap2 < deltap1) && (deltap2 > 2*rad)) ) // deltap2
900 else // 2a or 3a or 4
902 if ( pl1m < pl2m ) // 2a
909 if ( pl2m > pf2m ) // 3a
916 Standard_Real deltap1 = Modulo2PI(pl1 - pf2);
917 Standard_Real deltap2 = Modulo2PI(pl2 - pf1);
918 if ( ((deltap1 < deltap2) && (deltap1 < 2*rad)) ||
919 ((deltap2 < deltap1) && (deltap2 > 2*rad)) ) // deltap2
933 if ( myAutomaticPosition )
935 ComputeAutoArcPresentation(thecirc,firstp,lastp,case1);
944 else ComputeNotAutoArcPresentation(thecirc, firstp, lastp);
949 // Display of the presentation
950 TCollection_ExtendedString vals(" ==");
951 gp_Pnt attach = myPosition;
952 ComputeAttach(thecirc->Circ(),myFAttach,mySAttach,attach);
953 DsgPrs_IdenticPresentation::Add(aPrs,
956 myPlane->Pln().Position().Ax2(),
964 //=======================================================================
965 //function : ComputeAutoArcPresentation
966 //purpose : Compute the presentation of the constraint where we are
967 // not in the case of dragging.
968 //=======================================================================
969 void AIS_IdenticRelation::ComputeAutoArcPresentation(const Handle(Geom_Circle)& thecirc,
970 const gp_Pnt& firstp,
972 const Standard_Boolean isstatic)
974 Standard_Real aSegSize = thecirc->Radius()/5.0;
975 Standard_Real rad = M_PI / 5.0;
977 Standard_Real pFA = ElCLib::Parameter(thecirc->Circ(),firstp);
978 Standard_Real pSA = ElCLib::Parameter(thecirc->Circ(),lastp);
979 Standard_Real maxrad = Modulo2PI(pSA - pFA)/2.0;
981 if ( (rad > maxrad) || isstatic ) rad = maxrad;
982 Standard_Real pmiddle = Modulo2PI(pFA + Modulo2PI(pSA - pFA)/2.0);
984 myFAttach = ElCLib::Value(Modulo2PI(pmiddle - rad),thecirc->Circ());
985 mySAttach = ElCLib::Value(Modulo2PI(pmiddle + rad),thecirc->Circ());
987 gp_Pnt curpos = ElCLib::Value(pmiddle,thecirc->Circ());
988 gp_Vec vtrans(myCenter, curpos);
991 myPosition = curpos.Translated(vtrans);
994 //=======================================================================
995 //function : ComputeNotAutoCircPresentation
996 //purpose : Compute the presentation of the constraint where we are
997 // in the case of dragging.
998 // Note : This function is to be used only in the case of full circles.
999 // The symbol of the constraint moves together with arc
1000 // representing the constraint around all the circle.
1001 //=======================================================================
1002 void AIS_IdenticRelation::ComputeNotAutoCircPresentation(const Handle(Geom_Circle)& thecirc)
1004 gp_Pnt curpos = myPosition;
1006 Handle(Geom_Circle) cirNotAuto = new Geom_Circle(thecirc->Circ());
1008 // Case of confusion between the current position and the center
1009 // of the circle -> we move the current position
1010 Standard_Real confusion (Precision::Confusion());
1011 if ( myCenter.Distance(curpos) <= confusion )
1013 gp_Vec vprec(myCenter, myFAttach);
1015 curpos.Translate(vprec*1e-5);
1018 Standard_Real rad = M_PI / 5.0;
1019 Standard_Real pcurpos = ElCLib::Parameter(cirNotAuto->Circ(),curpos);
1020 Standard_Real pFAttach = pcurpos - rad;
1021 Standard_Real pSAttach = pcurpos + rad;
1022 myFAttach = ElCLib::Value(pFAttach,cirNotAuto->Circ());
1023 mySAttach = ElCLib::Value(pSAttach,cirNotAuto->Circ());
1026 //=======================================================================
1027 //function : ComputeNotAutoArcPresentation
1028 //purpose : Compute the presentation of the constraint where we are
1029 // in the case of dragging.
1030 // Note : This function is to be used only in the case of circles.
1031 // The symbol of the constraint moves only between myFAttach
1033 //=======================================================================
1034 void AIS_IdenticRelation::ComputeNotAutoArcPresentation(const Handle(Geom_Circle)& thecirc,
1035 const gp_Pnt& pntfirst,
1036 const gp_Pnt& pntlast)
1038 gp_Pnt curpos = myPosition;
1040 gp_Circ cirNotAuto = thecirc->Circ();
1042 Standard_Real pFPnt = ElCLib::Parameter(cirNotAuto, pntfirst);
1043 Standard_Real pSPnt = ElCLib::Parameter(cirNotAuto, pntlast);
1044 Standard_Real deltap = Modulo2PI(pSPnt - pFPnt)/2.0;
1046 Standard_Real rad = M_PI / 5;
1049 myFAttach = pntfirst;
1050 mySAttach = pntlast;
1054 gp_Pnt aFPnt = ElCLib::Value(Modulo2PI(pFPnt + rad), cirNotAuto);
1055 gp_Pnt aSPnt = ElCLib::Value(Modulo2PI(pSPnt - rad), cirNotAuto);
1057 ComputeAttach(cirNotAuto,aFPnt,aSPnt,curpos);
1059 Standard_Real pcurpos = ElCLib::Parameter(cirNotAuto,curpos);
1060 myFAttach = ElCLib::Value(pcurpos - rad, cirNotAuto);
1061 mySAttach = ElCLib::Value(pcurpos + rad, cirNotAuto);
1064 // jfa 17/10/2000 end
1067 //=======================================================================
1068 //function : ComputeTwoEllipsesPresentation
1069 //purpose : Compute the presentation of the 'identic' constraint
1070 // between two ellipses (which are equal)
1071 //input : <theEll>: the ellipse
1072 // <firstp1>: first extremity of the 1st curve of the constraint
1073 // <lastp1> : last extremity of the 1st curve of the constraint
1074 // <firstp2>: first extremity of the 2nd curve of the constraint
1075 // <lastp2> :last extremity of the 2nd curve of the constraint
1076 //=======================================================================
1077 void AIS_IdenticRelation::ComputeTwoEllipsesPresentation(const Handle(Prs3d_Presentation)& aPrs,
1078 const Handle(Geom_Ellipse)& theEll,
1079 const gp_Pnt& firstp1,
1080 const gp_Pnt& lastp1,
1081 const gp_Pnt& firstp2,
1082 const gp_Pnt& lastp2)
1084 Standard_Real confusion (Precision::Confusion());
1086 // Searching of complete ellipses
1087 Standard_Boolean circ1complete = (firstp1.IsEqual(lastp1, confusion));
1088 Standard_Boolean circ2complete = (firstp2.IsEqual(lastp2, confusion));
1090 myCenter = theEll->Location();
1091 Standard_Real aSegSize = theEll->MajorRadius()/5.0;
1092 Standard_Real rad = M_PI / 5.0;
1094 // I. Case of 2 complete ellipses
1095 if ( circ1complete && circ2complete )
1097 if (myAutomaticPosition)
1099 Standard_Real pfirst1 = ElCLib::Parameter(theEll->Elips(), firstp1);
1100 myFAttach = ElCLib::Value(Modulo2PI(pfirst1-rad), theEll->Elips());
1101 mySAttach = ElCLib::Value(Modulo2PI(pfirst1+rad), theEll->Elips());
1103 gp_Pnt curpos = ElCLib::Value(pfirst1,theEll->Elips());
1104 gp_Vec vtrans(myCenter, curpos);
1107 curpos.Translate(vtrans);
1108 myPosition = curpos;
1110 else ComputeNotAutoElipsPresentation(theEll);
1113 // II. Case of one complete circle and one arc
1114 else if ( (circ1complete && !circ2complete) || (!circ1complete && circ2complete) )
1116 gp_Pnt firstp, lastp;
1117 if ( circ1complete && !circ2complete)
1128 if (myAutomaticPosition)
1130 ComputeAutoArcPresentation(theEll, firstp, lastp);
1134 ComputeNotAutoArcPresentation(theEll, firstp, lastp);
1138 // III and IV. Case of two arcs
1139 else if ( !circ1complete && !circ2complete )
1141 // We project all the points on the circle
1142 Standard_Real pf1, pf2, pl1, pl2;
1143 pf1 = ElCLib::Parameter(theEll->Elips(), firstp1);
1144 pf2 = ElCLib::Parameter(theEll->Elips(), firstp2);
1145 pl1 = ElCLib::Parameter(theEll->Elips(), lastp1);
1146 pl2 = ElCLib::Parameter(theEll->Elips(), lastp2);
1148 // III. Arcs with common ends
1149 // III.1. First of one and last of another
1150 if ( IsEqual2PI(pl1,pf2,confusion) || IsEqual2PI(pf1,pl2,confusion) )
1153 Standard_Real att=0.;
1154 if ( IsEqual2PI(pl1,pf2,confusion) )
1159 else if ( IsEqual2PI(pf1,pl2,confusion) )
1164 Standard_Real maxrad = Min(Modulo2PI(pl1 - pf1),Modulo2PI(pl2 - pf2))*3/4;
1165 if ( rad > maxrad ) rad = maxrad;
1166 Standard_Real pFAttach = Modulo2PI(att - rad);
1167 Standard_Real pSAttach = Modulo2PI(att + rad);
1168 myFAttach = ElCLib::Value(pFAttach, theEll->Elips());
1169 mySAttach = ElCLib::Value(pSAttach, theEll->Elips());
1170 if ( myAutomaticPosition )
1172 gp_Vec vtrans(myCenter,curpos);
1175 curpos.Translate(vtrans);
1176 myPosition = curpos;
1179 // III.2. Two first or two last
1180 else if ( IsEqual2PI(pf1,pf2,confusion) || IsEqual2PI(pl1,pl2,confusion) )
1182 Standard_Real l1 = Modulo2PI(pl1 - pf1);
1183 Standard_Real l2 = Modulo2PI(pl2 - pf2);
1184 gp_Pnt firstp,lastp;
1196 if ( myAutomaticPosition )
1198 ComputeAutoArcPresentation(theEll, firstp, lastp);
1202 ComputeNotAutoArcPresentation(theEll, firstp, lastp);
1205 // IV. All others arcs (without common ends)
1208 // order the parameters; first will be pf1
1209 Standard_Real pl1m = Modulo2PI(pl1 - pf1);
1210 Standard_Real pf2m = Modulo2PI(pf2 - pf1);
1211 Standard_Real pl2m = Modulo2PI(pl2 - pf1);
1213 Standard_Boolean case1 = Standard_False;
1214 // 1 - not intersecting arcs
1215 // 2 - intersecting arcs, but one doesn't contain another
1216 // 3a - first arc contains the second one
1217 // 3b - second arc contains the first one
1218 // 4 - two intersections
1220 gp_Pnt firstp, lastp;
1222 if ( pl1m < pf2m ) // 1 or 2b or 3b
1224 if ( pl1m < pl2m ) // 1 or 3b
1226 if ( pl2m < pf2m ) // 3b
1233 case1 = Standard_True;
1234 Standard_Real deltap1 = Modulo2PI(pf1 - pl2);
1235 Standard_Real deltap2 = Modulo2PI(pf2 - pl1);
1236 if ( ((deltap1 < deltap2) && (deltap1 < 2*rad)) ||
1237 ((deltap2 < deltap1) && (deltap2 > 2*rad)) ) // deltap2
1255 else // 2a or 3a or 4
1257 if ( pl1m < pl2m ) // 2a
1264 if ( pl2m > pf2m ) // 3a
1271 Standard_Real deltap1 = Modulo2PI(pl1 - pf2);
1272 Standard_Real deltap2 = Modulo2PI(pl2 - pf1);
1273 if ( ((deltap1 < deltap2) && (deltap1 < 2*rad)) ||
1274 ((deltap2 < deltap1) && (deltap2 > 2*rad)) ) // deltap2
1288 if ( myAutomaticPosition )
1290 ComputeAutoArcPresentation(theEll,firstp,lastp,case1);
1299 else ComputeNotAutoArcPresentation(theEll, firstp, lastp);
1304 // Display of the presentation
1305 TCollection_ExtendedString vals(" ==");
1306 gp_Pnt attach = myPosition;
1307 ComputeAttach(theEll->Elips(),myFAttach,mySAttach,attach);
1308 DsgPrs_IdenticPresentation::Add(aPrs,
1318 //=======================================================================
1319 //function : ComputeAutoArcPresentation
1320 //purpose : Compute the presentation of the constraint where we are
1321 // not in the case of dragging.
1322 //=======================================================================
1323 void AIS_IdenticRelation::ComputeAutoArcPresentation(const Handle(Geom_Ellipse)& theEll,
1324 const gp_Pnt& firstp,
1325 const gp_Pnt& lastp,
1326 const Standard_Boolean isstatic)
1328 Standard_Real aSegSize = theEll->MajorRadius()/5.0;
1329 Standard_Real rad = M_PI / 5.0;
1331 gp_Elips anEll = theEll->Elips();
1333 Standard_Real pFA = ElCLib::Parameter(anEll,firstp);
1334 Standard_Real pSA = ElCLib::Parameter(anEll,lastp);
1335 Standard_Real maxrad = Modulo2PI(pSA - pFA)/2.0;
1337 if ( (rad > maxrad) || isstatic ) rad = maxrad;
1338 Standard_Real pmiddle = Modulo2PI(pFA + Modulo2PI(pSA - pFA)/2.0);
1340 myFAttach = ElCLib::Value(Modulo2PI(pmiddle - rad),anEll);
1341 mySAttach = ElCLib::Value(Modulo2PI(pmiddle + rad),anEll);
1343 gp_Pnt curpos = ElCLib::Value(pmiddle,anEll);
1344 gp_Vec vtrans(myCenter, curpos);
1347 myPosition = curpos.Translated(vtrans);
1350 //=======================================================================
1351 //function : ComputeNotAutoElipsPresentation
1352 //purpose : Compute the presentation of the constraint where we are
1353 // in the case of dragging.
1354 // Note : This function is to be used only in the case of ellipses.
1355 // The symbol of the constraint moves only between myFAttach
1357 //=======================================================================
1358 void AIS_IdenticRelation::ComputeNotAutoElipsPresentation(const Handle(Geom_Ellipse)& theEll)
1360 gp_Pnt curpos = myPosition;
1362 gp_Elips anEll = theEll->Elips();
1364 // Case of confusion between the current position and the center
1365 // of the ellipse -> we move the current position
1366 Standard_Real confusion (Precision::Confusion());
1367 if ( myCenter.Distance(curpos) <= confusion )
1369 gp_Vec vprec(myCenter, myFAttach);
1371 curpos.Translate(vprec*1e-5);
1374 Standard_Real rad = M_PI / 5.0;
1375 // Standard_Real pcurpos = ElCLib::Parameter(anEll,curpos);
1376 GeomAPI_ProjectPointOnCurve aProj (curpos, theEll);
1377 Standard_Real pcurpos = aProj.LowerDistanceParameter();
1379 Standard_Real pFAttach = pcurpos - rad;
1380 Standard_Real pSAttach = pcurpos + rad;
1381 myFAttach = ElCLib::Value(pFAttach,anEll);
1382 mySAttach = ElCLib::Value(pSAttach,anEll);
1385 //=======================================================================
1386 //function : ComputeNotAutoArcPresentation
1387 //purpose : Compute the presentation of the constraint where we are
1388 // in the case of dragging.
1389 // Note : This function is to be used only in the case of ellipses.
1390 // The symbol of the constraint moves only between myFAttach
1392 //=======================================================================
1393 void AIS_IdenticRelation::ComputeNotAutoArcPresentation(const Handle(Geom_Ellipse)& theEll,
1394 const gp_Pnt& pntfirst,
1395 const gp_Pnt& pntlast)
1397 gp_Pnt curpos = myPosition;
1399 gp_Elips anEll = theEll->Elips();
1401 Standard_Real pFPnt = ElCLib::Parameter(anEll, pntfirst);
1402 Standard_Real pSPnt = ElCLib::Parameter(anEll, pntlast);
1403 Standard_Real deltap = Modulo2PI(pSPnt - pFPnt)/2.0;
1405 Standard_Real rad = M_PI / 5;
1408 myFAttach = pntfirst;
1409 mySAttach = pntlast;
1413 gp_Pnt aFPnt = ElCLib::Value(Modulo2PI(pFPnt + rad), anEll);
1414 gp_Pnt aSPnt = ElCLib::Value(Modulo2PI(pSPnt - rad), anEll);
1416 ComputeAttach(anEll,aFPnt,aSPnt,curpos);
1418 // Standard_Real pcurpos = ElCLib::Parameter(anEll,curpos);
1419 GeomAPI_ProjectPointOnCurve aProj (curpos, theEll);
1420 Standard_Real pcurpos = aProj.LowerDistanceParameter();
1422 myFAttach = ElCLib::Value(pcurpos - rad, anEll);
1423 mySAttach = ElCLib::Value(pcurpos + rad, anEll);
1426 // jfa 18/10/2000 end
1428 //=======================================================================
1429 //function : ComputeTwoVerticesPresentation
1431 //=======================================================================
1432 void AIS_IdenticRelation::ComputeTwoVerticesPresentation(const Handle(Prs3d_Presentation)& aPrs)
1434 Standard_Boolean isOnPlane1, isOnPlane2;
1435 const TopoDS_Vertex& FVertex = TopoDS::Vertex(myFShape);
1436 const TopoDS_Vertex& SVertex = TopoDS::Vertex(mySShape);
1438 AIS::ComputeGeometry(FVertex, myFAttach, myPlane, isOnPlane1);
1439 AIS::ComputeGeometry(SVertex, mySAttach, myPlane, isOnPlane2);
1441 if (isOnPlane1 && isOnPlane2)
1443 else if ( isOnPlane1 && !isOnPlane2)
1445 else if (!isOnPlane1 && isOnPlane2)
1451 // The attachement points are the points themselves that must be
1453 myFAttach = BRep_Tool::Pnt(FVertex);
1454 mySAttach = myFAttach;
1457 if (myAutomaticPosition)
1459 //Computation of the size of the symbol
1460 Standard_Real symbsize = ComputeSegSize();
1461 if (symbsize <= Precision::Confusion()) symbsize = 1.;
1463 // Computation of the direction of the segment of the presentation
1464 // we take the median of the edges connected to vertices
1467 TColStd_ListIteratorOfListOfTransient it(Users());
1470 Handle(AIS_Shape) USER (Handle(AIS_Shape)::DownCast(it.Value()));
1473 const TopoDS_Shape& SH =USER->Shape();
1474 if ( (!SH.IsNull()) && (SH.ShapeType() == TopAbs_WIRE) )
1476 const TopoDS_Wire& WIRE = TopoDS::Wire(USER->Shape());
1477 Standard_Boolean done = ComputeDirection(WIRE,FVertex,dF);
1479 done = ComputeDirection(WIRE,SVertex,dS);
1486 // computation of the segment direction like average
1487 // of the 2 computed directions.
1488 if ( dF.IsParallel(dS, Precision::Angular()) )
1490 myDir = dF.Crossed(myPlane->Pln().Axis().Direction());
1494 myDir.SetXYZ(dF.XYZ() + dS.XYZ());
1496 curpos = myFAttach.Translated(gp_Vec(myDir)*symbsize) ;
1503 // jfa 11/10/2000 end
1505 myPosition = curpos;
1506 myAutomaticPosition = Standard_False;
1510 curpos = myPosition;
1513 // Presentation computation
1514 TCollection_ExtendedString vals(" ++");
1515 DsgPrs_IdenticPresentation::Add(aPrs,
1520 // Calculate the projection of vertex
1521 if ( myExtShape == 1)
1522 ComputeProjVertexPresentation(aPrs,FVertex,myFAttach);
1523 else if ( myExtShape == 2)
1524 ComputeProjVertexPresentation(aPrs,SVertex,mySAttach);
1529 //=======================================================================
1530 //function : ComputeSegSize
1532 //=======================================================================
1533 Standard_Real AIS_IdenticRelation::ComputeSegSize() const
1538 //=======================================================================
1539 //function : ComputeDirection
1540 //purpose : Compute a direction according to the different geometric
1541 // elements connected to the vertex <VERT>, in way to not have
1542 // overlap between the symbol and them.
1543 //=======================================================================
1544 Standard_Boolean AIS_IdenticRelation::ComputeDirection(const TopoDS_Wire& aWire,
1545 const TopoDS_Vertex& VERT,
1548 // we take the median of the edges connected to vertices
1549 TopoDS_Edge edg1,edg2;
1550 ConnectedEdges(aWire,VERT,edg1,edg2);
1552 if ( edg1.IsNull() && edg2.IsNull() ) {
1553 return Standard_False;
1556 Handle(Geom_Curve) curv1,curv2;
1557 gp_Pnt firstp1,lastp1,firstp2,lastp2;
1559 // Case with 2 edges connected to the vertex <VERT>
1560 if ( !edg1.IsNull() && !edg2.IsNull() ) {
1561 if ( !AIS::ComputeGeometry(edg1,edg2,
1564 firstp2, lastp2,myPlane))
1565 return Standard_False;
1568 if ( curv1->IsInstance(STANDARD_TYPE(Geom_Circle)) ) {
1569 d1 = ComputeCircleDirection(Handle(Geom_Circle)::DownCast (curv1), VERT);
1571 else if (curv1->IsInstance(STANDARD_TYPE(Geom_Line)) ) {
1572 d1 = ComputeLineDirection(Handle(Geom_Line)::DownCast (curv1), firstp1);
1575 return Standard_False;
1577 if ( curv2->IsInstance(STANDARD_TYPE(Geom_Circle)) ) {
1578 d2 = ComputeCircleDirection( Handle(Geom_Circle)::DownCast (curv2), VERT);
1580 else if (curv2->IsInstance(STANDARD_TYPE(Geom_Line)) ) {
1581 d2 =ComputeLineDirection( Handle(Geom_Line)::DownCast (curv2), firstp2);
1584 return Standard_False;
1586 if ( !d1.IsParallel(d2, Precision::Angular() ))
1587 dF.SetXYZ( (d1.XYZ() + d2.XYZ())/2 );
1589 dF= d1.Crossed(myPlane->Pln().Axis().Direction());
1593 // Case where <VERT> is at an extremity of a wire.
1596 if ( !edg1.IsNull() )
1598 else if (!edg2.IsNull() )
1601 return Standard_False;
1603 if ( !AIS::ComputeGeometry(VEdge, curv1, firstp1, lastp1) )
1604 return Standard_False;
1605 if ( curv1->IsInstance(STANDARD_TYPE(Geom_Circle)) ) {
1606 dF = ComputeCircleDirection( Handle(Geom_Circle)::DownCast (curv1), VERT);
1608 else if (curv1->IsInstance(STANDARD_TYPE(Geom_Line)) ) {
1609 dF = ComputeLineDirection( Handle(Geom_Line)::DownCast (curv1), firstp1);
1612 return Standard_False;
1615 return Standard_True;
1618 //=======================================================================
1619 //function : ComputeLineDirection
1621 //=======================================================================
1622 gp_Dir AIS_IdenticRelation::ComputeLineDirection(const Handle(Geom_Line)& lin,
1623 const gp_Pnt& firstP) const
1626 dir = lin->Lin().Direction();
1627 if ( !myFAttach.IsEqual(firstP, Precision::Confusion()) )
1632 //=======================================================================
1633 //function : ComputeCircleDirection
1635 //=======================================================================
1636 gp_Dir AIS_IdenticRelation::ComputeCircleDirection(const Handle(Geom_Circle)& circ,
1637 const TopoDS_Vertex& VERT) const
1639 gp_Vec V(circ->Location(),BRep_Tool::Pnt(VERT));
1643 //=======================================================================
1644 //function : ComputeOneEdgeOVertexPresentation
1646 //=======================================================================
1647 void AIS_IdenticRelation::ComputeOneEdgeOVertexPresentation(const Handle(Prs3d_Presentation)& aPrs)
1651 Standard_Integer numedge;
1653 if (myFShape.ShapeType() == TopAbs_VERTEX) {
1654 V = TopoDS::Vertex(myFShape);
1655 E = TopoDS::Edge(mySShape);
1656 numedge = 2;// edge = 2nd shape
1659 V = TopoDS::Vertex(mySShape);
1660 E = TopoDS::Edge(myFShape);
1661 numedge = 1; // edge = 1st shape
1663 gp_Pnt ptonedge1,ptonedge2;
1664 Handle(Geom_Curve) aCurve;
1665 Handle(Geom_Curve) extCurv;
1666 Standard_Boolean isInfinite;
1667 Standard_Boolean isOnPlanEdge, isOnPlanVertex;
1668 if (!AIS::ComputeGeometry(E,aCurve,ptonedge1,ptonedge2,extCurv,isInfinite,isOnPlanEdge,myPlane))
1670 aPrs->SetInfiniteState(isInfinite);
1671 AIS::ComputeGeometry(V, myFAttach, myPlane, isOnPlanVertex);
1673 // only the curve can be projected
1674 if (!isOnPlanEdge && !isOnPlanVertex) return;
1676 if (!isOnPlanEdge) {
1677 if (numedge == 1) myExtShape = 1;
1678 else myExtShape = 2;
1680 else if (!isOnPlanVertex) {
1681 if (numedge == 1) myExtShape = 2;
1682 else myExtShape = 1;
1684 // The attachement points are the point
1685 myFAttach = BRep_Tool::Pnt(V);
1686 mySAttach = myFAttach;
1689 if (myAutomaticPosition) {
1690 //Computation of the size of the symbol
1691 Standard_Real symbsize = ComputeSegSize();
1693 // Computation of the direction of the segment of the presentation
1694 // we take the median of the edges connected to vertices
1696 if ( aCurve->IsKind(STANDARD_TYPE(Geom_Line))) {
1697 myDir = Handle(Geom_Line)::DownCast (aCurve)->Lin().Direction();
1698 myDir.Cross(myPlane->Pln().Axis().Direction());
1700 else if (aCurve->IsKind(STANDARD_TYPE(Geom_Circle))) {
1701 Handle(Geom_Circle) CIR = Handle(Geom_Circle)::DownCast (aCurve);
1702 myDir.SetXYZ(myFAttach.XYZ() - CIR->Location().XYZ());
1705 else if (aCurve->IsKind(STANDARD_TYPE(Geom_Ellipse))) {
1706 Handle(Geom_Ellipse) CIR = Handle(Geom_Ellipse)::DownCast (aCurve);
1707 myDir.SetXYZ(myFAttach.XYZ() - CIR->Location().XYZ());
1709 // jfa 10/10/2000 end
1711 curpos = myFAttach.Translated(gp_Vec(myDir)*symbsize) ;
1712 myPosition = curpos;
1713 myAutomaticPosition = Standard_True;
1716 curpos = myPosition;
1719 // Presentation computation
1720 TCollection_ExtendedString vals(" -+-");
1721 DsgPrs_IdenticPresentation::Add(aPrs,
1726 if (myExtShape != 0) {
1727 if (!extCurv.IsNull()) { // the edge is not in the WP
1728 ComputeProjEdgePresentation(aPrs,E,Handle(Geom_Line)::DownCast (aCurve),ptonedge1,ptonedge2);