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