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