1 // Created on: 1996-12-05
2 // Created by: Flore Lantheaume/Odile Olivier
3 // Copyright (c) 1996-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 #include <PrsDim_FixRelation.hxx>
18
19 #include <PrsDim.hxx>
20 #include <BRep_Tool.hxx>
21 #include <BRepAdaptor_Curve.hxx>
22 #include <DsgPrs_FixPresentation.hxx>
23 #include <ElCLib.hxx>
24 #include <ElSLib.hxx>
25 #include <Geom_Circle.hxx>
26 #include <Geom_Curve.hxx>
27 #include <Geom_Line.hxx>
28 #include <Geom_Plane.hxx>
29 #include <gp_Ax1.hxx>
30 #include <gp_Circ.hxx>
31 #include <gp_Dir.hxx>
32 #include <gp_Lin.hxx>
33 #include <gp_Pnt.hxx>
34 #include <gp_Vec.hxx>
35 #include <gp_XYZ.hxx>
36 #include <Precision.hxx>
37 #include <Prs3d_Presentation.hxx>
38 #include <Select3D_SensitiveSegment.hxx>
39 #include <SelectMgr_EntityOwner.hxx>
40 #include <SelectMgr_Selection.hxx>
41 #include <Standard_DomainError.hxx>
42 #include <Standard_NotImplemented.hxx>
43 #include <TColStd_ListIteratorOfListOfTransient.hxx>
44 #include <TopAbs_ShapeEnum.hxx>
45 #include <TopExp.hxx>
46 #include <TopLoc_Location.hxx>
47 #include <TopoDS.hxx>
48 #include <TopoDS_Edge.hxx>
49 #include <TopoDS_Shape.hxx>
50 #include <TopoDS_Vertex.hxx>
51 #include <TopoDS_Wire.hxx>
52 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
53 #include <TopTools_IndexedMapOfShape.hxx>
54 #include <TopTools_ListIteratorOfListOfShape.hxx>
55
IMPLEMENT_STANDARD_RTTIEXT(PrsDim_FixRelation,PrsDim_Relation)56 IMPLEMENT_STANDARD_RTTIEXT(PrsDim_FixRelation, PrsDim_Relation)
57
58 static Standard_Boolean InDomain(const Standard_Real fpar,
59 const Standard_Real lpar,
60 const Standard_Real para)
61 {
62 if (fpar >= 0.) {
63 return ((para >= fpar) && (para <= lpar));
64 }
65 if (para >= (fpar+2*M_PI)) return Standard_True;
66 if (para <= lpar) return Standard_True;
67 return Standard_False;
68 }
69
70 //=======================================================================
71 //function : Constructor
72 //purpose : vertex Fix Relation
73 //=======================================================================
74
PrsDim_FixRelation(const TopoDS_Shape & aShape,const Handle (Geom_Plane)& aPlane,const TopoDS_Wire & aWire)75 PrsDim_FixRelation::PrsDim_FixRelation(const TopoDS_Shape& aShape,
76 const Handle(Geom_Plane)& aPlane,
77 const TopoDS_Wire& aWire)
78 : PrsDim_Relation(),
79 myWire(aWire)
80 {
81 myFShape = aShape;
82 myPlane = aPlane;
83 myAutomaticPosition = Standard_True;
84 myArrowSize = 5.;
85 }
86
87 //=======================================================================
88 //function : Constructor
89 //purpose : vertex Fix Relation
90 //=======================================================================
91
PrsDim_FixRelation(const TopoDS_Shape & aShape,const Handle (Geom_Plane)& aPlane,const TopoDS_Wire & aWire,const gp_Pnt & aPosition,const Standard_Real anArrowSize)92 PrsDim_FixRelation::PrsDim_FixRelation(const TopoDS_Shape& aShape,
93 const Handle(Geom_Plane)& aPlane,
94 const TopoDS_Wire& aWire,
95 const gp_Pnt& aPosition,
96 const Standard_Real anArrowSize)
97 : PrsDim_Relation(),
98 myWire(aWire)
99 {
100 myFShape = aShape;
101 myPlane = aPlane;
102 myPosition = aPosition;
103 SetArrowSize( anArrowSize );
104 myAutomaticPosition = Standard_False;
105 }
106
107
108 //=======================================================================
109 //function : Constructor
110 //purpose : edge (line or circle) Fix Relation
111 //=======================================================================
112
PrsDim_FixRelation(const TopoDS_Shape & aShape,const Handle (Geom_Plane)& aPlane)113 PrsDim_FixRelation::PrsDim_FixRelation (const TopoDS_Shape& aShape,
114 const Handle(Geom_Plane)& aPlane)
115 {
116 myFShape = aShape;
117 myPlane = aPlane;
118 myAutomaticPosition = Standard_True;
119 myArrowSize = 5.;
120 }
121
122 //=======================================================================
123 //function : Constructor
124 //purpose : edge (line or circle) Fix Relation
125 //=======================================================================
126
PrsDim_FixRelation(const TopoDS_Shape & aShape,const Handle (Geom_Plane)& aPlane,const gp_Pnt & aPosition,const Standard_Real anArrowSize)127 PrsDim_FixRelation::PrsDim_FixRelation(
128 const TopoDS_Shape& aShape,
129 const Handle(Geom_Plane)& aPlane,
130 const gp_Pnt& aPosition,
131 const Standard_Real anArrowSize)
132 {
133 myFShape = aShape;
134 myPlane = aPlane;
135 myPosition = aPosition;
136 SetArrowSize( anArrowSize );
137 myAutomaticPosition = Standard_False;
138 }
139
140 //=======================================================================
141 //function : Compute
142 //purpose :
143 //=======================================================================
Compute(const Handle (PrsMgr_PresentationManager)&,const Handle (Prs3d_Presentation)& aPresentation,const Standard_Integer)144 void PrsDim_FixRelation::Compute (const Handle(PrsMgr_PresentationManager)& ,
145 const Handle(Prs3d_Presentation)& aPresentation,
146 const Standard_Integer )
147 {
148 // Calculate position of the symbol and
149 // point of attach of the segment on the shape
150 gp_Pnt curpos;
151 if (myFShape.ShapeType() == TopAbs_VERTEX)
152 ComputeVertex(TopoDS::Vertex(myFShape), curpos);
153 else if (myFShape.ShapeType() == TopAbs_EDGE)
154 ComputeEdge(TopoDS::Edge(myFShape), curpos);
155
156 const gp_Dir& nor = myPlane->Axis().Direction();
157
158
159 // calculate presentation
160 // definition of the symbol size
161 if( !myArrowSizeIsDefined )
162 myArrowSize = 5.;
163
164 //creation of the presentation
165 DsgPrs_FixPresentation::Add(aPresentation,
166 myDrawer,
167 myPntAttach,
168 curpos,
169 nor,
170 myArrowSize);
171 }
172
173 //=======================================================================
174 //function : ComputeSelection
175 //purpose :
176 //=======================================================================
177
ComputeSelection(const Handle (SelectMgr_Selection)& aSelection,const Standard_Integer)178 void PrsDim_FixRelation::ComputeSelection(const Handle(SelectMgr_Selection)& aSelection,
179 const Standard_Integer)
180 {
181 Handle(SelectMgr_EntityOwner) own = new SelectMgr_EntityOwner(this,7);
182
183 // creation of segment sensible for the linked segment
184 // of the shape fixed to symbol 'Fix'
185 Handle(Select3D_SensitiveSegment) seg;
186 seg = new Select3D_SensitiveSegment(own,
187 myPntAttach,
188 myPosition);
189 aSelection->Add(seg);
190
191 // Creation of the sensible zone of symbol 'Fix'
192 gp_Dir norm = myPlane->Axis().Direction();
193
194 gp_Vec dirac(myPntAttach,myPosition);
195 dirac.Normalize();
196 gp_Vec norac = dirac.Crossed(gp_Vec(norm));
197 gp_Ax1 ax(myPosition, norm);
198 norac.Rotate(ax, M_PI/8);
199
200 norac*=(myArrowSize/2);
201 gp_Pnt P1 = myPosition.Translated(norac);
202 gp_Pnt P2 = myPosition.Translated(-norac);
203 seg = new Select3D_SensitiveSegment(own,
204 P1,
205 P2);
206 aSelection->Add(seg);
207
208 norac*=0.8;
209 P1 = myPosition.Translated(norac);
210 P2 = myPosition.Translated(-norac);
211 dirac*=(myArrowSize/2);
212 gp_Pnt PF(P1.XYZ());
213 gp_Pnt PL = PF.Translated(dirac);
214 PL.Translate(norac);
215 seg = new Select3D_SensitiveSegment(own,
216 PF,
217 PL);
218 aSelection->Add(seg);
219
220
221 PF.SetXYZ(P2.XYZ());
222 PL = PF.Translated(dirac);
223 PL.Translate(norac);
224 seg = new Select3D_SensitiveSegment(own,
225 PF,
226 PL);
227 aSelection->Add(seg);
228
229 PF.SetXYZ( (P1.XYZ() + P2.XYZ()) /2 );
230 PL = PF.Translated(dirac);
231 PL.Translate(norac);
232 seg = new Select3D_SensitiveSegment(own,
233 PF,
234 PL);
235 }
236
237 //=======================================================================
238 //function : ComputeVertex
239 //purpose : computes myPntAttach and the position of the presentation
240 // when you fix a vertex
241 //=======================================================================
242
ComputeVertex(const TopoDS_Vertex &,gp_Pnt & curpos)243 void PrsDim_FixRelation::ComputeVertex(const TopoDS_Vertex& /*FixVertex*/,
244 gp_Pnt& curpos)
245 {
246 myPntAttach = BRep_Tool::Pnt(TopoDS::Vertex(myFShape));
247 curpos = myPosition;
248 if (myAutomaticPosition) {
249 gp_Pln pln(myPlane->Pln());
250 gp_Dir dir(pln.XAxis().Direction());
251 gp_Vec transvec = gp_Vec(dir)*myArrowSize;
252 curpos = myPntAttach.Translated(transvec);
253 myPosition = curpos;
254 myAutomaticPosition = Standard_True;
255 }
256 }
257
258 //=======================================================================
259 //function : ComputePosition
260 //purpose :
261 //=======================================================================
262
ComputePosition(const Handle (Geom_Curve)& curv1,const Handle (Geom_Curve)& curv2,const gp_Pnt & firstp1,const gp_Pnt & lastp1,const gp_Pnt & firstp2,const gp_Pnt & lastp2) const263 gp_Pnt PrsDim_FixRelation::ComputePosition(const Handle(Geom_Curve)& curv1,
264 const Handle(Geom_Curve)& curv2,
265 const gp_Pnt& firstp1,
266 const gp_Pnt& lastp1,
267 const gp_Pnt& firstp2,
268 const gp_Pnt& lastp2) const
269 {
270 //---------------------------------------------------------
271 // calculate the point of attach
272 //---------------------------------------------------------
273 gp_Pnt curpos;
274
275 if (curv1->IsInstance(STANDARD_TYPE(Geom_Circle)) || curv2->IsInstance(STANDARD_TYPE(Geom_Circle))) {
276 Handle(Geom_Circle) gcirc = Handle(Geom_Circle)::DownCast(curv1);
277 if (gcirc.IsNull()) gcirc = Handle(Geom_Circle)::DownCast(curv2);
278 gp_Dir dir( gcirc->Location().XYZ() + myPntAttach.XYZ() );
279 gp_Vec transvec = gp_Vec(dir)*myArrowSize;
280 curpos = myPntAttach.Translated(transvec);
281 }
282
283 else {
284 gp_Vec vec1(firstp1,lastp1);
285 gp_Vec vec2(firstp2,lastp2);
286
287 if (!vec1.IsParallel(vec2, Precision::Angular()) ) {
288 gp_Dir dir;
289 Standard_Real conf =Precision::Confusion();
290 if (lastp1.IsEqual(firstp2,conf) || firstp1.IsEqual(lastp2,conf)) dir.SetXYZ(vec1.XYZ() - vec2.XYZ());
291 else dir.SetXYZ(vec1.XYZ() + vec2.XYZ());
292 gp_Vec transvec = gp_Vec(dir)*myArrowSize;
293 curpos = myPntAttach.Translated(transvec);
294 }
295 else {
296 gp_Vec crossvec = vec1.Crossed(vec2);
297 vec1.Cross(crossvec);
298 gp_Dir dir(vec1);
299 curpos = myPntAttach.Translated(gp_Vec(dir)*myArrowSize);
300 }
301 }
302
303 return curpos;
304 }
305
306 //=======================================================================
307 //function : ComputePosition
308 //purpose : Computes the position of the "fix dimension" when the
309 // fixed object is a vertex which is set at the intersection
310 // of two curves.
311 // The "dimension" is in the "middle" of the two edges.
312 //=======================================================================
313
ComputePosition(const Handle (Geom_Curve)& curv,const gp_Pnt & firstp,const gp_Pnt & lastp) const314 gp_Pnt PrsDim_FixRelation::ComputePosition(const Handle(Geom_Curve)& curv,
315 const gp_Pnt& firstp,
316 const gp_Pnt& lastp) const
317 {
318 //---------------------------------------------------------
319 // calculate the point of attach
320 //---------------------------------------------------------
321 gp_Pnt curpos;
322
323 if (curv->IsKind(STANDARD_TYPE(Geom_Circle))) {
324
325 Handle(Geom_Circle) gcirc = Handle(Geom_Circle)::DownCast(curv);
326 gp_Dir dir( gcirc->Location().XYZ() + myPntAttach.XYZ() );
327 gp_Vec transvec = gp_Vec(dir)*myArrowSize;
328 curpos = myPntAttach.Translated(transvec);
329
330 } //if (curv->IsKind(STANDARD_TYPE(Geom_Circle))
331
332 else {
333 // gp_Pln pln(Component()->WorkingPlane()->Plane()->GetValue()->Pln());
334 gp_Pln pln(myPlane->Pln());
335 gp_Dir NormPln = pln.Axis().Direction();
336 gp_Vec vec(firstp,lastp);
337 vec.Cross( gp_Vec(NormPln));
338 vec.Normalize();
339 gp_Vec transvec = vec*myArrowSize;
340 curpos = myPntAttach.Translated(transvec);
341 gp_Ax1 RotAx( myPntAttach, NormPln);
342 curpos.Rotate(RotAx, M_PI/10);
343 }
344
345 return curpos;
346 }
347
348 //=======================================================================
349 //function : ComputeEdge
350 //purpose : computes myPntAttach and the position of the presentation
351 // when you fix an edge
352 //=======================================================================
353
ComputeEdge(const TopoDS_Edge & FixEdge,gp_Pnt & curpos)354 void PrsDim_FixRelation::ComputeEdge(const TopoDS_Edge& FixEdge, gp_Pnt& curpos)
355 {
356 Handle(Geom_Curve) curEdge;
357 gp_Pnt ptbeg,ptend;
358 if (!PrsDim::ComputeGeometry(FixEdge,curEdge,ptbeg,ptend)) return;
359
360 //---------------------------------------------------------
361 // calcul du point de positionnement du symbole 'fix'
362 //---------------------------------------------------------
363 //--> In case of a straight line
364 if (curEdge->IsKind(STANDARD_TYPE(Geom_Line))){
365 gp_Lin glin = Handle(Geom_Line)::DownCast(curEdge)->Lin();
366 Standard_Real pfirst(ElCLib::Parameter(glin,ptbeg));
367 Standard_Real plast(ElCLib::Parameter(glin,ptend));
368 ComputeLinePosition(glin, curpos, pfirst, plast);
369 }
370
371 //--> In case of a circle
372 else if (curEdge->IsKind(STANDARD_TYPE(Geom_Circle))) {
373 gp_Circ gcirc = Handle(Geom_Circle)::DownCast(curEdge)->Circ();
374 Standard_Real pfirst, plast;
375 BRepAdaptor_Curve cu(FixEdge);
376 pfirst = cu.FirstParameter();
377 plast = cu.LastParameter();
378 ComputeCirclePosition(gcirc, curpos, pfirst, plast);
379 }
380
381 else
382 return;
383
384 }
385
386 //=======================================================================
387 //function : ComputeLinePosition
388 //purpose : compute the values of myPntAttach and the position <pos> of
389 // the symbol when the fixed edge has a geometric support equal
390 // to a line.
391 //=======================================================================
392
ComputeLinePosition(const gp_Lin & glin,gp_Pnt & pos,Standard_Real & pfirst,Standard_Real & plast)393 void PrsDim_FixRelation::ComputeLinePosition(const gp_Lin& glin,
394 gp_Pnt& pos,
395 Standard_Real& pfirst,
396 Standard_Real& plast)
397 {
398 if (myAutomaticPosition) {
399 // point of attach is chosen as middle of the segment
400 myPntAttach = ElCLib::Value((pfirst+ plast)/2, glin);
401
402 gp_Dir norm = myPlane ->Axis().Direction();
403
404 norm.Cross(glin.Position().Direction());
405 pos = myPntAttach.Translated(gp_Vec(norm)*myArrowSize);
406 myAutomaticPosition = Standard_True;
407 } // if (myAutomaticPosition)
408
409 else {
410 pos = myPosition;
411 Standard_Real linparam = ElCLib::Parameter(glin, pos);
412
413 // case if the projection of position is located between 2 vertices
414 // de l'edge
415 if ( (linparam >= pfirst) && (linparam <= plast) )
416 myPntAttach = ElCLib::Value(linparam,glin);
417
418 // case if the projection of Position is outside of the limits
419 // of the edge : the point closest to the projection is chosen
420 // as the attach point
421 else {
422 Standard_Real pOnLin;
423 if (linparam > plast)
424 pOnLin = plast;
425 else
426 pOnLin = pfirst;
427 myPntAttach = ElCLib::Value(pOnLin,glin);
428 gp_Dir norm = myPlane->Axis().Direction();
429
430 norm.Cross(glin.Position().Direction());
431 gp_Lin lsup(myPntAttach, norm);
432 Standard_Real parpos = ElCLib::Parameter(lsup,myPosition);
433 pos = ElCLib::Value(parpos,lsup);
434 }
435
436 }
437 myPosition = pos;
438 }
439
440 //=======================================================================
441 //function : ComputeCirclePosition
442 //purpose : compute the values of myPntAttach and the position <pos> of
443 // the symbol when the fixed edge has a geometric support equal
444 // to a circle.
445 //=======================================================================
446
ComputeCirclePosition(const gp_Circ & gcirc,gp_Pnt & pos,Standard_Real & pfirst,Standard_Real & plast)447 void PrsDim_FixRelation::ComputeCirclePosition(
448 const gp_Circ& gcirc,
449 gp_Pnt& pos,
450 Standard_Real& pfirst,
451 Standard_Real& plast)
452 {
453 // readjust parametres on the circle
454 if (plast > 2*M_PI ) {
455 Standard_Real nbtours = Floor(plast / (2*M_PI));
456 plast -= nbtours*2*M_PI;
457 pfirst -= nbtours*2*M_PI;
458 }
459
460 if (myAutomaticPosition) {
461 // the point attach is the "middle" of the segment (relatively
462 // to the parametres of start and end vertices of the edge
463
464 Standard_Real circparam = (pfirst + plast)/2.;
465
466 if ( !InDomain(pfirst,plast,circparam)) {
467 Standard_Real otherpar = circparam + M_PI;
468 if (otherpar > 2*M_PI) otherpar -= 2*M_PI;
469 circparam = otherpar;
470 }
471
472 myPntAttach = ElCLib::Value(circparam, gcirc );
473
474 gp_Vec dir( gcirc.Location().XYZ(), myPntAttach.XYZ() );
475 dir.Normalize();
476 gp_Vec transvec = dir*myArrowSize;
477 pos = myPntAttach.Translated(transvec);
478 myPosition = pos;
479 myAutomaticPosition = Standard_True;
480 } // if (myAutomaticPosition)
481
482 else {
483 // case if the projection of myPosition is outside of 2
484 // vertices of the edge. In this case the parameter is readjusted
485 // in the valid part of the circle
486 pos = myPosition;
487
488 Standard_Real circparam = ElCLib::Parameter(gcirc, pos);
489
490 if ( !InDomain(pfirst,plast,circparam)) {
491 Standard_Real otherpar = circparam + M_PI;
492 if (otherpar > 2*M_PI) otherpar -= 2*M_PI;
493 circparam = otherpar;
494 }
495
496 myPntAttach = ElCLib::Value(circparam,gcirc);
497 }
498 }
499
500 //=======================================================================
501 //function : ConnectedEdges
502 //purpose :
503 //=======================================================================
ConnectedEdges(const TopoDS_Wire & WIRE,const TopoDS_Vertex & V,TopoDS_Edge & E1,TopoDS_Edge & E2)504 Standard_Boolean PrsDim_FixRelation::ConnectedEdges(const TopoDS_Wire& WIRE,
505 const TopoDS_Vertex& V,
506 TopoDS_Edge& E1,
507 TopoDS_Edge& E2)
508 {
509 TopTools_IndexedDataMapOfShapeListOfShape vertexMap;
510 TopExp::MapShapesAndAncestors (WIRE,TopAbs_VERTEX,TopAbs_EDGE,vertexMap);
511
512 Standard_Boolean found(Standard_False);
513 TopoDS_Vertex theVertex;
514 for (Standard_Integer i=1; i<=vertexMap.Extent() && !found; i++) {
515 if (vertexMap.FindKey(i).IsSame(V)) {
516 theVertex = TopoDS::Vertex(vertexMap.FindKey(i));
517 found = Standard_True;
518 }
519 }
520 if (!found) {
521 E1.Nullify();
522 E2.Nullify();
523 return Standard_False;
524 }
525
526 TopTools_ListIteratorOfListOfShape iterator(vertexMap.FindFromKey(theVertex));
527 if (iterator.More()) {
528 E1 = TopoDS::Edge(iterator.Value());
529 BRepAdaptor_Curve curv(E1);
530 iterator.Next();
531 }
532 else {
533 E1.Nullify();
534 return Standard_False;
535 }
536
537 if (iterator.More()) {
538 E2 = TopoDS::Edge(iterator.Value());
539 BRepAdaptor_Curve curv(E2);
540 iterator.Next();
541 }
542 else {
543 E2.Nullify();
544 return Standard_False;
545 }
546
547 if (iterator.More()) {
548 E1.Nullify();
549 E2.Nullify();
550 return Standard_False;
551 }
552 return Standard_True;
553 }
554