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