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