1 // Created on: 1998-11-12
2 // Created by: Robert COUBLANC
3 // Copyright (c) 1998-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 #include <ViewerTest.hxx>
19 #include <AIS_Circle.hxx>
20 #include <AIS_DisplayMode.hxx>
21 #include <AIS_InteractiveContext.hxx>
22 #include <AIS_ListIteratorOfListOfInteractive.hxx>
23 #include <AIS_ListOfInteractive.hxx>
24 #include <AIS_MapOfInteractive.hxx>
25 #include <AIS_Point.hxx>
26 #include <AIS_Shape.hxx>
27 #include <PrsDim_AngleDimension.hxx>
28 #include <PrsDim_ConcentricRelation.hxx>
29 #include <PrsDim_DiameterDimension.hxx>
30 #include <PrsDim_EqualDistanceRelation.hxx>
31 #include <PrsDim_EqualRadiusRelation.hxx>
32 #include <PrsDim_FixRelation.hxx>
33 #include <PrsDim_IdenticRelation.hxx>
34 #include <PrsDim_KindOfRelation.hxx>
35 #include <PrsDim_LengthDimension.hxx>
36 #include <PrsDim_OffsetDimension.hxx>
37 #include <PrsDim_ParallelRelation.hxx>
38 #include <PrsDim_PerpendicularRelation.hxx>
39 #include <PrsDim_RadiusDimension.hxx>
40 #include <PrsDim_Relation.hxx>
41 #include <PrsDim_SymmetricRelation.hxx>
42 #include <PrsDim_TangentRelation.hxx>
43 #include <BRep_Builder.hxx>
44 #include <BRep_Tool.hxx>
45 #include <BRepAdaptor_Curve.hxx>
46 #include <BRepBuilderAPI_MakeVertex.hxx>
47 #include <BRepExtrema_ExtCC.hxx>
48 #include <BRepExtrema_ExtPC.hxx>
49 #include <BRepExtrema_ExtCF.hxx>
50 #include <BRepExtrema_ExtPF.hxx>
51 #include <BRepExtrema_ExtFF.hxx>
52 #include <BRepTools.hxx>
53 #include <Draw_Interpretor.hxx>
55 #include <Draw_Appli.hxx>
56 #include <Draw_Window.hxx>
59 #include <Font_FontMgr.hxx>
60 #include <GC_MakePlane.hxx>
61 #include <Geom_CartesianPoint.hxx>
62 #include <Geom_Circle.hxx>
63 #include <Geom_Line.hxx>
64 #include <Geom_Plane.hxx>
65 #include <GeomAPI_IntCS.hxx>
66 #include <gce_MakeLin.hxx>
67 #include <gce_MakePln.hxx>
68 #include <gp_Circ.hxx>
70 #include <IntAna_IntConicQuad.hxx>
71 #include <IntAna_Quadric.hxx>
72 #include <Message.hxx>
73 #include <Precision.hxx>
74 #include <StdSelect.hxx>
75 #include <TCollection_AsciiString.hxx>
76 #include <TCollection_ExtendedString.hxx>
77 #include <TColStd_MapOfInteger.hxx>
78 #include <TColStd_SequenceOfReal.hxx>
80 #include <TopAbs_ShapeEnum.hxx>
82 #include <TopExp_Explorer.hxx>
84 #include <TopoDS_Face.hxx>
85 #include <TopoDS_Solid.hxx>
86 #include <TopoDS_Vertex.hxx>
87 #include <V3d_Viewer.hxx>
88 #include <V3d_View.hxx>
90 #include <ViewerTest_DoubleMapOfInteractiveAndName.hxx>
91 #include <ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName.hxx>
92 #include <ViewerTest_EventManager.hxx>
94 extern Standard_Boolean VDisplayAISObject (const TCollection_AsciiString& theName,
95 const Handle(AIS_InteractiveObject)& theAISObj,
96 Standard_Boolean theReplaceIfExists = Standard_True);
97 extern ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS();
98 extern int ViewerMainLoop(Standard_Integer argc, const char** argv);
99 extern Handle(AIS_InteractiveContext)& TheAISContext ();
101 #define VertexMask 0x01
102 #define EdgeMask 0x02
103 #define FaceMask 0x04
105 //=======================================================================
106 //function : Get3DPointAtMousePosition
107 //purpose : Calculates the 3D points corresponding to the mouse position
108 // in the plane of the view
109 //=======================================================================
110 static gp_Pnt Get3DPointAtMousePosition()
112 Handle(V3d_View) aView = ViewerTest::CurrentView();
114 Standard_Real xv,yv,zv;
115 aView->Proj (xv,yv,zv);
116 Standard_Real xat,yat,zat;
117 aView->At(xat,yat,zat);
118 gp_Pln aPlane (gp_Pnt(xat,yat,zat), gp_Dir(xv,yv,zv));
120 Standard_Integer aPixX, aPixY;
121 Standard_Real aX, aY, aZ, aDX, aDY, aDZ;
123 ViewerTest::GetMousePosition (aPixX, aPixY);
124 aView->ConvertWithProj (aPixX, aPixY, aX, aY, aZ, aDX, aDY, aDZ);
125 gp_Lin aLine( gp_Pnt(aX, aY, aZ), gp_Dir(aDX, aDY, aDZ) );
127 // Compute intersection
128 Handle(Geom_Line) aGeomLine = new Geom_Line (aLine);
129 Handle(Geom_Plane) aGeomPlane = new Geom_Plane (aPlane);
130 GeomAPI_IntCS anIntersector (aGeomLine, aGeomPlane);
131 if (!anIntersector.IsDone() || anIntersector.NbPoints() == 0)
135 return anIntersector.Point (1);
138 //=======================================================================
139 //function : Get3DPointAtMousePosition
140 //purpose : Calculates the 3D points corresponding to the mouse position
141 // in the plane of the view
142 //=======================================================================
143 static Standard_Boolean Get3DPointAtMousePosition (const gp_Pnt& theFirstPoint,
144 const gp_Pnt& theSecondPoint,
145 gp_Pnt& theOutputPoint)
147 theOutputPoint = gp::Origin();
149 Handle(V3d_View) aView = ViewerTest::CurrentView();
151 Standard_Integer aPixX, aPixY;
152 Standard_Real aX, aY, aZ, aDx, aDy, aDz, aUx, aUy, aUz;
154 // Get 3D point in view coordinates and projection vector from the pixel point.
155 ViewerTest::GetMousePosition (aPixX, aPixY);
156 aView->ConvertWithProj (aPixX, aPixY, aX, aY, aZ, aDx, aDy, aDz);
157 gp_Lin aProjLin (gp_Pnt(aX, aY, aZ), gp_Dir(aDx, aDy, aDz));
160 gp_Vec aDimVec (theFirstPoint, theSecondPoint);
161 aView->Up (aUx, aUy, aUz);
162 gp_Vec aViewUp (aUx, aUy, aUz);
164 if (aDimVec.IsParallel (aViewUp, Precision::Angular()))
166 theOutputPoint = Get3DPointAtMousePosition();
167 return Standard_True;
170 gp_Vec aDimNormal = aDimVec ^ aViewUp;
171 gp_Pln aViewPlane= gce_MakePln (theFirstPoint, aDimNormal);
173 // Get intersection of view plane and projection line
174 Handle(Geom_Plane) aPlane = new Geom_Plane (aViewPlane);
175 Handle(Geom_Line) aProjLine = new Geom_Line (aProjLin);
176 GeomAPI_IntCS anIntersector (aProjLine, aPlane);
177 if (!anIntersector.IsDone() || anIntersector.NbPoints() == 0)
179 return Standard_False;
182 theOutputPoint = anIntersector.Point (1);
183 return Standard_True;
186 //=======================================================================
187 //function : ParseDimensionParams
188 //purpose : Auxilliary function: sets aspect parameters for
189 // length, angle, radius and diameter dimension.
191 //draw args: -text [3d|2d] [wf|sh|wireframe|shading] [Size]
192 // -label [left|right|hcenter|hfit] [top|bottom|vcenter|vfit]
193 // -arrow [external|internal|fit] [Length(int)]
194 // -arrowangle ArrowAngle(degrees)
195 // -plane xoy|yoz|zox
196 // -flyout FloatValue -extension FloatValue
198 // -value CustomRealValue
199 // -textvalue CustomTextValue
200 // -dispunits DisplayUnitsString
201 // -modelunits ModelUnitsString
205 // Warning! flyout is not an aspect value, it is for dimension parameter
206 // likewise text position, but text position override other parameters.
207 // For text position changing use 'vmovedim'.
208 //=======================================================================
209 static int ParseDimensionParams (Standard_Integer theArgNum,
210 const char** theArgVec,
211 Standard_Integer theStartIndex,
212 const Handle(Prs3d_DimensionAspect)& theAspect,
213 Standard_Boolean& theIsCustomPlane, gp_Pln& thePlane,
214 NCollection_DataMap<TCollection_AsciiString, Standard_Real>& theRealParams,
215 NCollection_DataMap<TCollection_AsciiString, TCollection_AsciiString>& theStringParams,
216 NCollection_List<Handle(AIS_InteractiveObject)>* theShapeList = NULL)
218 theRealParams.Clear();
219 theStringParams.Clear();
221 theIsCustomPlane = Standard_False;
223 // Begin from the second parameter: the first one is dimension name
224 for (Standard_Integer anIt = theStartIndex; anIt < theArgNum; ++anIt)
226 TCollection_AsciiString aParam (theArgVec[anIt]);
229 if (aParam.Search ("-") == -1)
235 if (aParam.IsEqual ("-autovalue"))
237 theRealParams.Bind ("autovalue", 1);
241 if (aParam.IsEqual ("-showunits"))
243 theAspect->MakeUnitsDisplayed (Standard_True);
246 else if (aParam.IsEqual ("-hideunits"))
248 theAspect->MakeUnitsDisplayed (Standard_False);
251 else if (aParam.IsEqual ("-selected"))
255 Message::SendFail() << "Error: unknown parameter '" << aParam << "'";
259 for (TheAISContext()->InitSelected(); TheAISContext()->MoreSelected(); TheAISContext()->NextSelected())
261 TopoDS_Shape aShape = TheAISContext()->SelectedShape();
262 if (!aShape.IsNull())
264 theShapeList->Append (new AIS_Shape (aShape));
270 // Before all non-boolean flags parsing check if a flag have at least one value.
271 if (anIt + 1 >= theArgNum)
273 Message::SendFail() << "Error: "<< aParam <<" flag should have value.";
278 if (aParam.IsEqual ("-shape")
279 || aParam.IsEqual ("-shapes"))
283 Message::SendFail() << "Error: unknown parameter '" << aParam << "'";
290 TCollection_AsciiString anArgString = theArgVec[anIt];
291 Handle(AIS_InteractiveObject) anAISObject;
292 Standard_CString aStr = anArgString.ToCString();
293 TopoDS_Shape aShape = DBRep::Get (aStr);
294 if (!aShape.IsNull())
296 anAISObject = new AIS_Shape (aShape);
298 else if (!GetMapOfAIS().Find2 (anArgString, anAISObject)
299 || anAISObject.IsNull())
301 Message::SendFail() << "Error: shape with name '" << aStr << "' is not found.";
304 theShapeList->Append (anAISObject);
306 while (anIt + 1 < theArgNum && theArgVec[anIt + 1][0] != '-');
308 else if (aParam.IsEqual ("-text"))
313 TCollection_AsciiString aValue (theArgVec[anIt]);
315 if (aValue.IsEqual ("3d"))
317 theAspect->MakeText3d (Standard_True);
319 else if (aValue.IsEqual ("2d"))
321 theAspect->MakeText3d (Standard_False);
323 else if (aValue.IsEqual ("wf") || aValue.IsEqual ("wireframe"))
325 theAspect->MakeTextShaded (Standard_False);
327 else if ( aValue.IsEqual ("sh") || aValue.IsEqual ("shading"))
329 theAspect->MakeTextShaded (Standard_True);
331 else if (aValue.IsIntegerValue()) // text size
333 theAspect->TextAspect()->SetHeight (Draw::Atoi (aValue.ToCString()));
336 while (anIt + 1 < theArgNum && theArgVec[anIt + 1][0] != '-');
338 else if (aParam.IsEqual ("-font"))
340 if (anIt + 1 >= theArgNum)
342 Message::SendFail() << "Error: wrong number of values for parameter '" << aParam << "'";
346 theAspect->TextAspect()->SetFont (theArgVec[++anIt]);
348 else if (aParam.IsEqual ("-label"))
353 TCollection_AsciiString aParamValue (theArgVec[anIt]);
354 aParamValue.LowerCase();
356 if (aParamValue == "left") { theAspect->SetTextHorizontalPosition (Prs3d_DTHP_Left); }
357 else if (aParamValue == "right") { theAspect->SetTextHorizontalPosition (Prs3d_DTHP_Right); }
358 else if (aParamValue == "hcenter") { theAspect->SetTextHorizontalPosition (Prs3d_DTHP_Center);}
359 else if (aParamValue == "hfit") { theAspect->SetTextHorizontalPosition (Prs3d_DTHP_Fit); }
360 else if (aParamValue == "above") { theAspect->SetTextVerticalPosition (Prs3d_DTVP_Above); }
361 else if (aParamValue == "below") { theAspect->SetTextVerticalPosition (Prs3d_DTVP_Below); }
362 else if (aParamValue == "vcenter") { theAspect->SetTextVerticalPosition (Prs3d_DTVP_Center);}
365 Message::SendFail() << "Error: invalid label position: '" << aParamValue << "'.";
369 while (anIt + 1 < theArgNum && theArgVec[anIt+1][0] != '-');
371 else if (aParam.IsEqual ("-arrow"))
373 TCollection_AsciiString aLocalParam(theArgVec[++anIt]);
374 aLocalParam.LowerCase();
376 if (aLocalParam == "external") { theAspect->SetArrowOrientation (Prs3d_DAO_External); }
377 if (aLocalParam == "internal") { theAspect->SetArrowOrientation (Prs3d_DAO_Internal); }
378 if (aLocalParam == "fit") { theAspect->SetArrowOrientation (Prs3d_DAO_Fit); }
380 else if (aParam.IsEqual ("-arrowlength") || aParam.IsEqual ("-arlen"))
382 TCollection_AsciiString aValue (theArgVec[++anIt]);
383 if (!aValue.IsRealValue (Standard_True))
385 Message::SendFail() << "Error: arrow length should be float degree value.";
388 theAspect->ArrowAspect()->SetLength (Draw::Atof (aValue.ToCString()));
390 else if (aParam.IsEqual ("-arrowangle") || aParam.IsEqual ("-arangle"))
392 TCollection_AsciiString aValue (theArgVec[++anIt]);
393 if (!aValue.IsRealValue (Standard_True))
395 Message::SendFail ("Error: arrow angle should be float degree value.");
398 theAspect->ArrowAspect()->SetAngle (Draw::Atof (aValue.ToCString()));
400 else if (aParam.IsEqual ("-color"))
402 Quantity_Color aColor;
403 Standard_Integer aNbParsed = Draw::ParseColor (theArgNum - anIt - 1,
404 theArgVec + anIt + 1,
409 Message::SendFail() << "Error: wrong syntax at '" << aParam << "'";
412 theAspect->SetCommonColor (aColor);
414 else if (aParam.IsEqual ("-extension"))
416 TCollection_AsciiString aLocalParam(theArgVec[++anIt]);
417 if (!aLocalParam.IsRealValue (Standard_True))
419 Message::SendFail ("Error: extension size for dimension should be real value.");
422 theAspect->SetExtensionSize (Draw::Atof (aLocalParam.ToCString()));
424 else if (aParam.IsEqual ("-plane"))
426 TCollection_AsciiString aValue (theArgVec[++anIt]);
430 theIsCustomPlane = Standard_True;
431 thePlane = gp_Pln (gp_Ax3 (gp::XOY()));
433 else if (aValue == "zox")
435 theIsCustomPlane = Standard_True;
436 thePlane = gp_Pln (gp_Ax3 (gp::ZOX()));
438 else if (aValue == "yoz")
440 theIsCustomPlane = Standard_True;
441 thePlane = gp_Pln (gp_Ax3 (gp::YOZ()));
445 Message::SendFail() << "Error: wrong plane '" << aValue << "'";
449 else if (aParam.IsEqual ("-flyout"))
451 TCollection_AsciiString aLocalParam(theArgVec[++anIt]);
452 if (!aLocalParam.IsRealValue (Standard_True))
454 Message::SendFail ("Error: flyout for dimension should be real value.");
458 theRealParams.Bind ("flyout", Draw::Atof (aLocalParam.ToCString()));
460 else if (aParam.IsEqual ("-value"))
462 TCollection_AsciiString aLocalParam(theArgVec[++anIt]);
463 if (!aLocalParam.IsRealValue (Standard_True))
465 Message::SendFail ("Error: dimension value for dimension should be real value");
469 theRealParams.Bind ("value", Draw::Atof (aLocalParam.ToCString()));
471 else if (aParam.IsEqual ("-textvalue"))
473 TCollection_AsciiString aLocalParam(theArgVec[++anIt]);
475 theStringParams.Bind ("textvalue", aLocalParam);
477 else if (aParam.IsEqual ("-modelunits"))
479 TCollection_AsciiString aLocalParam(theArgVec[++anIt]);
481 theStringParams.Bind ("modelunits", aLocalParam);
483 else if (aParam.IsEqual ("-dispunits"))
485 TCollection_AsciiString aLocalParam(theArgVec[++anIt]);
487 theStringParams.Bind ("dispunits", aLocalParam);
491 Message::SendFail() << "Error: unknown parameter '" << aParam << "'";
499 //=======================================================================
500 //function : SetDimensionParams
501 //purpose : Sets parameters for dimension
502 //=======================================================================
503 static void SetDimensionParams (const Handle(PrsDim_Dimension)& theDim,
504 const NCollection_DataMap<TCollection_AsciiString, Standard_Real>& theRealParams,
505 const NCollection_DataMap<TCollection_AsciiString, TCollection_AsciiString>& theStringParams)
507 if (theRealParams.IsBound ("flyout"))
509 theDim->SetFlyout (theRealParams.Find ("flyout"));
512 if (theRealParams.IsBound ("autovalue"))
514 theDim->SetComputedValue();
517 if (theRealParams.IsBound ("value"))
519 theDim->SetCustomValue (theRealParams.Find ("value"));
522 if (theStringParams.IsBound ("textvalue"))
524 theDim->SetCustomValue (theStringParams.Find ("textvalue"));
527 if (theStringParams.IsBound ("modelunits"))
529 theDim->SetModelUnits (theStringParams.Find ("modelunits"));
532 if (theStringParams.IsBound ("dispunits"))
534 theDim->SetDisplayUnits (theStringParams.Find ("dispunits"));
538 //=======================================================================
539 //function : ParseAngleDimensionParams
540 //purpose : Auxilliary function: sets custom parameters for angle dimension.
542 //draw args: -type [interior|exterior]
543 // -showarrow [first|second|both|none]
544 //=======================================================================
545 static int ParseAngleDimensionParams (Standard_Integer theArgNum,
546 const char** theArgVec,
547 Standard_Integer theStartIndex,
548 NCollection_DataMap<TCollection_AsciiString, TCollection_AsciiString>& theStringParams)
550 theStringParams.Clear();
552 // Begin from the second parameter: the first one is dimension name
553 for (Standard_Integer anIt = theStartIndex; anIt < theArgNum; ++anIt)
555 TCollection_AsciiString aParam (theArgVec[anIt]);
558 if (aParam.Search ("-") == -1)
560 Message::SendFail() << "Error: wrong parameter '" << aParam << "'.";
564 // Before all non-boolean flags parsing check if a flag have at least one value.
565 if (anIt + 1 >= theArgNum)
567 Message::SendFail() << "Error: "<< aParam <<" flag should have value.";
571 if (aParam.IsEqual ("-type"))
573 TCollection_AsciiString aLocalParam(theArgVec[++anIt]);
575 theStringParams.Bind ("type", aLocalParam);
577 else if (aParam.IsEqual ("-showarrow"))
579 TCollection_AsciiString aLocalParam(theArgVec[++anIt]);
581 theStringParams.Bind ("showarrow", aLocalParam);
585 Message::SendFail() << "Error: unknown parameter '" << aParam << "'.";
593 //=======================================================================
594 //function : SetAngleDimensionParams
595 //purpose : Sets parameters for angle dimension
596 //=======================================================================
597 static void SetAngleDimensionParams (const Handle(PrsDim_Dimension)& theDim,
598 const NCollection_DataMap<TCollection_AsciiString,
599 TCollection_AsciiString>& theStringParams)
601 Handle(PrsDim_AngleDimension) anAngleDim = Handle(PrsDim_AngleDimension)::DownCast (theDim);
602 if (anAngleDim.IsNull())
607 if (theStringParams.IsBound ("type"))
609 PrsDim_TypeOfAngle anAngleType = PrsDim_TypeOfAngle_Interior;
610 TCollection_AsciiString anAngleTypeStr = theStringParams.Find ("type");
611 if (anAngleTypeStr.IsEqual("interior"))
613 anAngleType = PrsDim_TypeOfAngle_Interior;
615 else if (anAngleTypeStr.IsEqual("exterior"))
617 anAngleType = PrsDim_TypeOfAngle_Exterior;
621 Message::SendFail() << "Error: wrong angle type.";
623 anAngleDim->SetType(anAngleType);
626 if (theStringParams.IsBound ("showarrow"))
628 PrsDim_TypeOfAngleArrowVisibility anArrowType = PrsDim_TypeOfAngleArrowVisibility_Both;
629 TCollection_AsciiString anArrowTypeStr = theStringParams.Find ("showarrow");
630 if (anArrowTypeStr.IsEqual("both"))
632 anArrowType = PrsDim_TypeOfAngleArrowVisibility_Both;
634 else if (anArrowTypeStr.IsEqual("first"))
636 anArrowType = PrsDim_TypeOfAngleArrowVisibility_First;
638 else if (anArrowTypeStr.IsEqual("second"))
640 anArrowType = PrsDim_TypeOfAngleArrowVisibility_Second;
642 else if (anArrowTypeStr.IsEqual("none"))
644 anArrowType = PrsDim_TypeOfAngleArrowVisibility_None;
648 Message::SendFail() << "Error: wrong showarrow type.";
650 anAngleDim->SetArrowsVisibility(anArrowType);
654 //=======================================================================
655 //function : VDimBuilder
656 //purpose : Command for building dimension presentations: angle,
657 // length, radius, diameter
658 //=======================================================================
659 static int VDimBuilder (Draw_Interpretor& /*theDi*/,
660 Standard_Integer theArgsNb,
661 const char** theArgs)
665 Message::SendFail ("Syntax error: wrong number of arguments");
670 TCollection_AsciiString aName (theArgs[1]);
672 NCollection_List<Handle(AIS_InteractiveObject)> aShapes;
673 Handle(Prs3d_DimensionAspect) anAspect = new Prs3d_DimensionAspect();
674 Standard_Boolean isPlaneCustom = Standard_False;
675 gp_Pln aWorkingPlane;
677 NCollection_DataMap<TCollection_AsciiString, Standard_Real> aRealParams;
678 NCollection_DataMap<TCollection_AsciiString, TCollection_AsciiString> aStringParams;
680 TCollection_AsciiString aDimType(theArgs[2]);
681 aDimType.LowerCase();
682 PrsDim_KindOfDimension aKindOfDimension;
683 if (aDimType == "-length")
685 aKindOfDimension = PrsDim_KOD_LENGTH;
687 else if (aDimType == "-angle")
689 aKindOfDimension = PrsDim_KOD_PLANEANGLE;
691 else if (aDimType == "-radius")
693 aKindOfDimension = PrsDim_KOD_RADIUS;
695 else if (aDimType == "-diameter" || aDimType == "-diam")
697 aKindOfDimension = PrsDim_KOD_DIAMETER;
701 Message::SendFail ("Error: wrong type of dimension");
706 if (ParseDimensionParams (theArgsNb, theArgs, 3,
707 anAspect,isPlaneCustom,aWorkingPlane,
708 aRealParams, aStringParams, &aShapes))
714 Handle(PrsDim_Dimension) aDim;
715 switch (aKindOfDimension)
717 case PrsDim_KOD_LENGTH:
719 if (aShapes.Extent() == 1)
721 Handle(AIS_Shape) aFirstShapePrs = Handle(AIS_Shape)::DownCast(aShapes.First());
722 if (aFirstShapePrs.IsNull()
723 || aFirstShapePrs->Shape().ShapeType() != TopAbs_EDGE)
725 Message::SendFail ("Error: wrong shape type");
730 Message::SendFail ("Error: can not build dimension without working plane");
734 // Adjust working plane
735 TopoDS_Edge anEdge = TopoDS::Edge (aFirstShapePrs->Shape());
736 TopoDS_Vertex aFirst, aSecond;
737 TopExp::Vertices (anEdge, aFirst, aSecond);
738 aDim = new PrsDim_LengthDimension (anEdge, aWorkingPlane);
740 // Move standard plane (XOY, YOZ or ZOX) to the first point to make it working for dimension
741 aWorkingPlane.SetLocation (Handle(PrsDim_LengthDimension)::DownCast (aDim)->FirstPoint());
743 else if (aShapes.Extent() == 2)
745 TopoDS_Shape aShape1, aShape2;
748 if (Handle(AIS_Point) aPntPrs = Handle(AIS_Point)::DownCast (aShapes.First()))
750 aShape1 = aPntPrs->Vertex();
752 else if (Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast (aShapes.First()))
754 aShape1 = aShapePrs->Shape();
757 if (Handle(AIS_Point) aPntPrs = Handle(AIS_Point)::DownCast (aShapes.Last ()))
759 aShape2 = aPntPrs->Vertex();
761 else if (Handle(AIS_Shape) aShapePrs = Handle(AIS_Shape)::DownCast (aShapes.Last()))
763 aShape2 = aShapePrs->Shape();
766 if (aShape1.IsNull() || aShape2.IsNull())
768 Message::SendFail ("Error: wrong shape type.");
773 Handle(PrsDim_LengthDimension) aLenDim = new PrsDim_LengthDimension();
776 if (aShape1.ShapeType() == TopAbs_VERTEX)
778 aWorkingPlane.SetLocation (BRep_Tool::Pnt (TopoDS::Vertex (aShape1)));
780 else if (aShape2.ShapeType() == TopAbs_VERTEX)
782 aWorkingPlane.SetLocation (BRep_Tool::Pnt (TopoDS::Vertex (aShape2)));
784 aLenDim->SetCustomPlane (aWorkingPlane);
786 else if (aShape1.ShapeType() == TopAbs_VERTEX
787 && aShape2.ShapeType() == TopAbs_VERTEX)
789 Message::SendFail ("Error: can not build dimension without working plane");
792 aLenDim->SetMeasuredShapes (aShape1, aShape2);
797 Message::SendFail ("Error: wrong number of shapes to build dimension");
803 case PrsDim_KOD_PLANEANGLE:
805 switch (aShapes.Extent())
809 if (Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(aShapes.First()))
811 if (aShape->Shape().ShapeType() == TopAbs_FACE)
813 aDim = new PrsDim_AngleDimension (TopoDS::Face(aShape->Shape()));
820 Handle(AIS_Shape) aShape1 = Handle(AIS_Shape)::DownCast(aShapes.First());
821 Handle(AIS_Shape) aShape2 = Handle(AIS_Shape)::DownCast(aShapes.Last());
822 if (!aShape1.IsNull() && !aShape2.IsNull()
823 && aShape1->Shape().ShapeType() == TopAbs_EDGE
824 && aShape2->Shape().ShapeType() == TopAbs_EDGE)
826 aDim = new PrsDim_AngleDimension (TopoDS::Edge(aShape1->Shape()), TopoDS::Edge(aShape2->Shape()));
830 Message::SendFail ("Error: wrong shapes for angle dimension");
838 Standard_Integer aPntIndex = 0;
839 for (NCollection_List<Handle(AIS_InteractiveObject)>::Iterator aPntIter (aShapes); aPntIter.More(); aPntIter.Next())
841 if (Handle(AIS_Point) aPoint = Handle(AIS_Point)::DownCast (aPntIter.Value()))
843 aPnts[aPntIndex++] = aPoint->Component()->Pnt();
848 aDim = new PrsDim_AngleDimension (aPnts[0], aPnts[1], aPnts[2]);
855 Message::SendFail ("Error: wrong number of shapes to build dimension");
860 case PrsDim_KOD_RADIUS: // radius of the circle
863 bool hasAnchor = false;
864 for (NCollection_List<Handle(AIS_InteractiveObject)>::Iterator aShapeIter (aShapes); aShapeIter.More(); aShapeIter.Next())
866 if (Handle(AIS_Point) aPoint = Handle(AIS_Point)::DownCast(aShapeIter.Value()))
869 anAnchor = aPoint->Component()->Pnt();
870 aShapes.Remove (aShapeIter);
874 if (aShapes.Extent() != 1)
876 Message::SendFail ("Syntax error: wrong number of shapes to build dimension");
880 if (Handle(AIS_Circle) aShapeCirc = Handle(AIS_Circle)::DownCast(aShapes.First()))
882 gp_Circ aCircle = aShapeCirc->Circle()->Circ();
885 aDim = new PrsDim_RadiusDimension (aCircle, anAnchor);
889 aDim = new PrsDim_RadiusDimension (aCircle);
892 else if (Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(aShapes.First()))
894 Handle(PrsDim_RadiusDimension) aRadDim = new PrsDim_RadiusDimension (aShape->Shape());
897 aRadDim->SetMeasuredGeometry (aShape->Shape(), anAnchor);
903 Message::SendFail ("Error: shape for radius has wrong type");
908 case PrsDim_KOD_DIAMETER:
910 if (aShapes.Extent() == 1)
912 if (aShapes.First()->DynamicType() == STANDARD_TYPE(AIS_Circle))
914 Handle(AIS_Circle) aShape = Handle(AIS_Circle)::DownCast (aShapes.First());
915 gp_Circ aCircle = aShape->Circle()->Circ();
916 aDim = new PrsDim_DiameterDimension (aCircle);
920 Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast (aShapes.First());
923 Message::SendFail ("Error: shape for radius is of wrong type");
926 aDim = new PrsDim_DiameterDimension (aShape->Shape());
931 Message::SendFail ("Error: wrong number of shapes to build dimension");
939 Message::SendFail ("Error: wrong type of dimension. Type help for more information");
944 // Check dimension geometry
945 if (!aDim->IsValid())
947 Message::SendFail() << "Error: dimension geometry is invalid, " << aDimType
948 << " dimension can't be built on input shapes.";
952 aDim->SetDimensionAspect (anAspect);
954 SetDimensionParams (aDim, aRealParams, aStringParams);
956 VDisplayAISObject (aName,aDim);
963 //! If the given shapes are edges then check whether they are parallel else return true.
964 Standard_Boolean IsParallel (const TopoDS_Shape& theShape1,
965 const TopoDS_Shape& theShape2)
967 if (theShape1.ShapeType() == TopAbs_EDGE
968 && theShape2.ShapeType() == TopAbs_EDGE)
970 BRepExtrema_ExtCC aDelta (TopoDS::Edge (theShape1),
971 TopoDS::Edge (theShape2));
972 return aDelta.IsParallel();
975 return Standard_True;
978 //=======================================================================
979 //function : VRelationBuilder
980 //purpose : Command for building realation presentation
981 //=======================================================================
982 static int VRelationBuilder (Draw_Interpretor& /*theDi*/,
983 Standard_Integer theArgsNb,
984 const char** theArgs)
988 Message::SendFail ("Error: wrong number of arguments");
992 TCollection_AsciiString aName (theArgs[1]);
993 TCollection_AsciiString aType (theArgs[2]);
995 PrsDim_KindOfRelation aKindOfRelation = PrsDim_KOR_NONE;
996 if (aType == "-concentric")
998 aKindOfRelation = PrsDim_KOR_CONCENTRIC;
1000 else if (aType == "-equaldistance")
1002 aKindOfRelation = PrsDim_KOR_EQUALDISTANCE;
1004 else if (aType == "-equalradius")
1006 aKindOfRelation = PrsDim_KOR_EQUALRADIUS;
1008 else if (aType == "-fix")
1010 aKindOfRelation = PrsDim_KOR_FIX;
1012 else if (aType == "-identic")
1014 aKindOfRelation = PrsDim_KOR_IDENTIC;
1016 else if (aType == "-offset")
1018 aKindOfRelation = PrsDim_KOR_OFFSET;
1020 else if (aType == "-parallel")
1022 aKindOfRelation = PrsDim_KOR_PARALLEL;
1024 else if (aType == "-perpendicular")
1026 aKindOfRelation = PrsDim_KOR_PERPENDICULAR;
1028 else if (aType == "-tangent")
1030 aKindOfRelation = PrsDim_KOR_TANGENT;
1032 else if (aType == "-symmetric")
1034 aKindOfRelation = PrsDim_KOR_SYMMETRIC;
1037 TopTools_ListOfShape aShapes;
1038 ViewerTest::GetSelectedShapes (aShapes);
1041 Handle(PrsDim_Relation) aRelation;
1042 switch (aKindOfRelation)
1044 case PrsDim_KOR_CONCENTRIC:
1046 if (aShapes.Extent() != 2)
1048 Message::SendFail ("Error: Wrong number of selected shapes");
1052 const TopoDS_Shape& aShape1 = aShapes.First();
1053 const TopoDS_Shape& aShape2 = aShapes.Last();
1055 if (!(aShape1.ShapeType() == TopAbs_EDGE
1056 && aShape2.ShapeType() == TopAbs_EDGE))
1058 Message::SendFail ("Syntax error: selected shapes are not edges");
1062 BRepAdaptor_Curve aCurve1 (TopoDS::Edge (aShape1));
1063 gp_Circ aCircle1 = aCurve1.Circle();
1064 gp_Pnt aCenter1 = aCircle1.Location();
1065 gp_Pnt B = aCurve1.Value (0.25);
1066 gp_Pnt C = aCurve1.Value (0.75);
1067 GC_MakePlane aMkPlane (aCenter1, B, C);
1069 aRelation = new PrsDim_ConcentricRelation (aShape1, aShape2, aMkPlane.Value());
1073 case PrsDim_KOR_EQUALDISTANCE:
1075 if (aShapes.Extent() != 4)
1077 Message::SendFail ("Error: Wrong number of selected shapes");
1081 TopoDS_Shape aSelectedShapes[4];
1083 Standard_Integer anIdx = 0;
1084 TopTools_ListOfShape::Iterator anIter (aShapes);
1085 for (; anIter.More(); anIter.Next(), ++anIdx)
1087 aSelectedShapes[anIdx] = anIter.Value();
1090 if (!IsParallel (aSelectedShapes[0], aSelectedShapes[1])
1091 || !IsParallel (aSelectedShapes[2], aSelectedShapes[3]))
1093 Message::SendFail ("Syntax error: non parallel edges");
1098 if (aSelectedShapes[0].ShapeType() == TopAbs_EDGE)
1100 TopoDS_Vertex Va, Vb;
1101 TopExp::Vertices (TopoDS::Edge (aSelectedShapes[0]), Va, Vb);
1102 A = BRep_Tool::Pnt (Va);
1103 B = BRep_Tool::Pnt (Vb);
1105 if (aSelectedShapes[1].ShapeType() == TopAbs_EDGE)
1107 TopoDS_Vertex Vc, Vd;
1108 TopExp::Vertices (TopoDS::Edge (aSelectedShapes[1]), Vc, Vd);
1109 C = BRep_Tool::Pnt (Vc);
1113 C = BRep_Tool::Pnt (TopoDS::Vertex (aSelectedShapes[1]));
1118 A = BRep_Tool::Pnt (TopoDS::Vertex (aSelectedShapes[0]));
1120 if (aSelectedShapes[1].ShapeType() == TopAbs_EDGE)
1122 TopoDS_Vertex Vb, Vc;
1123 TopExp::Vertices (TopoDS::Edge (aSelectedShapes[1]), Vb, Vc);
1124 B = BRep_Tool::Pnt (Vb);
1125 C = BRep_Tool::Pnt (Vc);
1130 B = BRep_Tool::Pnt (TopoDS::Vertex (aSelectedShapes[1]));
1131 C.SetX (B.X() + 5.0);
1132 C.SetY (B.Y() + 5.0);
1133 C.SetZ (B.Z() + 5.0);
1138 GC_MakePlane aMkPlane (A, B, C);
1139 aRelation = new PrsDim_EqualDistanceRelation (aSelectedShapes[0], aSelectedShapes[1], aSelectedShapes[2], aSelectedShapes[3], aMkPlane.Value());
1143 case PrsDim_KOR_EQUALRADIUS:
1145 if (aShapes.Extent() != 2 && aShapes.Extent() != 1)
1147 Message::SendFail ("Error: Wrong number of selected shapes");
1151 const TopoDS_Shape& aShape1 = aShapes.First();
1152 const TopoDS_Shape& aShape2 = (aShapes.Extent() == 2) ? aShapes.Last() : aShape1;
1153 if (!(aShape1.ShapeType() == TopAbs_EDGE
1154 && aShape2.ShapeType() == TopAbs_EDGE))
1156 Message::SendFail ("Syntax error: selected shapes are not edges");
1160 TopoDS_Edge anEdge1 = TopoDS::Edge (aShape1);
1161 TopoDS_Edge anEdge2 = TopoDS::Edge (aShape2);
1162 BRepAdaptor_Curve aCurve1 (anEdge1);
1163 gp_Pnt A = aCurve1.Value (0.1);
1164 gp_Pnt B = aCurve1.Value (0.5);
1165 gp_Pnt C = aCurve1.Value (0.9);
1166 GC_MakePlane aMkPlane (A, B, C);
1168 aRelation = new PrsDim_EqualRadiusRelation (anEdge1, anEdge2, aMkPlane.Value());
1171 case PrsDim_KOR_FIX:
1173 if (aShapes.Extent() != 1)
1175 Message::SendFail ("Error: Wrong number of selected shapes");
1179 const TopoDS_Shape& aShape = aShapes.First();
1180 if (aShape.ShapeType() != TopAbs_EDGE)
1182 Message::SendFail ("Syntax error: selected shapes are not edges");
1186 TopoDS_Edge anEdge = TopoDS::Edge (aShape);
1187 BRepAdaptor_Curve aCurve (anEdge);
1188 gp_Pnt A = aCurve.Value(0.1);
1189 gp_Pnt B = aCurve.Value(0.5);
1190 gp_Pnt D = aCurve.Value(0.9);
1191 gp_Pnt C (B.X() + 5.0, B.Y() + 5.0, B.Z() + 5.0);
1192 GC_MakePlane aMkPlane (A, D, C);
1194 aRelation = new PrsDim_FixRelation (anEdge, aMkPlane.Value());
1197 case PrsDim_KOR_IDENTIC:
1199 if (aShapes.Extent() != 2)
1201 Message::SendFail ("Error: Wrong number of selected shapes");
1205 const TopoDS_Shape& aShapeA = aShapes.First();
1206 const TopoDS_Shape& aShapeB = aShapes.Last();
1209 if (aShapeA.ShapeType() == TopAbs_EDGE)
1211 TopoDS_Edge anEdgeA = TopoDS::Edge (aShapeA);
1212 BRepAdaptor_Curve aCurveA (anEdgeA);
1214 A = aCurveA.Value (0.1);
1215 B = aCurveA.Value (0.9);
1216 C.SetX (B.X() + 5.0);
1217 C.SetY (B.Y() + 5.0);
1218 C.SetZ (B.Z() + 5.0);
1220 else if (aShapeA.ShapeType() == TopAbs_VERTEX)
1222 if (aShapeB.ShapeType() == TopAbs_EDGE)
1224 TopoDS_Edge anEdgeB = TopoDS::Edge (aShapeB);
1225 BRepAdaptor_Curve aCurveB (anEdgeB);
1227 A = aCurveB.Value (0.1);
1228 B = aCurveB.Value (0.9);
1229 C.SetX (B.X() + 5.0);
1230 C.SetY (B.Y() + 5.0);
1231 C.SetZ (B.Z() + 5.0);
1233 else if (aShapeB.ShapeType() == TopAbs_FACE)
1235 TopoDS_Face aFaceB = TopoDS::Face (aShapeB);
1236 TopExp_Explorer aFaceExp (aFaceB, TopAbs_EDGE);
1237 TopoDS_Edge anEdgeFromB = TopoDS::Edge (aFaceExp.Current());
1238 BRepAdaptor_Curve aCurveB (anEdgeFromB);
1239 A = aCurveB.Value (0.1);
1240 B = aCurveB.Value (0.5);
1241 C = aCurveB.Value (0.9);
1245 A = BRep_Tool::Pnt (TopoDS::Vertex (aShapeA));
1246 B = BRep_Tool::Pnt (TopoDS::Vertex (aShapeB));
1247 C.SetX (B.X() + 5.0);
1248 C.SetY (B.Y() + 5.0);
1249 C.SetZ (B.Z() + 5.0);
1254 TopoDS_Face aFaceA = TopoDS::Face (aShapeA);
1255 TopExp_Explorer aFaceExp (aFaceA, TopAbs_EDGE);
1256 TopoDS_Edge anEdgeFromA = TopoDS::Edge (aFaceExp.Current());
1257 BRepAdaptor_Curve aCurveA (anEdgeFromA);
1258 A = aCurveA.Value (0.1);
1259 B = aCurveA.Value (0.5);
1260 C = aCurveA.Value (0.9);
1263 GC_MakePlane aMkPlane (A ,B ,C);
1264 aRelation = new PrsDim_IdenticRelation (aShapeA, aShapeB, aMkPlane.Value());
1267 case PrsDim_KOR_OFFSET:
1269 if (aShapes.Extent() != 2)
1271 Message::SendFail ("Error: Wrong number of selected shapes");
1275 const TopoDS_Shape& aShape1 = aShapes.First();
1276 const TopoDS_Shape& aShape2 = aShapes.Last();
1277 if (!(aShape1.ShapeType() == TopAbs_FACE
1278 && aShape2.ShapeType() == TopAbs_FACE))
1280 Message::SendFail ("Syntax error: selected shapes are not faces");
1284 TopoDS_Face aFace1 = TopoDS::Face (aShape1);
1285 TopoDS_Face aFace2 = TopoDS::Face (aShape2);
1287 BRepExtrema_ExtFF aDelta (aFace1, aFace2);
1288 if (!aDelta.IsParallel())
1290 Message::SendFail ("Syntax error: the faces are not parallel");
1294 Standard_Real aDist = Round (sqrt (aDelta.SquareDistance (1)) * 10.0) / 10.0;
1295 TCollection_ExtendedString aMessage (TCollection_ExtendedString ("offset=") + TCollection_ExtendedString (aDist));
1296 aRelation = new PrsDim_OffsetDimension (aFace1, aFace2, aDist, aMessage);
1299 case PrsDim_KOR_PARALLEL:
1301 if (aShapes.Extent() != 2)
1303 Message::SendFail ("Error: wrong number of selected shapes");
1307 const TopoDS_Shape& aShapeA = aShapes.First();
1308 const TopoDS_Shape& aShapeB = aShapes.Last();
1309 if (aShapeA.ShapeType() == TopAbs_EDGE)
1311 TopoDS_Edge anEdgeA = TopoDS::Edge (aShapeA);
1312 TopoDS_Edge anEdgeB = TopoDS::Edge (aShapeB);
1313 BRepExtrema_ExtCC aDeltaEdge (anEdgeA, anEdgeB);
1315 if (!aDeltaEdge.IsParallel())
1317 Message::SendFail ("Error: the edges are not parallel");
1321 BRepAdaptor_Curve aCurveA (anEdgeA);
1322 BRepAdaptor_Curve aCurveB (anEdgeB);
1324 gp_Pnt A = aCurveA.Value (0.1);
1325 gp_Pnt B = aCurveA.Value (0.9);
1326 gp_Pnt C = aCurveB.Value (0.5);
1328 GC_MakePlane aMkPlane (A, B, C);
1330 aRelation = new PrsDim_ParallelRelation (anEdgeA, anEdgeB, aMkPlane.Value());
1334 TopoDS_Face aFaceA = TopoDS::Face (aShapeA);
1335 TopoDS_Face aFaceB = TopoDS::Face (aShapeB);
1337 BRepExtrema_ExtFF aDeltaFace (aFaceA, aFaceB);
1338 if (!aDeltaFace.IsParallel())
1340 Message::SendFail ("Error: the faces are not parallel");
1344 TopExp_Explorer aFaceExpA (aFaceA, TopAbs_EDGE);
1345 TopExp_Explorer aFaceExpB (aFaceB, TopAbs_EDGE);
1347 TopoDS_Edge anEdgeA = TopoDS::Edge (aFaceExpA.Current());
1348 TopoDS_Edge anEdgeB = TopoDS::Edge (aFaceExpB.Current());
1350 BRepAdaptor_Curve aCurveA (anEdgeA);
1351 BRepAdaptor_Curve aCurveB (anEdgeB);
1352 gp_Pnt A = aCurveA.Value (0.1);
1353 gp_Pnt B = aCurveA.Value (0.9);
1354 gp_Pnt C = aCurveB.Value (0.5);
1356 GC_MakePlane aMkPlane (A, B, C);
1358 aRelation = new PrsDim_ParallelRelation (aFaceA, aFaceB, aMkPlane.Value());
1362 case PrsDim_KOR_PERPENDICULAR:
1364 if (aShapes.Extent() != 2)
1366 Message::SendFail ("Error: Wrong number of selected shapes");
1370 const TopoDS_Shape& aShapeA = aShapes.First();
1371 const TopoDS_Shape& aShapeB = aShapes.Last();
1373 if (aShapeA.ShapeType() == TopAbs_EDGE)
1375 TopoDS_Edge anEdgeA = TopoDS::Edge (aShapeA);
1376 TopoDS_Edge anEdgeB = TopoDS::Edge (aShapeB);
1378 BRepAdaptor_Curve aCurveA (anEdgeA);
1379 BRepAdaptor_Curve aCurveB (anEdgeB);
1381 gp_Pnt A = aCurveA.Value (0.1);
1382 gp_Pnt B = aCurveA.Value (0.9);
1383 gp_Pnt C = aCurveB.Value (0.5);
1385 GC_MakePlane aMkPlane (A, B, C);
1387 aRelation = new PrsDim_PerpendicularRelation (anEdgeA, anEdgeB, aMkPlane.Value());
1391 TopoDS_Face aFaceA = TopoDS::Face (aShapeA);
1392 TopoDS_Face aFaceB = TopoDS::Face (aShapeB);
1394 TopExp_Explorer aFaceExpA (aFaceA, TopAbs_EDGE);
1395 TopExp_Explorer aFaceExpB (aFaceB, TopAbs_EDGE);
1397 TopoDS_Edge anEdgeA = TopoDS::Edge (aFaceExpA.Current());
1398 TopoDS_Edge anEdgeB = TopoDS::Edge (aFaceExpB.Current());
1400 BRepAdaptor_Curve aCurveA (anEdgeA);
1401 BRepAdaptor_Curve aCurveB (anEdgeB);
1403 gp_Pnt A = aCurveA.Value (0.1);
1404 gp_Pnt B = aCurveA.Value (0.9);
1405 gp_Pnt C = aCurveB.Value (0.5);
1407 GC_MakePlane aMkPlane (A, B, C);
1409 aRelation = new PrsDim_PerpendicularRelation (aFaceA, aFaceB);
1414 case PrsDim_KOR_TANGENT:
1416 if (aShapes.Extent() != 2)
1418 Message::SendFail ("Error: Wrong number of selected shapes");
1422 const TopoDS_Shape& aShapeA = aShapes.First();
1423 const TopoDS_Shape& aShapeB = aShapes.Last();
1425 if (aShapeA.ShapeType() == TopAbs_EDGE)
1427 TopoDS_Edge anEdgeA = TopoDS::Edge (aShapeA);
1428 TopoDS_Edge anEdgeB = TopoDS::Edge (aShapeB);
1430 BRepAdaptor_Curve aCurveA (anEdgeA);
1431 BRepAdaptor_Curve aCurveB (anEdgeB);
1433 gp_Pnt A = aCurveA.Value (0.1);
1434 gp_Pnt B = aCurveA.Value (0.9);
1435 gp_Pnt C = aCurveB.Value (0.5);
1437 GC_MakePlane aMkPlane (A,B,C);
1439 aRelation = new PrsDim_TangentRelation (anEdgeA, anEdgeB, aMkPlane.Value());
1443 TopoDS_Face aFaceA = TopoDS::Face (aShapeA);
1444 TopoDS_Face aFaceB = TopoDS::Face (aShapeB);
1446 TopExp_Explorer aFaceExpA (aFaceA, TopAbs_EDGE);
1447 TopExp_Explorer aFaceExpB (aFaceB, TopAbs_EDGE);
1449 TopoDS_Edge anEdgeA = TopoDS::Edge (aFaceExpA.Current());
1450 TopoDS_Edge anEdgeB = TopoDS::Edge (aFaceExpB.Current());
1452 BRepAdaptor_Curve aCurveA (anEdgeA);
1453 BRepAdaptor_Curve aCurveB (anEdgeB);
1455 gp_Pnt A = aCurveA.Value (0.1);
1456 gp_Pnt B = aCurveA.Value (0.9);
1457 gp_Pnt C = aCurveB.Value (0.5);
1459 GC_MakePlane aMkPlane (A,B,C);
1461 aRelation = new PrsDim_TangentRelation (aFaceA, aFaceB, aMkPlane.Value());
1465 case PrsDim_KOR_SYMMETRIC:
1467 if (aShapes.Extent() != 3)
1469 Message::SendFail ("Error: Wrong number of selected shapes");
1473 TopoDS_Shape aSelectedShapes[3];
1474 Standard_Integer anIdx = 0;
1475 TopTools_ListOfShape::Iterator anIter (aShapes);
1476 for (; anIter.More(); anIter.Next(), ++anIdx)
1478 aSelectedShapes[anIdx] = anIter.Value();
1481 TopoDS_Edge anEdgeA = TopoDS::Edge (aSelectedShapes[0]);
1482 if (aSelectedShapes[1].ShapeType() == TopAbs_EDGE)
1484 // 1 - edge, 2 - edge, 3 - edge.
1485 TopoDS_Edge anEdgeB = TopoDS::Edge (aSelectedShapes[1]);
1486 TopoDS_Edge anEdgeC = TopoDS::Edge (aSelectedShapes[2]);
1488 BRepExtrema_ExtCC aDeltaEdgeAB (anEdgeA, anEdgeB);
1489 BRepExtrema_ExtCC aDeltaEdgeAC (anEdgeA, anEdgeC);
1491 if (!aDeltaEdgeAB.IsParallel())
1493 Message::SendFail ("Syntax error: the edges are not parallel");
1496 if (!aDeltaEdgeAC.IsParallel())
1498 Message::SendFail ("Syntax error: the edges are not parallel");
1502 TopoDS_Vertex Va, Vb, Vc, Vd;
1503 TopExp::Vertices (anEdgeB, Va, Vb);
1504 TopExp::Vertices (anEdgeC, Vc, Vd);
1505 gp_Pnt A = BRep_Tool::Pnt (Va);
1506 gp_Pnt B = BRep_Tool::Pnt (Vc);
1507 gp_Pnt C = Get3DPointAtMousePosition();
1509 GC_MakePlane aMkPlane (A, B, C);
1511 aRelation = new PrsDim_SymmetricRelation (anEdgeA, anEdgeB, anEdgeC, aMkPlane.Value());
1515 // 1 - edge, 2 - vertex, 3 - vertex
1516 TopoDS_Vertex aVertexB = TopoDS::Vertex (aSelectedShapes[1]);
1517 TopoDS_Vertex aVertexC = TopoDS::Vertex (aSelectedShapes[2]);
1519 gp_Pnt B = BRep_Tool::Pnt (aVertexB);
1520 gp_Pnt C = BRep_Tool::Pnt (aVertexC);
1522 TopoDS_Vertex Va, Vb;
1523 TopExp::Vertices (anEdgeA, Va, Vb);
1524 gp_Pnt A = BRep_Tool::Pnt (Va);
1526 GC_MakePlane aMkPlane(A, B, C);
1527 aRelation = new PrsDim_SymmetricRelation (anEdgeA, aVertexB, aVertexC, aMkPlane.Value());
1532 case PrsDim_KOR_NONE:
1534 Message::SendFail ("Error: Unknown type of relation!");
1539 VDisplayAISObject (aName, aRelation);
1543 //=======================================================================
1544 //function : VDimParam
1545 //purpose : Sets aspect parameters to dimension.
1546 //=======================================================================
1547 static int VDimParam (Draw_Interpretor& theDi, Standard_Integer theArgNum, const char** theArgVec)
1551 theDi << theArgVec[0] << " error: the wrong number of input parameters.\n";
1556 TCollection_AsciiString aName (theArgVec[1]);
1557 gp_Pln aWorkingPlane;
1558 Standard_Boolean isCustomPlane = Standard_False;
1559 Standard_Boolean toUpdate = Standard_True;
1561 NCollection_DataMap<TCollection_AsciiString, Standard_Real> aRealParams;
1562 NCollection_DataMap<TCollection_AsciiString, TCollection_AsciiString> aStringParams;
1564 Handle(AIS_InteractiveObject) anObject;
1565 if (!GetMapOfAIS().Find2 (aName, anObject))
1567 theDi << theArgVec[0] << "error: no object with this name.\n";
1570 Handle(PrsDim_Dimension) aDim = Handle(PrsDim_Dimension)::DownCast (anObject);
1573 theDi << theArgVec[0] << "error: no dimension with this name.\n";
1577 Handle(Prs3d_DimensionAspect) anAspect = aDim->DimensionAspect();
1579 if (ParseDimensionParams (theArgNum, theArgVec, 2, anAspect,
1580 isCustomPlane, aWorkingPlane,
1581 aRealParams, aStringParams))
1588 aDim->SetCustomPlane (aWorkingPlane);
1591 SetDimensionParams (aDim, aRealParams, aStringParams);
1593 if (!aDim->IsValid())
1595 Message::SendFail ("Error: Dimension geometry or plane is not valid");
1599 // Redisplay a dimension after parameter changing.
1600 if (ViewerTest::GetAISContext()->IsDisplayed (aDim))
1602 ViewerTest::GetAISContext()->Redisplay (aDim, toUpdate);
1608 //=======================================================================
1609 //function : VLengthParam
1610 //purpose : Sets parameters to length dimension.
1611 //=======================================================================
1612 static int VLengthParam (Draw_Interpretor&, Standard_Integer theArgNum, const char** theArgVec)
1616 Message::SendFail ("Syntax error: the wrong number of input parameters");
1620 TCollection_AsciiString aName (theArgVec[1]);
1621 Handle(AIS_InteractiveObject) anObject;
1622 if (!GetMapOfAIS().Find2 (aName, anObject))
1624 Message::SendFail() << "Syntax error: no object with name '" << aName << "'";
1628 Handle(PrsDim_LengthDimension) aLengthDim = Handle(PrsDim_LengthDimension)::DownCast (anObject);
1629 if (aLengthDim.IsNull())
1631 Message::SendFail() << "Syntax error: no length dimension with name '" << aName << "'";
1635 // parse direction value
1637 int anArgumentIt = 2;
1638 TCollection_AsciiString aParam (theArgVec[anArgumentIt]);
1641 bool isCustomDirection = false;
1642 if (aParam.IsEqual ("-direction"))
1644 if (anArgumentIt + 1 >= theArgNum)
1646 Message::SendFail() << "Error: "<< aParam <<" direction should have value";
1650 isCustomDirection = Standard_True;
1651 TCollection_AsciiString aValue = theArgVec[anArgumentIt];
1654 aDirection = gp::DX();
1655 else if (aValue == "oy")
1656 aDirection = gp::DY();
1657 else if (aValue == "oz")
1658 aDirection = gp::DZ();
1659 else if (aValue == "autodirection")
1660 isCustomDirection = false;
1663 if (anArgumentIt + 2 >= theArgNum)
1665 Message::SendFail() << "Error: wrong number of values for parameter '" << aParam << "'";
1668 // access coordinate arguments
1669 TColStd_SequenceOfReal aCoords;
1670 for (; anArgumentIt < theArgNum; ++anArgumentIt)
1672 TCollection_AsciiString anArg (theArgVec[anArgumentIt]);
1673 if (!anArg.IsRealValue (Standard_True))
1677 aCoords.Append (anArg.RealValue());
1679 // non-numeric argument too early
1680 if (aCoords.IsEmpty() || aCoords.Size() != 3)
1682 Message::SendFail ("Error: wrong number of direction arguments");
1685 aDirection = gp_Dir (aCoords.Value (1), aCoords.Value (2), aCoords.Value (3));
1689 aLengthDim->SetDirection (aDirection, isCustomDirection);
1690 if (!aLengthDim->IsValid())
1692 Message::SendFail ("Error: Dimension geometry or plane is not valid");
1696 // Redisplay a dimension after parameter changing.
1697 if (ViewerTest::GetAISContext()->IsDisplayed (aLengthDim))
1699 ViewerTest::GetAISContext()->Redisplay (aLengthDim, true);
1705 //=======================================================================
1706 //function : VAngleParam
1707 //purpose : Sets aspect parameters to angle dimension.
1708 //=======================================================================
1709 static int VAngleParam (Draw_Interpretor& theDi, Standard_Integer theArgNum, const char** theArgVec)
1713 theDi << theArgVec[0] << " error: the wrong number of input parameters.\n";
1718 TCollection_AsciiString aName (theArgVec[1]);
1719 gp_Pln aWorkingPlane;
1720 Standard_Boolean toUpdate = Standard_True;
1722 NCollection_DataMap<TCollection_AsciiString, TCollection_AsciiString> aStringParams;
1723 Handle(AIS_InteractiveObject) anObject;
1724 if (!GetMapOfAIS().Find2 (aName, anObject))
1726 theDi << theArgVec[0] << "error: no object with this name.\n";
1730 Handle(PrsDim_Dimension) aDim = Handle(PrsDim_Dimension)::DownCast (anObject);
1733 theDi << theArgVec[0] << "error: no dimension with this name.\n";
1737 Handle(Prs3d_DimensionAspect) anAspect = aDim->DimensionAspect();
1738 if (ParseAngleDimensionParams (theArgNum, theArgVec, 2, aStringParams))
1743 SetAngleDimensionParams (aDim, aStringParams);
1745 if (!aDim->IsValid())
1747 Message::SendFail ("Error: Dimension geometry or plane is not valid");
1751 // Redisplay a dimension after parameter changing.
1752 if (ViewerTest::GetAISContext()->IsDisplayed (aDim))
1754 ViewerTest::GetAISContext()->Redisplay (aDim, toUpdate);
1759 //=======================================================================
1760 //function : VMoveDim
1761 //purpose : Moves dimension or relation text label to defined or picked
1762 // position and updates the object.
1763 //draw args: vmovedim [name] [x y z]
1764 //=======================================================================
1765 static int VMoveDim (Draw_Interpretor& theDi, Standard_Integer theArgNum, const char** theArgVec)
1769 theDi << theArgVec[0] << " error: the wrong number of parameters.\n";
1773 // Parameters parsing
1774 Standard_Boolean isNameSet = (theArgNum ==2 || theArgNum == 5);
1775 Standard_Boolean isPointSet = (theArgNum == 4 || theArgNum == 5);
1777 Handle(AIS_InteractiveObject) aPickedObj;
1778 gp_Pnt aPoint (gp::Origin());
1779 Standard_Integer aMaxPickNum = 5;
1784 TCollection_AsciiString aName (theArgVec[1]);
1785 if (!GetMapOfAIS().Find2 (aName, aPickedObj)
1786 || aPickedObj.IsNull())
1788 theDi << theArgVec[0] << " error: no object with this name.\n";
1792 if (aPickedObj->Type() != AIS_KindOfInteractive_Dimension
1793 && aPickedObj->Type() != AIS_KindOfInteractive_Relation)
1795 theDi << theArgVec[0] << " error: no dimension or relation with this name.\n";
1799 else // Pick dimension or relation
1801 // Loop that will be handle picking.
1802 Standard_Integer anArgNum = 5;
1803 const char *aBuffer[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" };
1804 const char **anArgVec = (const char **) aBuffer;
1806 Standard_Boolean isPicked = Standard_False;
1807 Standard_Integer aPickNum = 0;
1808 while (!isPicked && aPickNum < aMaxPickNum)
1810 while (ViewerMainLoop (anArgNum, anArgVec)) { }
1812 for (TheAISContext()->InitSelected(); TheAISContext()->MoreSelected(); TheAISContext()->NextSelected())
1814 aPickedObj = TheAISContext()->SelectedInteractive();
1817 isPicked = (!aPickedObj.IsNull()
1818 && (aPickedObj->Type() == AIS_KindOfInteractive_Dimension
1819 || aPickedObj->Type() == AIS_KindOfInteractive_Relation));
1828 theDi << theArgVec[0] << ": no dimension or relation is selected.\n";
1836 aPoint = theArgNum == 4 ? gp_Pnt (atoi (theArgVec[1]), atoi (theArgVec[2]), atoi (theArgVec[3]))
1837 : gp_Pnt (atoi (theArgVec[2]), atoi (theArgVec[3]), atoi (theArgVec[4]));
1839 else // Pick the point
1841 Standard_Integer aPickArgNum = 5;
1842 const char *aPickBuff[] = {"VPick", "X", "VPickY", "VPickZ", "VPickShape"};
1843 const char **aPickArgVec = (const char **) aPickBuff;
1845 while (ViewerMainLoop (aPickArgNum, aPickArgVec)) { }
1847 // Set text position, update relation or dimension.
1848 if (aPickedObj->Type() == AIS_KindOfInteractive_Relation)
1850 Handle(PrsDim_Relation) aRelation = Handle(PrsDim_Relation)::DownCast (aPickedObj);
1851 aPoint = Get3DPointAtMousePosition();
1852 aRelation->SetPosition (aPoint);
1853 TheAISContext()->Redisplay (aRelation, Standard_True);
1857 Handle(PrsDim_Dimension) aDim = Handle(PrsDim_Dimension)::DownCast (aPickedObj);
1858 gp_Pnt aFirstPoint, aSecondPoint;
1859 if (aDim->KindOfDimension() == PrsDim_KOD_PLANEANGLE)
1861 Handle(PrsDim_AngleDimension) anAngleDim = Handle(PrsDim_AngleDimension)::DownCast (aDim);
1862 aFirstPoint = anAngleDim->FirstPoint();
1863 aSecondPoint = anAngleDim->SecondPoint();
1865 else if (aDim->KindOfDimension() == PrsDim_KOD_LENGTH)
1867 Handle(PrsDim_LengthDimension) aLengthDim = Handle(PrsDim_LengthDimension)::DownCast (aDim);
1868 aFirstPoint = aLengthDim->FirstPoint();
1869 aSecondPoint = aLengthDim->SecondPoint();
1871 else if (aDim->KindOfDimension() == PrsDim_KOD_RADIUS)
1873 Handle(PrsDim_RadiusDimension) aRadiusDim = Handle(PrsDim_RadiusDimension)::DownCast (aDim);
1874 aFirstPoint = aRadiusDim->AnchorPoint();
1875 aSecondPoint = aRadiusDim->Circle().Location();
1877 else if (aDim->KindOfDimension() == PrsDim_KOD_DIAMETER)
1879 Handle(PrsDim_DiameterDimension) aDiameterDim = Handle(PrsDim_DiameterDimension)::DownCast (aDim);
1880 aFirstPoint = aDiameterDim->AnchorPoint();
1881 aSecondPoint = aDiameterDim->Circle().Location();
1884 if (!Get3DPointAtMousePosition (aFirstPoint, aSecondPoint, aPoint))
1889 aDim->SetTextPosition (aPoint);
1890 TheAISContext()->Redisplay (aDim, Standard_True);
1895 // Set text position, update relation or dimension.
1896 if (Handle(PrsDim_Relation) aRelation = Handle(PrsDim_Relation)::DownCast (aPickedObj))
1898 aRelation->SetPosition (aPoint);
1899 TheAISContext()->Redisplay (aRelation, Standard_True);
1903 Handle(PrsDim_Dimension) aDim = Handle(PrsDim_Dimension)::DownCast (aPickedObj);
1904 aDim->SetTextPosition (aPoint);
1905 TheAISContext()->Redisplay (aDim, Standard_True);
1911 //=======================================================================
1912 //function : RelationsCommands
1914 //=======================================================================
1917 void ViewerTest::RelationCommands(Draw_Interpretor& theCommands)
1919 const char *group = "AISRelations";
1921 theCommands.Add("vdimension",
1922 "vdimension name {-angle|-length|-radius|-diameter}"
1923 "[-shapes shape1 [shape2 [shape3]]\n"
1925 "[-text 3d|2d wf|sh|wireframe|shading IntegerSize]\n"
1926 "[-font FontName]\n"
1927 "[-label left|right|hcenter|hfit top|bottom|vcenter|vfit]\n"
1928 "[-arrow external|internal|fit]\n"
1929 "[{-arrowlength|-arlen} RealArrowLength]\n"
1930 "[{-arrowangle|-arangle} ArrowAngle(degrees)]\n"
1931 "[-plane xoy|yoz|zox]\n"
1932 "[-flyout FloatValue -extension FloatValue]\n"
1934 "[-value CustomRealValue]\n"
1935 "[-textvalue CustomTextValue]\n"
1936 "[-dispunits DisplayUnitsString]\n"
1937 "[-modelunits ModelUnitsString]\n"
1938 "[-showunits | -hideunits]\n"
1939 " -Builds angle, length, radius and diameter dimensions.\n"
1940 " -See also: vdimparam, vmovedim.\n",
1941 __FILE__,VDimBuilder,group);
1943 theCommands.Add ("vrelation",
1944 "vrelation name {-concentric|-equaldistance|-equalradius|-fix|-identic|-offset|-parallel|-perpendicular|-tangent|-symmetric}"
1945 "\n\t\t: concentric - 2 circled edges."
1946 "\n\t\t: equaldistance - 4 vertex/edges."
1947 "\n\t\t: equalradius - 1 or 2 circled edges."
1948 "\n\t\t: fix - 1 edge."
1949 "\n\t\t: identic - 2 faces, edges or vertices."
1950 "\n\t\t: offset - 2 faces."
1951 "\n\t\t: parallel - 2 faces or 2 edges."
1952 "\n\t\t: perpendicular - 2 faces or 2 edges."
1953 "\n\t\t: tangent - two coplanar edges (first the circular edge then the tangent edge) or two faces."
1954 "\n\t\t: symmetric - 3 edges or 1 edge and 2 vertices."
1955 "-Builds specific relation from selected objects.",
1956 __FILE__, VRelationBuilder, group);
1958 theCommands.Add("vdimparam",
1960 "[-text 3d|2d wf|sh|wireframe|shading IntegerSize]\n"
1961 "[-font FontName]\n"
1962 "[-label left|right|hcenter|hfit top|bottom|vcenter|vfit]\n"
1963 "[-arrow external|internal|fit]\n"
1964 "[{-arrowlength|-arlen} RealArrowLength]\n"
1965 "[{-arrowangle|-arangle} ArrowAngle(degrees)]\n"
1966 "[-plane xoy|yoz|zox]\n"
1967 "[-flyout FloatValue -extension FloatValue]\n"
1968 "[-value CustomNumberValue]\n"
1969 "[-textvalue CustomTextValue]\n"
1970 "[-dispunits DisplayUnitsString]\n"
1971 "[-modelunits ModelUnitsString]\n"
1972 "[-showunits | -hideunits]\n"
1973 " -Sets parameters for angle, length, radius and diameter dimensions.\n"
1974 " -See also: vmovedim, vdimension.\n",
1975 __FILE__,VDimParam,group);
1977 theCommands.Add("vlengthparam",
1979 "[-direction {ox|oy|oz|x y z|autodirection}]\n"
1980 " -Sets parameters for length dimension.\n"
1981 " -See also: vdimparam, vdimension.\n",
1982 __FILE__,VLengthParam,group);
1984 theCommands.Add("vangleparam",
1986 "[-type interior|exterior]\n"
1987 "[-showarrow first|second|both|none]\n"
1988 " -Sets parameters for angle dimension.\n"
1989 " -See also: vdimparam, vdimension.\n",
1990 __FILE__,VAngleParam,group);
1992 theCommands.Add("vmovedim",
1993 "vmovedim : vmovedim [name] [x y z]"
1994 "\n\t\t: Moves picked or named (if name defined)"
1995 "\n\t\t: dimension to picked mouse position or input point."
1996 "\n\t\t: Text label of dimension 'name' is moved to position, another parts of dimensionare adjusted.",
1997 __FILE__,VMoveDim,group);