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