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