0030153: Visualization, TKOpenGl - AIS_ColoredShape::SynchronizeAspects() doesn't...
[occt.git] / src / AIS / AIS_IdenticRelation.cxx
CommitLineData
b311480e 1// Created on: 1997-03-03
2// Created by: Jean-Pierre COMBE
3// Copyright (c) 1997-1999 Matra Datavision
973c2be1 4// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 5//
973c2be1 6// This file is part of Open CASCADE Technology software library.
b311480e 7//
d5f74e42 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
973c2be1 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.
b311480e 13//
973c2be1 14// Alternatively, this file may be used under the terms of Open CASCADE
15// commercial license or contractual agreement.
7fd59977 16
7fd59977 17
18#include <AIS.hxx>
42cf5bc1 19#include <AIS_IdenticRelation.hxx>
7fd59977 20#include <AIS_Shape.hxx>
7fd59977 21#include <BRep_Tool.hxx>
7fd59977 22#include <DsgPrs_IdenticPresentation.hxx>
7fd59977 23#include <ElCLib.hxx>
7fd59977 24#include <Geom_Circle.hxx>
42cf5bc1 25#include <Geom_Ellipse.hxx>
7fd59977 26#include <Geom_Line.hxx>
27#include <Geom_Plane.hxx>
42cf5bc1 28#include <Geom_Transformation.hxx>
7fd59977 29#include <Geom_TrimmedCurve.hxx>
42cf5bc1 30#include <GeomAPI_ProjectPointOnCurve.hxx>
31#include <gp_Dir.hxx>
32#include <gp_Pln.hxx>
33#include <gp_Pnt.hxx>
34#include <gp_Vec.hxx>
7fd59977 35#include <Precision.hxx>
7fd59977 36#include <Prs3d_Drawer.hxx>
37#include <Prs3d_LineAspect.hxx>
42cf5bc1 38#include <Prs3d_Presentation.hxx>
39#include <Prs3d_Projector.hxx>
7fd59977 40#include <Select3D_SensitiveCurve.hxx>
41#include <Select3D_SensitiveSegment.hxx>
42#include <SelectMgr_EntityOwner.hxx>
f751596e 43#include <SelectMgr_Selection.hxx>
42cf5bc1 44#include <Standard_NotImplemented.hxx>
45#include <Standard_Type.hxx>
7fd59977 46#include <TCollection_ExtendedString.hxx>
42cf5bc1 47#include <TColStd_ListIteratorOfListOfTransient.hxx>
7fd59977 48#include <TopAbs.hxx>
49#include <TopExp.hxx>
50#include <TopoDS.hxx>
51#include <TopoDS_Edge.hxx>
42cf5bc1 52#include <TopoDS_Shape.hxx>
7fd59977 53#include <TopoDS_Vertex.hxx>
54#include <TopoDS_Wire.hxx>
55#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
56#include <TopTools_ListIteratorOfListOfShape.hxx>
57
92efcf78 58IMPLEMENT_STANDARD_RTTIEXT(AIS_IdenticRelation,AIS_Relation)
59
7fd59977 60// jfa 15/10/2000
7fd59977 61static Standard_Real Modulo2PI(const Standard_Real ANGLE)
62{
c6541a0c
D
63 if ( ANGLE < 0 ) return Modulo2PI(ANGLE + 2*M_PI);
64 else if ( ANGLE >= 2*M_PI ) return Modulo2PI(ANGLE - 2*M_PI);
7fd59977 65 return ANGLE;
66}
67
68static Standard_Boolean IsEqual2PI(const Standard_Real angle1,
69 const Standard_Real angle2, const Standard_Real precision)
70{
71 Standard_Real diff = Abs(angle1-angle2);
72 if ( diff < precision ) return Standard_True;
c6541a0c 73 else if ( Abs(diff-2*M_PI) < precision ) return Standard_True;
7fd59977 74 return Standard_False;
75}
76// jfa 15/10/2000 end
77
78//=======================================================================
79//function : AIS_Sort
80//purpose : sort an array of parameters <tab1> in increasing order
81// updates <tab2> and <tab3> according to <tab1>
82//=======================================================================
83static void AIS_Sort(Standard_Real tab1[4],
84 gp_Pnt tab2[4],
85 Standard_Integer tab3[4])
86{
87 Standard_Boolean found = Standard_True;
88 Standard_Real cur; gp_Pnt cur1; Standard_Integer cur2;
89
90 while (found) {
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;
98 }
99 }
100 }
101}
102
103//=======================================================================
104//function : ConnectedEdges
105//purpose :
106//=======================================================================
107static Standard_Boolean ConnectedEdges(const TopoDS_Wire& WIRE,
108 const TopoDS_Vertex& V,
109 TopoDS_Edge& E1,
110 TopoDS_Edge& E2)
111{
112 TopTools_IndexedDataMapOfShapeListOfShape vertexMap;
113 TopExp::MapShapesAndAncestors (WIRE,TopAbs_VERTEX,TopAbs_EDGE,vertexMap);
114
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;
121 }
122 }
123 if (!found) {
124 E1.Nullify();
125 E2.Nullify();
126 return Standard_False;
127 }
128
129 TopTools_ListIteratorOfListOfShape iterator(vertexMap.FindFromKey(theVertex));
130 if (iterator.More()) {
131 E1 = TopoDS::Edge(iterator.Value());
132 iterator.Next();
133 }
134 else {
135 E1.Nullify();
136 return Standard_False;
137 }
138
139 if (iterator.More()) {
140 E2 = TopoDS::Edge(iterator.Value());
141 iterator.Next();
142 }
143 else {
144 E2.Nullify();
145 return Standard_False;
146 }
147
148 if (iterator.More()) {
149 E1.Nullify();
150 E2.Nullify();
151 return Standard_False;
152 }
153 return Standard_True;
154}
155
156// jfa 16/10/2000
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//=======================================================================
166static Standard_Boolean ComputeAttach(const gp_Circ& thecirc,
167 const gp_Pnt& aFAttach,
168 const gp_Pnt& aSAttach,
169 gp_Pnt& aPosition)
170{
171 gp_Pnt curpos = aPosition;
172
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 )
178 {
179 gp_Vec vprec(aCenter, aFAttach);
180 vprec.Normalize();
181 curpos.Translate(vprec*1e-5);
182 }
183
184 Standard_Real pcurpos = ElCLib::Parameter(thecirc,curpos);
185 Standard_Real pFAttach = ElCLib::Parameter(thecirc,aFAttach);
186 Standard_Real pSAttach = ElCLib::Parameter(thecirc,aSAttach);
187
188 Standard_Real pSAttachM = pSAttach;
189 Standard_Real deltap = pSAttachM - pFAttach;
190 if ( deltap < 0 )
191 {
c6541a0c
D
192 deltap += 2 * M_PI;
193 pSAttachM += 2 * M_PI;
7fd59977 194 }
195 pSAttachM -= pFAttach;
196
c6541a0c 197 Standard_Real pmiddleout = pSAttachM/2.0 + M_PI;
7fd59977 198
199 Standard_Real pcurpos1 = pcurpos;
200 // define where curpos lays
201 if ( pcurpos1 < pFAttach )
202 {
c6541a0c 203 pcurpos1 = pcurpos1 + 2 * M_PI - pFAttach;
7fd59977 204 if ( pcurpos1 > pSAttachM ) // out
205 {
206 if ( pcurpos1 > pmiddleout ) pcurpos = pFAttach;
207 else pcurpos = pSAttach;
208 }
209 }
210 else if ( pcurpos1 > (pFAttach + deltap) ) // out
211 {
212 pcurpos1 -= pFAttach;
213 if ( pcurpos1 > pmiddleout ) pcurpos = pFAttach;
214 else pcurpos = pSAttach;
215 }
216
217 aPosition = ElCLib::Value(pcurpos,thecirc);
218 return Standard_True;
219}
220
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//=======================================================================
230static Standard_Boolean ComputeAttach(const gp_Elips& theEll,
231 const gp_Pnt& aFAttach,
232 const gp_Pnt& aSAttach,
233 gp_Pnt& aPosition)
234{
235 gp_Pnt curpos = aPosition;
236
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 )
242 {
243 gp_Vec vprec(aCenter, aFAttach);
244 vprec.Normalize();
245 curpos.Translate(vprec*1e-5);
246 }
247
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();
252
253 Standard_Real pFAttach = ElCLib::Parameter(theEll,aFAttach);
254 Standard_Real pSAttach = ElCLib::Parameter(theEll,aSAttach);
255
256 Standard_Real pSAttachM = pSAttach;
257 Standard_Real deltap = pSAttachM - pFAttach;
258 if ( deltap < 0 )
259 {
c6541a0c
D
260 deltap += 2 * M_PI;
261 pSAttachM += 2 * M_PI;
7fd59977 262 }
263 pSAttachM -= pFAttach;
264
c6541a0c 265 Standard_Real pmiddleout = pSAttachM/2.0 + M_PI;
7fd59977 266
267 Standard_Real pcurpos1 = pcurpos;
268 // define where curpos lays
269 if ( pcurpos1 < pFAttach )
270 {
c6541a0c 271 pcurpos1 = pcurpos1 + 2 * M_PI - pFAttach;
7fd59977 272 if ( pcurpos1 > pSAttachM ) // out
273 {
274 if ( pcurpos1 > pmiddleout ) pcurpos = pFAttach;
275 else pcurpos = pSAttach;
276 }
277 }
278 else if ( pcurpos1 > (pFAttach + deltap) ) // out
279 {
280 pcurpos1 -= pFAttach;
281 if ( pcurpos1 > pmiddleout ) pcurpos = pFAttach;
282 else pcurpos = pSAttach;
283 }
284
285 aPosition = ElCLib::Value(pcurpos,theEll);
286 return Standard_True;
287}
288// jfa 16/10/2000 end
289
290//=======================================================================
291//function : AIS_IdenticRelation
292//purpose :
293//=======================================================================
294AIS_IdenticRelation::AIS_IdenticRelation(const TopoDS_Shape& FirstShape,
295 const TopoDS_Shape& SecondShape,
296 const Handle(Geom_Plane)& aPlane)
297 :isCircle(Standard_False)
298{
299 myFShape = FirstShape;
300 mySShape = SecondShape;
301 myPlane = aPlane;
302}
303
304//=======================================================================
305//function : Compute
306//purpose :
307//=======================================================================
308void AIS_IdenticRelation::Compute(const Handle(PrsMgr_PresentationManager3d)&,
309 const Handle(Prs3d_Presentation)& aprs,
310 const Standard_Integer)
311{
7fd59977 312 switch ( myFShape.ShapeType() ) {
313
314 case TopAbs_VERTEX:
315 {
316 switch ( mySShape.ShapeType() ) {
317 case TopAbs_VERTEX:
318 {
319 ComputeTwoVerticesPresentation(aprs);
320 }
321 break;
322 case TopAbs_EDGE:
323 {
324 ComputeOneEdgeOVertexPresentation(aprs);
325 }
326 break;
327 default:
328 break;
329 }
330 }
331 break;
332
333 case TopAbs_EDGE:
334 {
335 switch ( mySShape.ShapeType() ) {
336 case TopAbs_VERTEX:
337 {
338 ComputeOneEdgeOVertexPresentation(aprs);
339 }
340 break;
341 case TopAbs_EDGE:
342 {
343 ComputeTwoEdgesPresentation(aprs);
344 }
345 break;
346 default:
347 break;
348 }
349 }
350 break;
351 default: break;
352 }
353}
354
355//=======================================================================
356//function : Compute
357//purpose :
358//=======================================================================
359void AIS_IdenticRelation::Compute(const Handle(Prs3d_Projector)& aProjector,
360 const Handle(Prs3d_Presentation)& aPresentation)
361{
9775fa61 362// throw Standard_NotImplemented("AIS_IdenticRelation::Compute(const Handle(Prs3d_Projector)&,const Handle(Prs3d_Presentation)&)");
7fd59977 363 PrsMgr_PresentableObject::Compute( aProjector , aPresentation ) ;
364}
365
857ffd5e 366void AIS_IdenticRelation::Compute(const Handle(Prs3d_Projector)& aProjector, const Handle(Geom_Transformation)& aTransformation, const Handle(Prs3d_Presentation)& aPresentation)
7fd59977 367{
9775fa61 368// throw Standard_NotImplemented("AIS_IdenticRelation::Compute(const Handle(Prs3d_Projector)&, const Handle(Geom_Transformation)&, const Handle(Prs3d_Presentation)&)");
7fd59977 369 PrsMgr_PresentableObject::Compute( aProjector , aTransformation , aPresentation ) ;
370}
371
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
81bba717 378// an arc of circle between the sames points. We Add a segment
7fd59977 379// to link Position to its projection on the curve described
380// before.
381//=======================================================================
382
383void AIS_IdenticRelation::ComputeSelection(const Handle(SelectMgr_Selection)& aSelection,
384 const Standard_Integer)
385{
386 Handle(SelectMgr_EntityOwner) own = new SelectMgr_EntityOwner(this,7);
387
388 Handle(Select3D_SensitiveSegment) seg;
389 // attachement point of the segment linking position to the curve
390 gp_Pnt attach;
391 Standard_Real confusion (Precision::Confusion());
392
393 if ( myFAttach.IsEqual(mySAttach, confusion) )
394 {
395 attach = myFAttach;
396 }
397 else
398 {
399// jfa 24/10/2000
400 if ( myFShape.ShapeType() == TopAbs_EDGE )
401 {
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;
410
411 if ( isCircle ) // case of Circles
412 {
c5f3a425 413 Handle(Geom_Circle) thecirc = Handle(Geom_Circle)::DownCast (curv1);
7fd59977 414 Standard_Real udeb = ElCLib::Parameter(thecirc->Circ(),myFAttach);
415 Standard_Real ufin = ElCLib::Parameter(thecirc->Circ(),mySAttach);
543a9964 416 Handle(Geom_Curve) thecu = new Geom_TrimmedCurve(thecirc,udeb,ufin);
7fd59977 417
418 Handle(Select3D_SensitiveCurve) scurv = new Select3D_SensitiveCurve(own, thecu);
419 aSelection->Add(scurv);
420
421 attach = myPosition;
422 ComputeAttach(thecirc->Circ(),myFAttach,mySAttach,attach);
423 }
424 else if ( curv1->IsInstance(STANDARD_TYPE(Geom_Ellipse)) ) // case of ellipses
425 {
c5f3a425 426 Handle(Geom_Ellipse) theEll = Handle(Geom_Ellipse)::DownCast (curv1);
7fd59977 427
428 Standard_Real udeb = ElCLib::Parameter(theEll->Elips(),myFAttach);
429 Standard_Real ufin = ElCLib::Parameter(theEll->Elips(),mySAttach);
543a9964 430 Handle(Geom_Curve) thecu = new Geom_TrimmedCurve(theEll,udeb,ufin);
7fd59977 431
432 Handle(Select3D_SensitiveCurve) scurv = new Select3D_SensitiveCurve(own, thecu);
433 aSelection->Add(scurv);
434
435 attach = myPosition;
436 ComputeAttach(theEll->Elips(),myFAttach,mySAttach,attach);
437 }
438 else if ( curv1->IsInstance(STANDARD_TYPE(Geom_Line)) ) // case of Lines
439 {
440 seg = new Select3D_SensitiveSegment(own, myFAttach, mySAttach);
441 aSelection->Add(seg);
442
81bba717 443 //attach = projection of Position() on the curve;
7fd59977 444 gp_Vec v1 (myFAttach, mySAttach);
445 gp_Vec v2 (myFAttach, myPosition);
446 if ( v1.IsParallel(v2, Precision::Angular()) )
447 {
448 attach = mySAttach;
449 }
450 else
451 {
452 gp_Lin ll (myFAttach, gp_Dir(v1));
453 attach = ElCLib::Value(ElCLib::Parameter(ll,myPosition), ll);
454 }
455 }
456 else return;
457 }
458// else if ( myFShape.ShapeType() == TopAbs_VERTEX )
459// {
460// }
461// jfa 24/10/2000 end
462 }
463
464 // Creation of the segment linking the attachement point with the
465 // position
466 if ( !attach.IsEqual(myPosition, confusion) )
467 {
468 seg = new Select3D_SensitiveSegment(own, attach, myPosition);
469 aSelection->Add(seg);
470 }
471}
472
473//=======================================================================
474//function : ComputeTwoEdgesPresentation
475//purpose :
476//=======================================================================
477void AIS_IdenticRelation::ComputeTwoEdgesPresentation(const Handle(Prs3d_Presentation)& aPrs)
478{
479 Handle(Geom_Curve) curv1,curv2;
480 gp_Pnt firstp1,lastp1,firstp2,lastp2;
481 Standard_Boolean isInfinite1,isInfinite2;
482
483 Handle(Geom_Curve) extCurv;
484 if (!AIS::ComputeGeometry(TopoDS::Edge(myFShape),
485 TopoDS::Edge(mySShape),
486 myExtShape,
487 curv1,
488 curv2,
489 firstp1,
490 lastp1,
491 firstp2,
492 lastp2,
493 extCurv,
494 isInfinite1,isInfinite2,
495 myPlane))
496 return;
497 aPrs->SetInfiniteState((isInfinite1 || isInfinite2) && myExtShape != 0);
498
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;
c5f3a425 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);
7fd59977 506 ComputeTwoLinesPresentation(aPrs, thelin, firstp1, lastp1, firstp2, lastp2, isInfinite1, isInfinite2);
507 }
508
509 // Treatement of the case of circles
510 else if ( curv1->IsInstance(STANDARD_TYPE(Geom_Circle)) && curv2->IsInstance(STANDARD_TYPE(Geom_Circle)) ) {
511 //gp_Pnt curpos;
81bba717 512 isCircle = Standard_True; // useful for ComputeSelection
c5f3a425 513 Handle(Geom_Circle) thecirc (Handle(Geom_Circle)::DownCast (curv1));
7fd59977 514 ComputeTwoCirclesPresentation(aPrs, thecirc, firstp1, lastp1, firstp2, lastp2);
515 }
516
517 // jfa 10/10/2000
518 // Treatement of the case of ellipses
519 else if ( curv1->IsInstance(STANDARD_TYPE(Geom_Ellipse)) && curv2->IsInstance(STANDARD_TYPE(Geom_Ellipse)) )
520 {
c5f3a425 521 Handle(Geom_Ellipse) theEll (Handle(Geom_Ellipse)::DownCast (curv1));
7fd59977 522 ComputeTwoEllipsesPresentation(aPrs, theEll, firstp1, lastp1, firstp2, lastp2);
523 }
524 // jfa 10/10/2000 end
525 else
526 return;
527
81bba717 528 // Calculate presentation of projected edges
7fd59977 529 if ( (myExtShape != 0) && !extCurv.IsNull()) {
530 if (myExtShape == 1 )
531 ComputeProjEdgePresentation(aPrs, TopoDS::Edge(myFShape), curv1, firstp1, lastp1);
532 else
533 ComputeProjEdgePresentation(aPrs, TopoDS::Edge(mySShape), curv2, firstp2, lastp2);
534 }
535}
536
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//=======================================================================
547void AIS_IdenticRelation::ComputeTwoLinesPresentation(const Handle(Prs3d_Presentation)& aPrs,
548 const Handle(Geom_Line)& thelin,
549 gp_Pnt& firstp1,
550 gp_Pnt& lastp1,
551 gp_Pnt& firstp2,
552 gp_Pnt& lastp2,
553 const Standard_Boolean isInfinite1,
554 const Standard_Boolean isInfinite2)
555{
556 if (isInfinite1 && isInfinite2) {
557 if ( myAutomaticPosition ) {
558 myFAttach = mySAttach = thelin->Lin().Location();
559 gp_Pnt curpos;
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);;
564 myPosition = curpos;
565 myAutomaticPosition = Standard_True;
566 }
567 else {
568 myFAttach = mySAttach = ElCLib::Value(ElCLib::Parameter(thelin->Lin(),myPosition),thelin->Lin());
569 }
570 TCollection_ExtendedString vals(" ==");
571 DsgPrs_IdenticPresentation::Add(aPrs,
572 myDrawer,
573 vals,
574 myFAttach,
575 myPosition);
576 }
577 else {
578 // Computation of the parameters of the 4 points on the line <thelin>
579 Standard_Real pf1, pf2, pl1, pl2;
580
581 pf1 = ElCLib::Parameter(thelin->Lin(), firstp1);
582 pl1 = ElCLib::Parameter(thelin->Lin(), lastp1);
583
584 pf2 = ElCLib::Parameter(thelin->Lin(), firstp2);
585 pl2 = ElCLib::Parameter(thelin->Lin(), lastp2);
586
587 if (isInfinite1) {
588 pf1 = pf2;
589 pl1 = pl2;
590 firstp1 = firstp2;
591 lastp1 = lastp2;
592 }
593 else if (isInfinite2) {
594 pf2 = pf1;
595 pl2 = pl1;
596 firstp2 = firstp1;
597 lastp2 = lastp1;
598 }
599
600 Standard_Real tabRang1[4]; // array taht contains the parameters of the 4 points
601 // ordered by increasing abscisses.
602
603 gp_Pnt tabRang2[4]; // array containing the points corresponding to the
604 // parameters in tabRang1
605
606 Standard_Integer tabRang3[4]; // array containing the number of the curve( 1 or 2)
607 // of which belongs each point of tabRang2
608
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;
614
615 // Sort of the array of parameters (tabRang1)
616 AIS_Sort(tabRang1, tabRang2, tabRang3);
617
618 // Computation of myFAttach and mySAttach according to the
619 // position of the 2 linear edges
620 gp_Pnt curpos;
621 gp_Pnt middle;
622
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());
629 }
630
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());
638 }
639
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];
647 }
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];
654 }
655 else { // Inclusion
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.);
659 }
660
661
662 if ( myAutomaticPosition ) {
663
664 gp_Vec vtrans(myFAttach, mySAttach);
665 vtrans.Normalize();
666 vtrans.Cross(gp_Vec(myPlane->Pln().Axis().Direction()));
667 vtrans *= ComputeSegSize();
668 curpos = middle.Translated(vtrans);
669 myPosition = curpos;
670 myAutomaticPosition = Standard_True;
671 }
672
673 else {
674
675 curpos = myPosition;
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());
679 gp_Vec trans;
680 Standard_Real confusion(Precision::Confusion());
681 if ( dist >= confusion ) {
682 trans = gp_Vec(proj, curpos);
683 trans.Normalize();
684 }
685 Standard_Real pf = ElCLib::Parameter(thelin->Lin() ,myFAttach);
686 Standard_Real pl = ElCLib::Parameter(thelin->Lin() ,mySAttach);
687 if ( pcurpos <= pf ) {
688 pcurpos = pf + 1e-5;
689 curpos = ElCLib::Value( pcurpos, thelin->Lin());
690 if ( dist >= confusion ) curpos.Translate(trans*dist);
691 }
692 else if ( pcurpos >= pl ) {
693 pcurpos = pl - 1e-5;
694 curpos = ElCLib::Value( pcurpos, thelin->Lin());
695 if ( dist >= confusion ) curpos.Translate(trans*dist);
696 }
697 SetPosition(curpos);
698 }
699
700 // Display of the presentation
701 TCollection_ExtendedString vals(" ==");
702 DsgPrs_IdenticPresentation::Add(aPrs,
703 myDrawer,
704 vals,
705 myFAttach,
706 mySAttach,
707 curpos);
708 }
709}
710
711// jfa 17/10/2000
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//=======================================================================
722void 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)
728{
729 Standard_Real confusion (Precision::Confusion());
730
731 // Searching of complete circles
732 Standard_Boolean circ1complete = (firstp1.IsEqual(lastp1, confusion));
733 Standard_Boolean circ2complete = (firstp2.IsEqual(lastp2, confusion));
734
735 myCenter = thecirc->Location();
736 Standard_Real aSegSize = thecirc->Radius()/5.0;
c6541a0c 737 Standard_Real rad = M_PI / 5.0;
7fd59977 738
739 // I. Case of 2 complete circles
740 if ( circ1complete && circ2complete )
741 {
742 if (myAutomaticPosition)
743 {
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());
747
748 gp_Pnt curpos = ElCLib::Value(pfirst1,thecirc->Circ());
749 gp_Vec vtrans(myCenter, curpos);
750 vtrans.Normalize();
751 vtrans *= aSegSize;
752 curpos.Translate(vtrans);
753 myPosition = curpos;
754 }
755 else ComputeNotAutoCircPresentation(thecirc);
756 }
757
758 // II. Case of one complete circle and one arc
759 else if ( (circ1complete && !circ2complete) || (!circ1complete && circ2complete) )
760 {
761 gp_Pnt firstp, lastp;
762 if ( circ1complete && !circ2complete)
763 {
764 firstp = firstp2;
765 lastp = lastp2;
766 }
767 else
768 {
769 firstp = firstp1;
770 lastp = lastp1;
771 }
772
773 if (myAutomaticPosition)
774 {
775 ComputeAutoArcPresentation(thecirc, firstp, lastp);
776 }
777 else
778 {
779 ComputeNotAutoArcPresentation(thecirc, firstp, lastp);
780 }
781 }
782
783 // III and IV. Case of two arcs
784 else if ( !circ1complete && !circ2complete )
785 {
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);
792
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) )
796 {
797 gp_Pnt curpos(0.,0.,0.);
798 Standard_Real att=0.;
799 if ( IsEqual2PI(pl1,pf2,confusion) )
800 {
801 att = pl1;
802 curpos = lastp1;
803 }
804 else if ( IsEqual2PI(pf1,pl2,confusion) )
805 {
806 att = pf1;
807 curpos = firstp1;
808 }
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 )
816 {
817 gp_Vec vtrans(myCenter,curpos);
818 vtrans.Normalize();
819 vtrans *= aSegSize;
820 curpos.Translate(vtrans);
821 myPosition = curpos;
822 }
823 }
824 // III.2. Two first or two last
825 else if ( IsEqual2PI(pf1,pf2,confusion) || IsEqual2PI(pl1,pl2,confusion) )
826 {
827 Standard_Real l1 = Modulo2PI(pl1 - pf1);
828 Standard_Real l2 = Modulo2PI(pl2 - pf2);
829 gp_Pnt firstp,lastp;
830 if ( l1 < l2 )
831 {
832 firstp = firstp1;
833 lastp = lastp1;
834 }
835 else
836 {
837 firstp = firstp2;
838 lastp = lastp2;
839 }
840
841 if ( myAutomaticPosition )
842 {
843 ComputeAutoArcPresentation(thecirc, firstp, lastp);
844 }
845 else
846 {
847 ComputeNotAutoArcPresentation(thecirc, firstp, lastp);
848 }
849 }
850 // IV. All others arcs (without common ends)
851 else
852 {
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);
857
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
864
865 gp_Pnt firstp, lastp;
866
867 if ( pl1m < pf2m ) // 1 or 2b or 3b
868 {
869 if ( pl1m < pl2m ) // 1 or 3b
870 {
871 if ( pl2m < pf2m ) // 3b
872 {
873 firstp = firstp1;
874 lastp = lastp1;
875 }
876 else // 1
877 {
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
883 {
884 firstp = lastp1;
885 lastp = firstp2;
886 }
887 else // deltap1
888 {
889 firstp = lastp2;
890 lastp = firstp1;
891 }
892 }
893 }
894 else // 2b
895 {
896 firstp = firstp1;
897 lastp = lastp2;
898 }
899 }
900 else // 2a or 3a or 4
901 {
902 if ( pl1m < pl2m ) // 2a
903 {
904 firstp = firstp2;
905 lastp = lastp1;
906 }
907 else // 3a or 4
908 {
909 if ( pl2m > pf2m ) // 3a
910 {
911 firstp = firstp2;
912 lastp = lastp2;
913 }
914 else // 4
915 {
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
920 {
921 firstp = firstp1;
922 lastp = lastp2;
923 }
924 else // deltap1
925 {
926 firstp = firstp2;
927 lastp = lastp1;
928 }
929 }
930 }
931 }
932
933 if ( myAutomaticPosition )
934 {
935 ComputeAutoArcPresentation(thecirc,firstp,lastp,case1);
936 }
937 else
938 {
939 if ( case1 )
940 {
941 myFAttach = firstp;
942 mySAttach = lastp;
943 }
944 else ComputeNotAutoArcPresentation(thecirc, firstp, lastp);
945 }
946 }
947 }
948
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,
954 myDrawer,
955 vals,
956 myPlane->Pln().Position().Ax2(),
957 myCenter,
958 myFAttach,
959 mySAttach,
960 myPosition,
961 attach);
962}
963
964//=======================================================================
965//function : ComputeAutoArcPresentation
966//purpose : Compute the presentation of the constraint where we are
967// not in the case of dragging.
968//=======================================================================
969void AIS_IdenticRelation::ComputeAutoArcPresentation(const Handle(Geom_Circle)& thecirc,
970 const gp_Pnt& firstp,
971 const gp_Pnt& lastp,
972 const Standard_Boolean isstatic)
973{
974 Standard_Real aSegSize = thecirc->Radius()/5.0;
c6541a0c 975 Standard_Real rad = M_PI / 5.0;
7fd59977 976
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;
980
981 if ( (rad > maxrad) || isstatic ) rad = maxrad;
982 Standard_Real pmiddle = Modulo2PI(pFA + Modulo2PI(pSA - pFA)/2.0);
983
984 myFAttach = ElCLib::Value(Modulo2PI(pmiddle - rad),thecirc->Circ());
985 mySAttach = ElCLib::Value(Modulo2PI(pmiddle + rad),thecirc->Circ());
986
987 gp_Pnt curpos = ElCLib::Value(pmiddle,thecirc->Circ());
988 gp_Vec vtrans(myCenter, curpos);
989 vtrans.Normalize();
990 vtrans *= aSegSize;
991 myPosition = curpos.Translated(vtrans);
992}
993
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//=======================================================================
1002void AIS_IdenticRelation::ComputeNotAutoCircPresentation(const Handle(Geom_Circle)& thecirc)
1003{
1004 gp_Pnt curpos = myPosition;
1005
1006 Handle(Geom_Circle) cirNotAuto = new Geom_Circle(thecirc->Circ());
1007
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 )
1012 {
1013 gp_Vec vprec(myCenter, myFAttach);
1014 vprec.Normalize();
1015 curpos.Translate(vprec*1e-5);
1016 }
1017
c6541a0c 1018 Standard_Real rad = M_PI / 5.0;
7fd59977 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());
1024}
1025
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
1032// and mySAttach.
1033//=======================================================================
1034void AIS_IdenticRelation::ComputeNotAutoArcPresentation(const Handle(Geom_Circle)& thecirc,
1035 const gp_Pnt& pntfirst,
1036 const gp_Pnt& pntlast)
1037{
1038 gp_Pnt curpos = myPosition;
1039
1040 gp_Circ cirNotAuto = thecirc->Circ();
1041
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;
1045
c6541a0c 1046 Standard_Real rad = M_PI / 5;
7fd59977 1047 if ( deltap < rad )
1048 {
1049 myFAttach = pntfirst;
1050 mySAttach = pntlast;
1051 }
1052 else
1053 {
1054 gp_Pnt aFPnt = ElCLib::Value(Modulo2PI(pFPnt + rad), cirNotAuto);
1055 gp_Pnt aSPnt = ElCLib::Value(Modulo2PI(pSPnt - rad), cirNotAuto);
1056
1057 ComputeAttach(cirNotAuto,aFPnt,aSPnt,curpos);
1058
1059 Standard_Real pcurpos = ElCLib::Parameter(cirNotAuto,curpos);
1060 myFAttach = ElCLib::Value(pcurpos - rad, cirNotAuto);
1061 mySAttach = ElCLib::Value(pcurpos + rad, cirNotAuto);
1062 }
1063}
1064// jfa 17/10/2000 end
1065
1066// jfa 18/10/2000
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//=======================================================================
1077void 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)
1083{
1084 Standard_Real confusion (Precision::Confusion());
1085
1086 // Searching of complete ellipses
1087 Standard_Boolean circ1complete = (firstp1.IsEqual(lastp1, confusion));
1088 Standard_Boolean circ2complete = (firstp2.IsEqual(lastp2, confusion));
1089
1090 myCenter = theEll->Location();
1091 Standard_Real aSegSize = theEll->MajorRadius()/5.0;
c6541a0c 1092 Standard_Real rad = M_PI / 5.0;
7fd59977 1093
1094 // I. Case of 2 complete ellipses
1095 if ( circ1complete && circ2complete )
1096 {
1097 if (myAutomaticPosition)
1098 {
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());
1102
1103 gp_Pnt curpos = ElCLib::Value(pfirst1,theEll->Elips());
1104 gp_Vec vtrans(myCenter, curpos);
1105 vtrans.Normalize();
1106 vtrans *= aSegSize;
1107 curpos.Translate(vtrans);
1108 myPosition = curpos;
1109 }
1110 else ComputeNotAutoElipsPresentation(theEll);
1111 }
1112
1113 // II. Case of one complete circle and one arc
1114 else if ( (circ1complete && !circ2complete) || (!circ1complete && circ2complete) )
1115 {
1116 gp_Pnt firstp, lastp;
1117 if ( circ1complete && !circ2complete)
1118 {
1119 firstp = firstp2;
1120 lastp = lastp2;
1121 }
1122 else
1123 {
1124 firstp = firstp1;
1125 lastp = lastp1;
1126 }
1127
1128 if (myAutomaticPosition)
1129 {
1130 ComputeAutoArcPresentation(theEll, firstp, lastp);
1131 }
1132 else
1133 {
1134 ComputeNotAutoArcPresentation(theEll, firstp, lastp);
1135 }
1136 }
1137
1138 // III and IV. Case of two arcs
1139 else if ( !circ1complete && !circ2complete )
1140 {
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);
1147
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) )
1151 {
1152 gp_Pnt curpos;
1153 Standard_Real att=0.;
1154 if ( IsEqual2PI(pl1,pf2,confusion) )
1155 {
1156 att = pl1;
1157 curpos = lastp1;
1158 }
1159 else if ( IsEqual2PI(pf1,pl2,confusion) )
1160 {
1161 att = pf1;
1162 curpos = firstp1;
1163 }
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 )
1171 {
1172 gp_Vec vtrans(myCenter,curpos);
1173 vtrans.Normalize();
1174 vtrans *= aSegSize;
1175 curpos.Translate(vtrans);
1176 myPosition = curpos;
1177 }
1178 }
1179 // III.2. Two first or two last
1180 else if ( IsEqual2PI(pf1,pf2,confusion) || IsEqual2PI(pl1,pl2,confusion) )
1181 {
1182 Standard_Real l1 = Modulo2PI(pl1 - pf1);
1183 Standard_Real l2 = Modulo2PI(pl2 - pf2);
1184 gp_Pnt firstp,lastp;
1185 if ( l1 < l2 )
1186 {
1187 firstp = firstp1;
1188 lastp = lastp1;
1189 }
1190 else
1191 {
1192 firstp = firstp2;
1193 lastp = lastp2;
1194 }
1195
1196 if ( myAutomaticPosition )
1197 {
1198 ComputeAutoArcPresentation(theEll, firstp, lastp);
1199 }
1200 else
1201 {
1202 ComputeNotAutoArcPresentation(theEll, firstp, lastp);
1203 }
1204 }
1205 // IV. All others arcs (without common ends)
1206 else
1207 {
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);
1212
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
1219
1220 gp_Pnt firstp, lastp;
1221
1222 if ( pl1m < pf2m ) // 1 or 2b or 3b
1223 {
1224 if ( pl1m < pl2m ) // 1 or 3b
1225 {
1226 if ( pl2m < pf2m ) // 3b
1227 {
1228 firstp = firstp1;
1229 lastp = lastp1;
1230 }
1231 else // 1
1232 {
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
1238 {
1239 firstp = lastp1;
1240 lastp = firstp2;
1241 }
1242 else // deltap1
1243 {
1244 firstp = lastp2;
1245 lastp = firstp1;
1246 }
1247 }
1248 }
1249 else // 2b
1250 {
1251 firstp = firstp1;
1252 lastp = lastp2;
1253 }
1254 }
1255 else // 2a or 3a or 4
1256 {
1257 if ( pl1m < pl2m ) // 2a
1258 {
1259 firstp = firstp2;
1260 lastp = lastp1;
1261 }
1262 else // 3a or 4
1263 {
1264 if ( pl2m > pf2m ) // 3a
1265 {
1266 firstp = firstp2;
1267 lastp = lastp2;
1268 }
1269 else // 4
1270 {
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
1275 {
1276 firstp = firstp1;
1277 lastp = lastp2;
1278 }
1279 else // deltap1
1280 {
1281 firstp = firstp2;
1282 lastp = lastp1;
1283 }
1284 }
1285 }
1286 }
1287
1288 if ( myAutomaticPosition )
1289 {
1290 ComputeAutoArcPresentation(theEll,firstp,lastp,case1);
1291 }
1292 else
1293 {
1294 if ( case1 )
1295 {
1296 myFAttach = firstp;
1297 mySAttach = lastp;
1298 }
1299 else ComputeNotAutoArcPresentation(theEll, firstp, lastp);
1300 }
1301 }
1302 }
1303
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,
1309 myDrawer,
1310 vals,
1311 theEll->Elips(),
1312 myFAttach,
1313 mySAttach,
1314 myPosition,
1315 attach);
1316}
1317
1318//=======================================================================
1319//function : ComputeAutoArcPresentation
1320//purpose : Compute the presentation of the constraint where we are
1321// not in the case of dragging.
1322//=======================================================================
1323void AIS_IdenticRelation::ComputeAutoArcPresentation(const Handle(Geom_Ellipse)& theEll,
1324 const gp_Pnt& firstp,
1325 const gp_Pnt& lastp,
1326 const Standard_Boolean isstatic)
1327{
1328 Standard_Real aSegSize = theEll->MajorRadius()/5.0;
c6541a0c 1329 Standard_Real rad = M_PI / 5.0;
7fd59977 1330
1331 gp_Elips anEll = theEll->Elips();
1332
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;
1336
1337 if ( (rad > maxrad) || isstatic ) rad = maxrad;
1338 Standard_Real pmiddle = Modulo2PI(pFA + Modulo2PI(pSA - pFA)/2.0);
1339
1340 myFAttach = ElCLib::Value(Modulo2PI(pmiddle - rad),anEll);
1341 mySAttach = ElCLib::Value(Modulo2PI(pmiddle + rad),anEll);
1342
1343 gp_Pnt curpos = ElCLib::Value(pmiddle,anEll);
1344 gp_Vec vtrans(myCenter, curpos);
1345 vtrans.Normalize();
1346 vtrans *= aSegSize;
1347 myPosition = curpos.Translated(vtrans);
1348}
1349
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
1356// and mySAttach.
1357//=======================================================================
1358void AIS_IdenticRelation::ComputeNotAutoElipsPresentation(const Handle(Geom_Ellipse)& theEll)
1359{
1360 gp_Pnt curpos = myPosition;
1361
1362 gp_Elips anEll = theEll->Elips();
1363
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 )
1368 {
1369 gp_Vec vprec(myCenter, myFAttach);
1370 vprec.Normalize();
1371 curpos.Translate(vprec*1e-5);
1372 }
1373
c6541a0c 1374 Standard_Real rad = M_PI / 5.0;
7fd59977 1375// Standard_Real pcurpos = ElCLib::Parameter(anEll,curpos);
1376 GeomAPI_ProjectPointOnCurve aProj (curpos, theEll);
1377 Standard_Real pcurpos = aProj.LowerDistanceParameter();
1378
1379 Standard_Real pFAttach = pcurpos - rad;
1380 Standard_Real pSAttach = pcurpos + rad;
1381 myFAttach = ElCLib::Value(pFAttach,anEll);
1382 mySAttach = ElCLib::Value(pSAttach,anEll);
1383}
1384
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
1391// and mySAttach.
1392//=======================================================================
1393void AIS_IdenticRelation::ComputeNotAutoArcPresentation(const Handle(Geom_Ellipse)& theEll,
1394 const gp_Pnt& pntfirst,
1395 const gp_Pnt& pntlast)
1396{
1397 gp_Pnt curpos = myPosition;
1398
1399 gp_Elips anEll = theEll->Elips();
1400
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;
1404
c6541a0c 1405 Standard_Real rad = M_PI / 5;
7fd59977 1406 if ( deltap < rad )
1407 {
1408 myFAttach = pntfirst;
1409 mySAttach = pntlast;
1410 }
1411 else
1412 {
1413 gp_Pnt aFPnt = ElCLib::Value(Modulo2PI(pFPnt + rad), anEll);
1414 gp_Pnt aSPnt = ElCLib::Value(Modulo2PI(pSPnt - rad), anEll);
1415
1416 ComputeAttach(anEll,aFPnt,aSPnt,curpos);
1417
1418// Standard_Real pcurpos = ElCLib::Parameter(anEll,curpos);
1419 GeomAPI_ProjectPointOnCurve aProj (curpos, theEll);
1420 Standard_Real pcurpos = aProj.LowerDistanceParameter();
1421
1422 myFAttach = ElCLib::Value(pcurpos - rad, anEll);
1423 mySAttach = ElCLib::Value(pcurpos + rad, anEll);
1424 }
1425}
1426// jfa 18/10/2000 end
1427
1428//=======================================================================
1429//function : ComputeTwoVerticesPresentation
1430//purpose :
1431//=======================================================================
1432void AIS_IdenticRelation::ComputeTwoVerticesPresentation(const Handle(Prs3d_Presentation)& aPrs)
1433{
1434 Standard_Boolean isOnPlane1, isOnPlane2;
1435 const TopoDS_Vertex& FVertex = TopoDS::Vertex(myFShape);
1436 const TopoDS_Vertex& SVertex = TopoDS::Vertex(mySShape);
1437
1438 AIS::ComputeGeometry(FVertex, myFAttach, myPlane, isOnPlane1);
1439 AIS::ComputeGeometry(SVertex, mySAttach, myPlane, isOnPlane2);
1440
1441 if (isOnPlane1 && isOnPlane2)
1442 myExtShape = 0;
1443 else if ( isOnPlane1 && !isOnPlane2)
1444 myExtShape = 2;
1445 else if (!isOnPlane1 && isOnPlane2)
1446 myExtShape = 1;
1447 else
1448 return ;
1449
1450
1451 // The attachement points are the points themselves that must be
1452 //identical
1453 myFAttach = BRep_Tool::Pnt(FVertex);
1454 mySAttach = myFAttach;
1455
1456 gp_Pnt curpos;
1457 if (myAutomaticPosition)
1458 {
1459 //Computation of the size of the symbol
1460 Standard_Real symbsize = ComputeSegSize();
1461 if (symbsize <= Precision::Confusion()) symbsize = 1.;
1462 symbsize*=5;
1463 // Computation of the direction of the segment of the presentation
1464 // we take the median of the edges connected to vertices
1465 gp_Dir dF, dS;
1466 gp_Dir myDir;
1467 TColStd_ListIteratorOfListOfTransient it(Users());
1468 if (it.More())
1469 {
c5f3a425 1470 Handle(AIS_Shape) USER (Handle(AIS_Shape)::DownCast(it.Value()));
7fd59977 1471 if (!USER.IsNull())
1472 {
1473 const TopoDS_Shape& SH =USER->Shape();
1474 if ( (!SH.IsNull()) && (SH.ShapeType() == TopAbs_WIRE) )
1475 {
1476 const TopoDS_Wire& WIRE = TopoDS::Wire(USER->Shape());
1477 Standard_Boolean done = ComputeDirection(WIRE,FVertex,dF);
1478 if (!done) return;
1479 done = ComputeDirection(WIRE,SVertex,dS);
1480 if (!done) return;
1481 }
1482 else return;
1483 }
1484 else return;
1485
1486 // computation of the segment direction like average
1487 // of the 2 computed directions.
1488 if ( dF.IsParallel(dS, Precision::Angular()) )
1489 {
1490 myDir = dF.Crossed(myPlane->Pln().Axis().Direction());
1491 }
1492 else
1493 {
1494 myDir.SetXYZ(dF.XYZ() + dS.XYZ());
1495 }
1496 curpos = myFAttach.Translated(gp_Vec(myDir)*symbsize) ;
1497 }
1498// jfa 11/10/2000
1499 else
1500 {
1501 curpos = myFAttach;
1502 }
1503// jfa 11/10/2000 end
1504
1505 myPosition = curpos;
1506 myAutomaticPosition = Standard_False;
1507 }
1508 else
1509 {
1510 curpos = myPosition;
1511 }
1512
1513 // Presentation computation
1514 TCollection_ExtendedString vals(" ++");
1515 DsgPrs_IdenticPresentation::Add(aPrs,
1516 myDrawer,
1517 vals,
1518 myFAttach,
1519 curpos);
81bba717 1520 // Calculate the projection of vertex
7fd59977 1521 if ( myExtShape == 1)
1522 ComputeProjVertexPresentation(aPrs,FVertex,myFAttach);
1523 else if ( myExtShape == 2)
1524 ComputeProjVertexPresentation(aPrs,SVertex,mySAttach);
1525}
1526
1527
1528
1529//=======================================================================
1530//function : ComputeSegSize
1531//purpose :
1532//=======================================================================
1533Standard_Real AIS_IdenticRelation::ComputeSegSize() const
1534{
1535 return 1.;
1536}
1537
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
81bba717 1542// overlap between the symbol and them.
7fd59977 1543//=======================================================================
1544Standard_Boolean AIS_IdenticRelation::ComputeDirection(const TopoDS_Wire& aWire,
1545 const TopoDS_Vertex& VERT,
1546 gp_Dir& dF) const
1547{
1548 // we take the median of the edges connected to vertices
1549 TopoDS_Edge edg1,edg2;
1550 ConnectedEdges(aWire,VERT,edg1,edg2);
1551
1552 if ( edg1.IsNull() && edg2.IsNull() ) {
1553 return Standard_False;
1554 }
1555
1556 Handle(Geom_Curve) curv1,curv2;
1557 gp_Pnt firstp1,lastp1,firstp2,lastp2;
1558
1559 // Case with 2 edges connected to the vertex <VERT>
1560 if ( !edg1.IsNull() && !edg2.IsNull() ) {
1561 if ( !AIS::ComputeGeometry(edg1,edg2,
1562 curv1,curv2,
1563 firstp1, lastp1,
1564 firstp2, lastp2,myPlane))
1565 return Standard_False;
1566
1567 gp_Dir d1, d2;
1568 if ( curv1->IsInstance(STANDARD_TYPE(Geom_Circle)) ) {
c5f3a425 1569 d1 = ComputeCircleDirection(Handle(Geom_Circle)::DownCast (curv1), VERT);
7fd59977 1570 }
1571 else if (curv1->IsInstance(STANDARD_TYPE(Geom_Line)) ) {
c5f3a425 1572 d1 = ComputeLineDirection(Handle(Geom_Line)::DownCast (curv1), firstp1);
7fd59977 1573 }
1574 else
1575 return Standard_False;
1576
1577 if ( curv2->IsInstance(STANDARD_TYPE(Geom_Circle)) ) {
c5f3a425 1578 d2 = ComputeCircleDirection( Handle(Geom_Circle)::DownCast (curv2), VERT);
7fd59977 1579 }
1580 else if (curv2->IsInstance(STANDARD_TYPE(Geom_Line)) ) {
c5f3a425 1581 d2 =ComputeLineDirection( Handle(Geom_Line)::DownCast (curv2), firstp2);
7fd59977 1582 }
1583 else
1584 return Standard_False;
1585
1586 if ( !d1.IsParallel(d2, Precision::Angular() ))
1587 dF.SetXYZ( (d1.XYZ() + d2.XYZ())/2 );
1588 else {
1589 dF= d1.Crossed(myPlane->Pln().Axis().Direction());
1590 }
1591 }
1592
1593 // Case where <VERT> is at an extremity of a wire.
1594 else {
1595 TopoDS_Edge VEdge;
1596 if ( !edg1.IsNull() )
1597 VEdge = edg1;
1598 else if (!edg2.IsNull() )
1599 VEdge = edg2;
1600 else
1601 return Standard_False;
1602
1603 if ( !AIS::ComputeGeometry(VEdge, curv1, firstp1, lastp1) )
1604 return Standard_False;
1605 if ( curv1->IsInstance(STANDARD_TYPE(Geom_Circle)) ) {
c5f3a425 1606 dF = ComputeCircleDirection( Handle(Geom_Circle)::DownCast (curv1), VERT);
7fd59977 1607 }
1608 else if (curv1->IsInstance(STANDARD_TYPE(Geom_Line)) ) {
c5f3a425 1609 dF = ComputeLineDirection( Handle(Geom_Line)::DownCast (curv1), firstp1);
7fd59977 1610 }
1611 else
1612 return Standard_False;
1613 }
1614
1615 return Standard_True;
1616}
1617
1618//=======================================================================
1619//function : ComputeLineDirection
1620//purpose :
1621//=======================================================================
1622gp_Dir AIS_IdenticRelation::ComputeLineDirection(const Handle(Geom_Line)& lin,
1623 const gp_Pnt& firstP) const
1624{
1625 gp_Dir dir;
1626 dir = lin->Lin().Direction();
1627 if ( !myFAttach.IsEqual(firstP, Precision::Confusion()) )
1628 dir.Reverse();
1629 return dir;
1630}
1631
1632//=======================================================================
1633//function : ComputeCircleDirection
1634//purpose :
1635//=======================================================================
1636gp_Dir AIS_IdenticRelation::ComputeCircleDirection(const Handle(Geom_Circle)& circ,
1637 const TopoDS_Vertex& VERT) const
1638{
1639 gp_Vec V(circ->Location(),BRep_Tool::Pnt(VERT));
1640 return gp_Dir(V);
1641}
1642
1643//=======================================================================
1644//function : ComputeOneEdgeOVertexPresentation
1645//purpose :
1646//=======================================================================
1647void AIS_IdenticRelation::ComputeOneEdgeOVertexPresentation(const Handle(Prs3d_Presentation)& aPrs)
1648{
1649 TopoDS_Vertex V;
1650 TopoDS_Edge E;
1651 Standard_Integer numedge;
1652
1653 if (myFShape.ShapeType() == TopAbs_VERTEX) {
1654 V = TopoDS::Vertex(myFShape);
1655 E = TopoDS::Edge(mySShape);
81bba717 1656 numedge = 2;// edge = 2nd shape
7fd59977 1657 }
1658 else {
1659 V = TopoDS::Vertex(mySShape);
1660 E = TopoDS::Edge(myFShape);
81bba717 1661 numedge = 1; // edge = 1st shape
7fd59977 1662 }
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))
1669 return;
1670 aPrs->SetInfiniteState(isInfinite);
1671 AIS::ComputeGeometry(V, myFAttach, myPlane, isOnPlanVertex);
1672
81bba717 1673 // only the curve can be projected
7fd59977 1674 if (!isOnPlanEdge && !isOnPlanVertex) return;
1675
1676 if (!isOnPlanEdge) {
1677 if (numedge == 1) myExtShape = 1;
1678 else myExtShape = 2;
1679 }
1680 else if (!isOnPlanVertex) {
1681 if (numedge == 1) myExtShape = 2;
1682 else myExtShape = 1;
1683 }
1684 // The attachement points are the point
1685 myFAttach = BRep_Tool::Pnt(V);
1686 mySAttach = myFAttach;
1687
1688 gp_Pnt curpos;
1689 if (myAutomaticPosition) {
1690 //Computation of the size of the symbol
1691 Standard_Real symbsize = ComputeSegSize();
1692 symbsize*=5;
1693 // Computation of the direction of the segment of the presentation
1694 // we take the median of the edges connected to vertices
1695 gp_Dir myDir;
1696 if ( aCurve->IsKind(STANDARD_TYPE(Geom_Line))) {
c5f3a425 1697 myDir = Handle(Geom_Line)::DownCast (aCurve)->Lin().Direction();
7fd59977 1698 myDir.Cross(myPlane->Pln().Axis().Direction());
1699 }
1700 else if (aCurve->IsKind(STANDARD_TYPE(Geom_Circle))) {
c5f3a425 1701 Handle(Geom_Circle) CIR = Handle(Geom_Circle)::DownCast (aCurve);
7fd59977 1702 myDir.SetXYZ(myFAttach.XYZ() - CIR->Location().XYZ());
1703 }
1704 // jfa 10/10/2000
1705 else if (aCurve->IsKind(STANDARD_TYPE(Geom_Ellipse))) {
c5f3a425 1706 Handle(Geom_Ellipse) CIR = Handle(Geom_Ellipse)::DownCast (aCurve);
7fd59977 1707 myDir.SetXYZ(myFAttach.XYZ() - CIR->Location().XYZ());
1708 }
1709 // jfa 10/10/2000 end
1710
1711 curpos = myFAttach.Translated(gp_Vec(myDir)*symbsize) ;
1712 myPosition = curpos;
1713 myAutomaticPosition = Standard_True;
1714 }
1715 else {
1716 curpos = myPosition;
1717 }
1718
1719 // Presentation computation
1720 TCollection_ExtendedString vals(" -+-");
1721 DsgPrs_IdenticPresentation::Add(aPrs,
1722 myDrawer,
1723 vals,
1724 myFAttach,
1725 curpos);
1726 if (myExtShape != 0) {
81bba717 1727 if (!extCurv.IsNull()) { // the edge is not in the WP
c5f3a425 1728 ComputeProjEdgePresentation(aPrs,E,Handle(Geom_Line)::DownCast (aCurve),ptonedge1,ptonedge2);
7fd59977 1729 }
1730 }
1731}