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 <Precision.hxx>
73 #include <StdSelect.hxx>
74 #include <TCollection_AsciiString.hxx>
75 #include <TCollection_ExtendedString.hxx>
76 #include <TColStd_MapOfInteger.hxx>
77 #include <TColStd_SequenceOfReal.hxx>
79 #include <TopAbs_ShapeEnum.hxx>
81 #include <TopExp_Explorer.hxx>
83 #include <TopoDS_Face.hxx>
84 #include <TopoDS_Solid.hxx>
85 #include <TopoDS_Vertex.hxx>
86 #include <V3d_Viewer.hxx>
87 #include <V3d_View.hxx>
89 #include <ViewerTest_DoubleMapOfInteractiveAndName.hxx>
90 #include <ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName.hxx>
91 #include <ViewerTest_EventManager.hxx>
93 extern Standard_Boolean VDisplayAISObject (const TCollection_AsciiString& theName,
94 const Handle(AIS_InteractiveObject)& theAISObj,
95 Standard_Boolean theReplaceIfExists = Standard_True);
96 extern ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS();
97 extern int ViewerMainLoop(Standard_Integer argc, const char** argv);
98 extern Handle(AIS_InteractiveContext)& TheAISContext ();
100 #define VertexMask 0x01
101 #define EdgeMask 0x02
102 #define FaceMask 0x04
104 //=======================================================================
105 //function : Get3DPointAtMousePosition
106 //purpose : Calculates the 3D points corresponding to the mouse position
107 // in the plane of the view
108 //=======================================================================
109 static gp_Pnt Get3DPointAtMousePosition()
111 Handle(V3d_View) aView = ViewerTest::CurrentView();
113 Standard_Real xv,yv,zv;
114 aView->Proj (xv,yv,zv);
115 Standard_Real xat,yat,zat;
116 aView->At(xat,yat,zat);
117 gp_Pln aPlane (gp_Pnt(xat,yat,zat), gp_Dir(xv,yv,zv));
119 Standard_Integer aPixX, aPixY;
120 Standard_Real aX, aY, aZ, aDX, aDY, aDZ;
122 ViewerTest::GetMousePosition (aPixX, aPixY);
123 aView->ConvertWithProj (aPixX, aPixY, aX, aY, aZ, aDX, aDY, aDZ);
124 gp_Lin aLine( gp_Pnt(aX, aY, aZ), gp_Dir(aDX, aDY, aDZ) );
126 // Compute intersection
127 Handle(Geom_Line) aGeomLine = new Geom_Line (aLine);
128 Handle(Geom_Plane) aGeomPlane = new Geom_Plane (aPlane);
129 GeomAPI_IntCS anIntersector (aGeomLine, aGeomPlane);
130 if (!anIntersector.IsDone() || anIntersector.NbPoints() == 0)
134 return anIntersector.Point (1);
137 //=======================================================================
138 //function : Get3DPointAtMousePosition
139 //purpose : Calculates the 3D points corresponding to the mouse position
140 // in the plane of the view
141 //=======================================================================
142 static Standard_Boolean Get3DPointAtMousePosition (const gp_Pnt& theFirstPoint,
143 const gp_Pnt& theSecondPoint,
144 gp_Pnt& theOutputPoint)
146 theOutputPoint = gp::Origin();
148 Handle(V3d_View) aView = ViewerTest::CurrentView();
150 Standard_Integer aPixX, aPixY;
151 Standard_Real aX, aY, aZ, aDx, aDy, aDz, aUx, aUy, aUz;
153 // Get 3D point in view coordinates and projection vector from the pixel point.
154 ViewerTest::GetMousePosition (aPixX, aPixY);
155 aView->ConvertWithProj (aPixX, aPixY, aX, aY, aZ, aDx, aDy, aDz);
156 gp_Lin aProjLin (gp_Pnt(aX, aY, aZ), gp_Dir(aDx, aDy, aDz));
159 gp_Vec aDimVec (theFirstPoint, theSecondPoint);
160 aView->Up (aUx, aUy, aUz);
161 gp_Vec aViewUp (aUx, aUy, aUz);
163 if (aDimVec.IsParallel (aViewUp, Precision::Angular()))
165 theOutputPoint = Get3DPointAtMousePosition();
166 return Standard_True;
169 gp_Vec aDimNormal = aDimVec ^ aViewUp;
170 gp_Pln aViewPlane= gce_MakePln (theFirstPoint, aDimNormal);
172 // Get intersection of view plane and projection line
173 Handle(Geom_Plane) aPlane = new Geom_Plane (aViewPlane);
174 Handle(Geom_Line) aProjLine = new Geom_Line (aProjLin);
175 GeomAPI_IntCS anIntersector (aProjLine, aPlane);
176 if (!anIntersector.IsDone() || anIntersector.NbPoints() == 0)
178 return Standard_False;
181 theOutputPoint = anIntersector.Point (1);
182 return Standard_True;
185 //=======================================================================
186 //function : ParseDimensionParams
187 //purpose : Auxilliary function: sets aspect parameters for
188 // length, angle, radius and diameter dimension.
190 //draw args: -text [3d|2d] [wf|sh|wireframe|shading] [Size]
191 // -label [left|right|hcenter|hfit] [top|bottom|vcenter|vfit]
192 // -arrow [external|internal|fit] [Length(int)]
193 // -arrowangle ArrowAngle(degrees)
194 // -plane xoy|yoz|zox
195 // -flyout FloatValue -extension FloatValue
197 // -value CustomRealValue
198 // -textvalue CustomTextValue
199 // -dispunits DisplayUnitsString
200 // -modelunits ModelUnitsString
204 // Warning! flyout is not an aspect value, it is for dimension parameter
205 // likewise text position, but text position override other paramaters.
206 // For text position changing use 'vmovedim'.
207 //=======================================================================
208 static int ParseDimensionParams (Standard_Integer theArgNum,
209 const char** theArgVec,
210 Standard_Integer theStartIndex,
211 const Handle(Prs3d_DimensionAspect)& theAspect,
212 Standard_Boolean& theIsCustomPlane, gp_Pln& thePlane,
213 NCollection_DataMap<TCollection_AsciiString, Standard_Real>& theRealParams,
214 NCollection_DataMap<TCollection_AsciiString, TCollection_AsciiString>& theStringParams,
215 NCollection_List<Handle(AIS_InteractiveObject)>* theShapeList = NULL)
217 theRealParams.Clear();
218 theStringParams.Clear();
220 theIsCustomPlane = Standard_False;
222 // Begin from the second parameter: the first one is dimension name
223 for (Standard_Integer anIt = theStartIndex; anIt < theArgNum; ++anIt)
225 TCollection_AsciiString aParam (theArgVec[anIt]);
228 if (aParam.Search ("-") == -1)
234 if (aParam.IsEqual ("-autovalue"))
236 theRealParams.Bind ("autovalue", 1);
240 if (aParam.IsEqual ("-showunits"))
242 theAspect->MakeUnitsDisplayed (Standard_True);
245 else if (aParam.IsEqual ("-hideunits"))
247 theAspect->MakeUnitsDisplayed (Standard_False);
250 else if (aParam.IsEqual ("-selected"))
254 std::cerr << "Error: unknown parameter '" << aParam << "'\n";
258 for (TheAISContext()->InitSelected(); TheAISContext()->MoreSelected(); TheAISContext()->NextSelected())
260 TopoDS_Shape aShape = TheAISContext()->SelectedShape();
261 if (!aShape.IsNull())
263 theShapeList->Append (new AIS_Shape (aShape));
269 // Before all non-boolean flags parsing check if a flag have at least one value.
270 if (anIt + 1 >= theArgNum)
272 std::cerr << "Error: "<< aParam <<" flag should have value.\n";
277 if (aParam.IsEqual ("-shape")
278 || aParam.IsEqual ("-shapes"))
282 std::cerr << "Error: unknown parameter '" << aParam << "'\n";
289 TCollection_AsciiString anArgString = theArgVec[anIt];
290 Handle(AIS_InteractiveObject) anAISObject;
291 Standard_CString aStr = anArgString.ToCString();
292 TopoDS_Shape aShape = DBRep::Get (aStr);
293 if (!aShape.IsNull())
295 anAISObject = new AIS_Shape (aShape);
297 else if (!GetMapOfAIS().Find2 (anArgString, anAISObject)
298 || anAISObject.IsNull())
300 std::cerr << "Error: shape with name '" << aStr << "' is not found.\n";
303 theShapeList->Append (anAISObject);
305 while (anIt + 1 < theArgNum && theArgVec[anIt + 1][0] != '-');
307 else if (aParam.IsEqual ("-text"))
312 TCollection_AsciiString aValue (theArgVec[anIt]);
314 if (aValue.IsEqual ("3d"))
316 theAspect->MakeText3d (Standard_True);
318 else if (aValue.IsEqual ("2d"))
320 theAspect->MakeText3d (Standard_False);
322 else if (aValue.IsEqual ("wf") || aValue.IsEqual ("wireframe"))
324 theAspect->MakeTextShaded (Standard_False);
326 else if ( aValue.IsEqual ("sh") || aValue.IsEqual ("shading"))
328 theAspect->MakeTextShaded (Standard_True);
330 else if (aValue.IsIntegerValue()) // text size
332 theAspect->TextAspect()->SetHeight (Draw::Atoi (aValue.ToCString()));
335 while (anIt + 1 < theArgNum && theArgVec[anIt + 1][0] != '-');
337 else if (aParam.IsEqual ("-font"))
339 if (anIt + 1 >= theArgNum)
341 std::cout << "Error: wrong number of values for parameter '" << aParam << "'.\n";
345 theAspect->TextAspect()->SetFont (theArgVec[++anIt]);
347 else if (aParam.IsEqual ("-label"))
352 TCollection_AsciiString aParamValue (theArgVec[anIt]);
353 aParamValue.LowerCase();
355 if (aParamValue == "left") { theAspect->SetTextHorizontalPosition (Prs3d_DTHP_Left); }
356 else if (aParamValue == "right") { theAspect->SetTextHorizontalPosition (Prs3d_DTHP_Right); }
357 else if (aParamValue == "hcenter") { theAspect->SetTextHorizontalPosition (Prs3d_DTHP_Center);}
358 else if (aParamValue == "hfit") { theAspect->SetTextHorizontalPosition (Prs3d_DTHP_Fit); }
359 else if (aParamValue == "above") { theAspect->SetTextVerticalPosition (Prs3d_DTVP_Above); }
360 else if (aParamValue == "below") { theAspect->SetTextVerticalPosition (Prs3d_DTVP_Below); }
361 else if (aParamValue == "vcenter") { theAspect->SetTextVerticalPosition (Prs3d_DTVP_Center);}
364 std::cerr << "Error: invalid label position: '" << aParamValue << "'.\n";
368 while (anIt + 1 < theArgNum && theArgVec[anIt+1][0] != '-');
370 else if (aParam.IsEqual ("-arrow"))
372 TCollection_AsciiString aLocalParam(theArgVec[++anIt]);
373 aLocalParam.LowerCase();
375 if (aLocalParam == "external") { theAspect->SetArrowOrientation (Prs3d_DAO_External); }
376 if (aLocalParam == "internal") { theAspect->SetArrowOrientation (Prs3d_DAO_Internal); }
377 if (aLocalParam == "fit") { theAspect->SetArrowOrientation (Prs3d_DAO_Fit); }
379 else if (aParam.IsEqual ("-arrowlength") || aParam.IsEqual ("-arlen"))
381 TCollection_AsciiString aValue (theArgVec[++anIt]);
382 if (!aValue.IsRealValue())
384 std::cerr << "Error: arrow lenght should be float degree value.\n";
387 theAspect->ArrowAspect()->SetLength (Draw::Atof (aValue.ToCString()));
389 else if (aParam.IsEqual ("-arrowangle") || aParam.IsEqual ("-arangle"))
391 TCollection_AsciiString aValue (theArgVec[++anIt]);
392 if (!aValue.IsRealValue())
394 std::cerr << "Error: arrow angle should be float degree value.\n";
397 theAspect->ArrowAspect()->SetAngle (Draw::Atof (aValue.ToCString()));
399 else if (aParam.IsEqual ("-color"))
401 theAspect->SetCommonColor (Quantity_Color (ViewerTest::GetColorFromName (theArgVec[++anIt])));
403 else if (aParam.IsEqual ("-extension"))
405 TCollection_AsciiString aLocalParam(theArgVec[++anIt]);
406 if (!aLocalParam.IsRealValue())
408 std::cerr << "Error: extension size for dimension should be real value.\n";
411 theAspect->SetExtensionSize (Draw::Atof (aLocalParam.ToCString()));
413 else if (aParam.IsEqual ("-plane"))
415 TCollection_AsciiString aValue (theArgVec[++anIt]);
419 theIsCustomPlane = Standard_True;
420 thePlane = gp_Pln (gp_Ax3 (gp::XOY()));
422 else if (aValue == "zox")
424 theIsCustomPlane = Standard_True;
425 thePlane = gp_Pln (gp_Ax3 (gp::ZOX()));
427 else if (aValue == "yoz")
429 theIsCustomPlane = Standard_True;
430 thePlane = gp_Pln (gp_Ax3 (gp::YOZ()));
434 std::cerr << "Error: wrong plane '" << aValue << "'.\n";
438 else if (aParam.IsEqual ("-flyout"))
440 TCollection_AsciiString aLocalParam(theArgVec[++anIt]);
441 if (!aLocalParam.IsRealValue())
443 std::cerr << "Error: flyout for dimension should be real value.\n";
447 theRealParams.Bind ("flyout", Draw::Atof (aLocalParam.ToCString()));
449 else if (aParam.IsEqual ("-value"))
451 TCollection_AsciiString aLocalParam(theArgVec[++anIt]);
452 if (!aLocalParam.IsRealValue())
454 std::cerr << "Error: dimension value for dimension should be real value.\n";
458 theRealParams.Bind ("value", Draw::Atof (aLocalParam.ToCString()));
460 else if (aParam.IsEqual ("-textvalue"))
462 TCollection_AsciiString aLocalParam(theArgVec[++anIt]);
464 theStringParams.Bind ("textvalue", aLocalParam);
466 else if (aParam.IsEqual ("-modelunits"))
468 TCollection_AsciiString aLocalParam(theArgVec[++anIt]);
470 theStringParams.Bind ("modelunits", aLocalParam);
472 else if (aParam.IsEqual ("-dispunits"))
474 TCollection_AsciiString aLocalParam(theArgVec[++anIt]);
476 theStringParams.Bind ("dispunits", aLocalParam);
480 std::cerr << "Error: unknown parameter '" << aParam << "'.\n";
488 //=======================================================================
489 //function : SetDimensionParams
490 //purpose : Sets parameters for dimension
491 //=======================================================================
492 static void SetDimensionParams (const Handle(PrsDim_Dimension)& theDim,
493 const NCollection_DataMap<TCollection_AsciiString, Standard_Real>& theRealParams,
494 const NCollection_DataMap<TCollection_AsciiString, TCollection_AsciiString>& theStringParams)
496 if (theRealParams.IsBound ("flyout"))
498 theDim->SetFlyout (theRealParams.Find ("flyout"));
501 if (theRealParams.IsBound ("autovalue"))
503 theDim->SetComputedValue();
506 if (theRealParams.IsBound ("value"))
508 theDim->SetCustomValue (theRealParams.Find ("value"));
511 if (theStringParams.IsBound ("textvalue"))
513 theDim->SetCustomValue (theStringParams.Find ("textvalue"));
516 if (theStringParams.IsBound ("modelunits"))
518 theDim->SetModelUnits (theStringParams.Find ("modelunits"));
521 if (theStringParams.IsBound ("dispunits"))
523 theDim->SetDisplayUnits (theStringParams.Find ("dispunits"));
527 //=======================================================================
528 //function : ParseAngleDimensionParams
529 //purpose : Auxilliary function: sets custom parameters for angle dimension.
531 //draw args: -type [interior|exterior]
532 // -showarrow [first|second|both|none]
533 //=======================================================================
534 static int ParseAngleDimensionParams (Standard_Integer theArgNum,
535 const char** theArgVec,
536 Standard_Integer theStartIndex,
537 NCollection_DataMap<TCollection_AsciiString, TCollection_AsciiString>& theStringParams)
539 theStringParams.Clear();
541 // Begin from the second parameter: the first one is dimension name
542 for (Standard_Integer anIt = theStartIndex; anIt < theArgNum; ++anIt)
544 TCollection_AsciiString aParam (theArgVec[anIt]);
547 if (aParam.Search ("-") == -1)
549 std::cerr << "Error: wrong parameter '" << aParam << "'.\n";
553 // Before all non-boolean flags parsing check if a flag have at least one value.
554 if (anIt + 1 >= theArgNum)
556 std::cerr << "Error: "<< aParam <<" flag should have value.\n";
560 if (aParam.IsEqual ("-type"))
562 TCollection_AsciiString aLocalParam(theArgVec[++anIt]);
564 theStringParams.Bind ("type", aLocalParam);
566 else if (aParam.IsEqual ("-showarrow"))
568 TCollection_AsciiString aLocalParam(theArgVec[++anIt]);
570 theStringParams.Bind ("showarrow", aLocalParam);
574 std::cerr << "Error: unknown parameter '" << aParam << "'.\n";
582 //=======================================================================
583 //function : SetAngleDimensionParams
584 //purpose : Sets parameters for angle dimension
585 //=======================================================================
586 static void SetAngleDimensionParams (const Handle(PrsDim_Dimension)& theDim,
587 const NCollection_DataMap<TCollection_AsciiString,
588 TCollection_AsciiString>& theStringParams)
590 Handle(PrsDim_AngleDimension) anAngleDim = Handle(PrsDim_AngleDimension)::DownCast (theDim);
591 if (anAngleDim.IsNull())
596 if (theStringParams.IsBound ("type"))
598 PrsDim_TypeOfAngle anAngleType = PrsDim_TypeOfAngle_Interior;
599 TCollection_AsciiString anAngleTypeStr = theStringParams.Find ("type");
600 if (anAngleTypeStr.IsEqual("interior"))
602 anAngleType = PrsDim_TypeOfAngle_Interior;
604 else if (anAngleTypeStr.IsEqual("exterior"))
606 anAngleType = PrsDim_TypeOfAngle_Exterior;
610 std::cerr << "Error: wrong angle type.\n";
612 anAngleDim->SetType(anAngleType);
615 if (theStringParams.IsBound ("showarrow"))
617 PrsDim_TypeOfAngleArrowVisibility anArrowType = PrsDim_TypeOfAngleArrowVisibility_Both;
618 TCollection_AsciiString anArrowTypeStr = theStringParams.Find ("showarrow");
619 if (anArrowTypeStr.IsEqual("both"))
621 anArrowType = PrsDim_TypeOfAngleArrowVisibility_Both;
623 else if (anArrowTypeStr.IsEqual("first"))
625 anArrowType = PrsDim_TypeOfAngleArrowVisibility_First;
627 else if (anArrowTypeStr.IsEqual("second"))
629 anArrowType = PrsDim_TypeOfAngleArrowVisibility_Second;
631 else if (anArrowTypeStr.IsEqual("none"))
633 anArrowType = PrsDim_TypeOfAngleArrowVisibility_None;
637 std::cerr << "Error: wrong showarrow type.\n";
639 anAngleDim->SetArrowsVisibility(anArrowType);
643 //=======================================================================
644 //function : VDimBuilder
645 //purpose : Command for building dimension presentations: angle,
646 // length, radius, diameter
647 //=======================================================================
648 static int VDimBuilder (Draw_Interpretor& /*theDi*/,
649 Standard_Integer theArgsNb,
650 const char** theArgs)
654 std::cerr << "Error: wrong number of arguments.\n";
659 TCollection_AsciiString aName (theArgs[1]);
661 NCollection_List<Handle(AIS_InteractiveObject)> aShapes;
662 Handle(Prs3d_DimensionAspect) anAspect = new Prs3d_DimensionAspect;
663 Standard_Boolean isPlaneCustom = Standard_False;
664 gp_Pln aWorkingPlane;
666 NCollection_DataMap<TCollection_AsciiString, Standard_Real> aRealParams;
667 NCollection_DataMap<TCollection_AsciiString, TCollection_AsciiString> aStringParams;
669 TCollection_AsciiString aDimType(theArgs[2]);
670 aDimType.LowerCase();
671 PrsDim_KindOfDimension aKindOfDimension;
672 if (aDimType == "-length")
674 aKindOfDimension = PrsDim_KOD_LENGTH;
676 else if (aDimType == "-angle")
678 aKindOfDimension = PrsDim_KOD_PLANEANGLE;
680 else if (aDimType == "-radius")
682 aKindOfDimension = PrsDim_KOD_RADIUS;
684 else if (aDimType == "-diameter" || aDimType == "-diam")
686 aKindOfDimension = PrsDim_KOD_DIAMETER;
690 std::cerr << "Error: wrong type of dimension.\n";
695 if (ParseDimensionParams (theArgsNb, theArgs, 3,
696 anAspect,isPlaneCustom,aWorkingPlane,
697 aRealParams, aStringParams, &aShapes))
703 Handle(PrsDim_Dimension) aDim;
704 switch (aKindOfDimension)
706 case PrsDim_KOD_LENGTH:
708 if (aShapes.Extent() == 1)
710 if (aShapes.First()->Type() == AIS_KOI_Shape
711 && (Handle(AIS_Shape)::DownCast(aShapes.First()))->Shape().ShapeType() != TopAbs_EDGE)
713 std::cerr << theArgs[0] << ": wrong shape type.\n";
718 std::cerr << theArgs[0] << ": can not build dimension without working plane.\n";
722 // Adjust working plane
723 TopoDS_Edge anEdge = TopoDS::Edge ((Handle(AIS_Shape)::DownCast(aShapes.First()))->Shape());
724 TopoDS_Vertex aFirst, aSecond;
725 TopExp::Vertices (anEdge, aFirst, aSecond);
726 aDim = new PrsDim_LengthDimension (anEdge, aWorkingPlane);
728 // Move standard plane (XOY, YOZ or ZOX) to the first point to make it working for dimension
729 aWorkingPlane.SetLocation (Handle(PrsDim_LengthDimension)::DownCast (aDim)->FirstPoint());
731 else if (aShapes.Extent() == 2)
733 TopoDS_Shape aShape1, aShape2;
736 if (aShapes.First()->DynamicType() == STANDARD_TYPE (AIS_Point))
738 aShape1 = Handle(AIS_Point)::DownCast (aShapes.First ())->Vertex();
740 else if (aShapes.First()->Type() == AIS_KOI_Shape)
742 aShape1 = (Handle(AIS_Shape)::DownCast (aShapes.First()))->Shape();
745 if (aShapes.Last()->DynamicType() == STANDARD_TYPE (AIS_Point))
747 aShape2 = Handle(AIS_Point)::DownCast (aShapes.Last ())->Vertex();
749 else if (aShapes.Last()->Type() == AIS_KOI_Shape)
751 aShape2 = (Handle(AIS_Shape)::DownCast (aShapes.Last()))->Shape();
754 if (aShape1.IsNull() || aShape2.IsNull())
756 std::cerr << theArgs[0] << ": wrong shape type.\n";
761 if (aShape1.ShapeType() == TopAbs_FACE && aShape2.ShapeType() == TopAbs_FACE)
763 aDim = new PrsDim_LengthDimension (TopoDS::Face (aShape1), TopoDS::Face (aShape2));
765 else if (aShape1.ShapeType() == TopAbs_FACE && aShape2.ShapeType() == TopAbs_EDGE)
767 aDim = new PrsDim_LengthDimension (TopoDS::Face (aShape1), TopoDS::Edge (aShape2));
769 else if (aShape1.ShapeType() == TopAbs_EDGE && aShape2.ShapeType() == TopAbs_FACE)
771 aDim = new PrsDim_LengthDimension (TopoDS::Face (aShape2), TopoDS::Edge (aShape1));
777 std::cerr << theArgs[0] << ": can not build dimension without working plane.\n";
780 // Vertex-Vertex case
781 if (aShape1.ShapeType() == TopAbs_VERTEX)
783 aWorkingPlane.SetLocation (BRep_Tool::Pnt (TopoDS::Vertex (aShape1)));
785 else if (aShape2.ShapeType() == TopAbs_VERTEX)
787 aWorkingPlane.SetLocation (BRep_Tool::Pnt (TopoDS::Vertex (aShape2)));
790 aDim = new PrsDim_LengthDimension (aShape1, aShape2, aWorkingPlane);
795 std::cerr << theArgs[0] << ": wrong number of shapes to build dimension.\n";
801 case PrsDim_KOD_PLANEANGLE:
803 if (aShapes.Extent() == 1 && aShapes.First()->Type()==AIS_KOI_Shape)
805 Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(aShapes.First());
806 if (aShape->Shape().ShapeType() == TopAbs_FACE)
807 aDim = new PrsDim_AngleDimension (TopoDS::Face(aShape->Shape()));
809 if (aShapes.Extent() == 2)
811 Handle(AIS_Shape) aShape1 = Handle(AIS_Shape)::DownCast(aShapes.First());
812 Handle(AIS_Shape) aShape2 = Handle(AIS_Shape)::DownCast(aShapes.Last());
813 if (!aShape1.IsNull() && !aShape2.IsNull()
814 && aShape1->Shape().ShapeType() == TopAbs_EDGE
815 && aShape2->Shape().ShapeType() == TopAbs_EDGE)
816 aDim = new PrsDim_AngleDimension (TopoDS::Edge(aShape1->Shape()),TopoDS::Edge(aShape2->Shape()));
819 std::cerr << theArgs[0] << ": wrong shapes for angle dimension.\n";
823 else if (aShapes.Extent() == 3)
825 gp_Pnt aP1, aP2, aP3;
826 Handle(AIS_Point) aPoint = Handle(AIS_Point)::DownCast (aShapes.First());
829 aP1 = aPoint->Component()->Pnt();
830 aShapes.RemoveFirst();
831 aPoint = Handle(AIS_Point)::DownCast (aShapes.First());
834 aP2 = aPoint->Component()->Pnt();
835 aShapes.RemoveFirst();
836 aPoint = Handle(AIS_Point)::DownCast (aShapes.First());
839 aP3 = aPoint->Component()->Pnt();
840 aDim = new PrsDim_AngleDimension (aP1, aP2, aP3);
844 std::cerr << theArgs[0] << ": wrong number of shapes to build dimension.\n";
850 case PrsDim_KOD_RADIUS: // radius of the circle
853 bool hasAnchor = false;
854 for (NCollection_List<Handle(AIS_InteractiveObject)>::Iterator aShapeIter (aShapes); aShapeIter.More(); aShapeIter.Next())
856 if (Handle(AIS_Point) aPoint = Handle(AIS_Point)::DownCast(aShapeIter.Value()))
859 anAnchor = aPoint->Component()->Pnt();
860 aShapes.Remove (aShapeIter);
864 if (aShapes.Extent() != 1)
866 std::cout << "Syntax error: wrong number of shapes to build dimension.\n";
870 if (Handle(AIS_Circle) aShapeCirc = Handle(AIS_Circle)::DownCast(aShapes.First()))
872 gp_Circ aCircle = aShapeCirc->Circle()->Circ();
875 aDim = new PrsDim_RadiusDimension (aCircle, anAnchor);
879 aDim = new PrsDim_RadiusDimension (aCircle);
882 else if (Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(aShapes.First()))
884 Handle(PrsDim_RadiusDimension) aRadDim = new PrsDim_RadiusDimension (aShape->Shape());
887 aRadDim->SetMeasuredGeometry (aShape->Shape(), anAnchor);
893 std::cout << "Error: shape for radius has wrong type.\n";
898 case PrsDim_KOD_DIAMETER:
900 if (aShapes.Extent() == 1)
902 if (aShapes.First()->DynamicType() == STANDARD_TYPE(AIS_Circle))
904 Handle(AIS_Circle) aShape = Handle(AIS_Circle)::DownCast (aShapes.First());
905 gp_Circ aCircle = aShape->Circle()->Circ();
906 aDim = new PrsDim_DiameterDimension (aCircle);
910 Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast (aShapes.First());
913 std::cerr << "Error: shape for radius is of wrong type.\n";
916 aDim = new PrsDim_DiameterDimension (aShape->Shape());
921 std::cerr << theArgs[0] << ": wrong number of shapes to build dimension.\n";
929 std::cerr << theArgs[0] << ": wrong type of dimension. Type help for more information.\n";
934 // Check dimension geometry
935 if (!aDim->IsValid())
937 std::cerr << theArgs[0] << ":dimension geometry is invalid, " << aDimType.ToCString()
938 << " dimension can't be built on input shapes.\n";
942 aDim->SetDimensionAspect (anAspect);
944 SetDimensionParams (aDim, aRealParams, aStringParams);
946 VDisplayAISObject (aName,aDim);
953 //! If the given shapes are edges then check whether they are parallel else return true.
954 Standard_Boolean IsParallel (const TopoDS_Shape& theShape1,
955 const TopoDS_Shape& theShape2)
957 if (theShape1.ShapeType() == TopAbs_EDGE
958 && theShape2.ShapeType() == TopAbs_EDGE)
960 BRepExtrema_ExtCC aDelta (TopoDS::Edge (theShape1),
961 TopoDS::Edge (theShape2));
962 return aDelta.IsParallel();
965 return Standard_True;
968 //=======================================================================
969 //function : VRelationBuilder
970 //purpose : Command for building realation presentation
971 //=======================================================================
972 static int VRelationBuilder (Draw_Interpretor& /*theDi*/,
973 Standard_Integer theArgsNb,
974 const char** theArgs)
978 std::cerr << "Error: wrong number of arguments.\n";
982 TCollection_AsciiString aName (theArgs[1]);
983 TCollection_AsciiString aType (theArgs[2]);
985 PrsDim_KindOfRelation aKindOfRelation = PrsDim_KOR_NONE;
986 if (aType == "-concentric")
988 aKindOfRelation = PrsDim_KOR_CONCENTRIC;
990 else if (aType == "-equaldistance")
992 aKindOfRelation = PrsDim_KOR_EQUALDISTANCE;
994 else if (aType == "-equalradius")
996 aKindOfRelation = PrsDim_KOR_EQUALRADIUS;
998 else if (aType == "-fix")
1000 aKindOfRelation = PrsDim_KOR_FIX;
1002 else if (aType == "-identic")
1004 aKindOfRelation = PrsDim_KOR_IDENTIC;
1006 else if (aType == "-offset")
1008 aKindOfRelation = PrsDim_KOR_OFFSET;
1010 else if (aType == "-parallel")
1012 aKindOfRelation = PrsDim_KOR_PARALLEL;
1014 else if (aType == "-perpendicular")
1016 aKindOfRelation = PrsDim_KOR_PERPENDICULAR;
1018 else if (aType == "-tangent")
1020 aKindOfRelation = PrsDim_KOR_TANGENT;
1022 else if (aType == "-symmetric")
1024 aKindOfRelation = PrsDim_KOR_SYMMETRIC;
1027 TopTools_ListOfShape aShapes;
1028 ViewerTest::GetSelectedShapes (aShapes);
1031 Handle(PrsDim_Relation) aRelation;
1032 switch (aKindOfRelation)
1034 case PrsDim_KOR_CONCENTRIC:
1036 if (aShapes.Extent() != 2)
1038 std::cerr << "Error: Wrong number of selected shapes.\n";
1042 const TopoDS_Shape& aShape1 = aShapes.First();
1043 const TopoDS_Shape& aShape2 = aShapes.Last();
1045 if (!(aShape1.ShapeType() == TopAbs_EDGE
1046 && aShape2.ShapeType() == TopAbs_EDGE))
1048 std::cerr << "Syntax error: selected shapes are not edges.\n";
1052 BRepAdaptor_Curve aCurve1 (TopoDS::Edge (aShape1));
1053 gp_Circ aCircle1 = aCurve1.Circle();
1054 gp_Pnt aCenter1 = aCircle1.Location();
1055 gp_Pnt B = aCurve1.Value (0.25);
1056 gp_Pnt C = aCurve1.Value (0.75);
1057 GC_MakePlane aMkPlane (aCenter1, B, C);
1059 aRelation = new PrsDim_ConcentricRelation (aShape1, aShape2, aMkPlane.Value());
1063 case PrsDim_KOR_EQUALDISTANCE:
1065 if (aShapes.Extent() != 4)
1067 std::cerr << "Error: Wrong number of selected shapes.\n";
1071 TopoDS_Shape aSelectedShapes[4];
1073 Standard_Integer anIdx = 0;
1074 TopTools_ListOfShape::Iterator anIter (aShapes);
1075 for (; anIter.More(); anIter.Next(), ++anIdx)
1077 aSelectedShapes[anIdx] = anIter.Value();
1080 if (!IsParallel (aSelectedShapes[0], aSelectedShapes[1])
1081 || !IsParallel (aSelectedShapes[2], aSelectedShapes[3]))
1083 std::cerr << "Syntax error: non parallel edges.\n";
1088 if (aSelectedShapes[0].ShapeType() == TopAbs_EDGE)
1090 TopoDS_Vertex Va, Vb;
1091 TopExp::Vertices (TopoDS::Edge (aSelectedShapes[0]), Va, Vb);
1092 A = BRep_Tool::Pnt (Va);
1093 B = BRep_Tool::Pnt (Vb);
1095 if (aSelectedShapes[1].ShapeType() == TopAbs_EDGE)
1097 TopoDS_Vertex Vc, Vd;
1098 TopExp::Vertices (TopoDS::Edge (aSelectedShapes[1]), Vc, Vd);
1099 C = BRep_Tool::Pnt (Vc);
1103 C = BRep_Tool::Pnt (TopoDS::Vertex (aSelectedShapes[1]));
1108 A = BRep_Tool::Pnt (TopoDS::Vertex (aSelectedShapes[0]));
1110 if (aSelectedShapes[1].ShapeType() == TopAbs_EDGE)
1112 TopoDS_Vertex Vb, Vc;
1113 TopExp::Vertices (TopoDS::Edge (aSelectedShapes[1]), Vb, Vc);
1114 B = BRep_Tool::Pnt (Vb);
1115 C = BRep_Tool::Pnt (Vc);
1120 B = BRep_Tool::Pnt (TopoDS::Vertex (aSelectedShapes[1]));
1121 C.SetX (B.X() + 5.0);
1122 C.SetY (B.Y() + 5.0);
1123 C.SetZ (B.Z() + 5.0);
1128 GC_MakePlane aMkPlane (A, B, C);
1129 aRelation = new PrsDim_EqualDistanceRelation (aSelectedShapes[0], aSelectedShapes[1], aSelectedShapes[2], aSelectedShapes[3], aMkPlane.Value());
1133 case PrsDim_KOR_EQUALRADIUS:
1135 if (aShapes.Extent() != 2 && aShapes.Extent() != 1)
1137 std::cerr << "Error: Wrong number of selected shapes.\n";
1141 const TopoDS_Shape& aShape1 = aShapes.First();
1142 const TopoDS_Shape& aShape2 = (aShapes.Extent() == 2) ? aShapes.Last() : aShape1;
1143 if (!(aShape1.ShapeType() == TopAbs_EDGE
1144 && aShape2.ShapeType() == TopAbs_EDGE))
1146 std::cerr << "Syntax error: selected shapes are not edges.\n";
1150 TopoDS_Edge anEdge1 = TopoDS::Edge (aShape1);
1151 TopoDS_Edge anEdge2 = TopoDS::Edge (aShape2);
1152 BRepAdaptor_Curve aCurve1 (anEdge1);
1153 gp_Pnt A = aCurve1.Value (0.1);
1154 gp_Pnt B = aCurve1.Value (0.5);
1155 gp_Pnt C = aCurve1.Value (0.9);
1156 GC_MakePlane aMkPlane (A, B, C);
1158 aRelation = new PrsDim_EqualRadiusRelation (anEdge1, anEdge2, aMkPlane.Value());
1161 case PrsDim_KOR_FIX:
1163 if (aShapes.Extent() != 1)
1165 std::cerr << "Error: Wrong number of selected shapes.\n";
1169 const TopoDS_Shape& aShape = aShapes.First();
1170 if (aShape.ShapeType() != TopAbs_EDGE)
1172 std::cerr << "Syntax error: selected shapes are not edges.\n";
1176 TopoDS_Edge anEdge = TopoDS::Edge (aShape);
1177 BRepAdaptor_Curve aCurve (anEdge);
1178 gp_Pnt A = aCurve.Value(0.1);
1179 gp_Pnt B = aCurve.Value(0.5);
1180 gp_Pnt D = aCurve.Value(0.9);
1181 gp_Pnt C (B.X() + 5.0, B.Y() + 5.0, B.Z() + 5.0);
1182 GC_MakePlane aMkPlane (A, D, C);
1184 aRelation = new PrsDim_FixRelation (anEdge, aMkPlane.Value());
1187 case PrsDim_KOR_IDENTIC:
1189 if (aShapes.Extent() != 2)
1191 std::cerr << "Error: Wrong number of selected shapes.\n";
1195 const TopoDS_Shape& aShapeA = aShapes.First();
1196 const TopoDS_Shape& aShapeB = aShapes.Last();
1199 if (aShapeA.ShapeType() == TopAbs_EDGE)
1201 TopoDS_Edge anEdgeA = TopoDS::Edge (aShapeA);
1202 BRepAdaptor_Curve aCurveA (anEdgeA);
1204 A = aCurveA.Value (0.1);
1205 B = aCurveA.Value (0.9);
1206 C.SetX (B.X() + 5.0);
1207 C.SetY (B.Y() + 5.0);
1208 C.SetZ (B.Z() + 5.0);
1210 else if (aShapeA.ShapeType() == TopAbs_VERTEX)
1212 if (aShapeB.ShapeType() == TopAbs_EDGE)
1214 TopoDS_Edge anEdgeB = TopoDS::Edge (aShapeB);
1215 BRepAdaptor_Curve aCurveB (anEdgeB);
1217 A = aCurveB.Value (0.1);
1218 B = aCurveB.Value (0.9);
1219 C.SetX (B.X() + 5.0);
1220 C.SetY (B.Y() + 5.0);
1221 C.SetZ (B.Z() + 5.0);
1223 else if (aShapeB.ShapeType() == TopAbs_FACE)
1225 TopoDS_Face aFaceB = TopoDS::Face (aShapeB);
1226 TopExp_Explorer aFaceExp (aFaceB, TopAbs_EDGE);
1227 TopoDS_Edge anEdgeFromB = TopoDS::Edge (aFaceExp.Current());
1228 BRepAdaptor_Curve aCurveB (anEdgeFromB);
1229 A = aCurveB.Value (0.1);
1230 B = aCurveB.Value (0.5);
1231 C = aCurveB.Value (0.9);
1235 A = BRep_Tool::Pnt (TopoDS::Vertex (aShapeA));
1236 B = BRep_Tool::Pnt (TopoDS::Vertex (aShapeB));
1237 C.SetX (B.X() + 5.0);
1238 C.SetY (B.Y() + 5.0);
1239 C.SetZ (B.Z() + 5.0);
1244 TopoDS_Face aFaceA = TopoDS::Face (aShapeA);
1245 TopExp_Explorer aFaceExp (aFaceA, TopAbs_EDGE);
1246 TopoDS_Edge anEdgeFromA = TopoDS::Edge (aFaceExp.Current());
1247 BRepAdaptor_Curve aCurveA (anEdgeFromA);
1248 A = aCurveA.Value (0.1);
1249 B = aCurveA.Value (0.5);
1250 C = aCurveA.Value (0.9);
1253 GC_MakePlane aMkPlane (A ,B ,C);
1254 aRelation = new PrsDim_IdenticRelation (aShapeA, aShapeB, aMkPlane.Value());
1257 case PrsDim_KOR_OFFSET:
1259 if (aShapes.Extent() != 2)
1261 std::cerr << "Error: Wrong number of selected shapes.\n";
1265 const TopoDS_Shape& aShape1 = aShapes.First();
1266 const TopoDS_Shape& aShape2 = aShapes.Last();
1267 if (!(aShape1.ShapeType() == TopAbs_FACE
1268 && aShape2.ShapeType() == TopAbs_FACE))
1270 std::cerr << "Syntax error: selected shapes are not faces.\n";
1274 TopoDS_Face aFace1 = TopoDS::Face (aShape1);
1275 TopoDS_Face aFace2 = TopoDS::Face (aShape2);
1277 BRepExtrema_ExtFF aDelta (aFace1, aFace2);
1278 if (!aDelta.IsParallel())
1280 std::cerr << "Syntax error: the faces are not parallel.\n";
1284 Standard_Real aDist = Round (sqrt (aDelta.SquareDistance (1)) * 10.0) / 10.0;
1285 TCollection_ExtendedString aMessage (TCollection_ExtendedString ("offset=") + TCollection_ExtendedString (aDist));
1286 aRelation = new PrsDim_OffsetDimension (aFace1, aFace2, aDist, aMessage);
1289 case PrsDim_KOR_PARALLEL:
1291 if (aShapes.Extent() != 2)
1293 std::cerr << "Error: wrong number of selected shapes.\n";
1297 const TopoDS_Shape& aShapeA = aShapes.First();
1298 const TopoDS_Shape& aShapeB = aShapes.Last();
1299 if (aShapeA.ShapeType() == TopAbs_EDGE)
1301 TopoDS_Edge anEdgeA = TopoDS::Edge (aShapeA);
1302 TopoDS_Edge anEdgeB = TopoDS::Edge (aShapeB);
1303 BRepExtrema_ExtCC aDeltaEdge (anEdgeA, anEdgeB);
1305 if (!aDeltaEdge.IsParallel())
1307 std::cerr << "Error: the edges are not parallel.\n";
1311 BRepAdaptor_Curve aCurveA (anEdgeA);
1312 BRepAdaptor_Curve aCurveB (anEdgeB);
1314 gp_Pnt A = aCurveA.Value (0.1);
1315 gp_Pnt B = aCurveA.Value (0.9);
1316 gp_Pnt C = aCurveB.Value (0.5);
1318 GC_MakePlane aMkPlane (A, B, C);
1320 aRelation = new PrsDim_ParallelRelation (anEdgeA, anEdgeB, aMkPlane.Value());
1324 TopoDS_Face aFaceA = TopoDS::Face (aShapeA);
1325 TopoDS_Face aFaceB = TopoDS::Face (aShapeB);
1327 BRepExtrema_ExtFF aDeltaFace (aFaceA, aFaceB);
1328 if (!aDeltaFace.IsParallel())
1330 std::cerr << "Error: the faces are not parallel.\n";
1334 TopExp_Explorer aFaceExpA (aFaceA, TopAbs_EDGE);
1335 TopExp_Explorer aFaceExpB (aFaceB, TopAbs_EDGE);
1337 TopoDS_Edge anEdgeA = TopoDS::Edge (aFaceExpA.Current());
1338 TopoDS_Edge anEdgeB = TopoDS::Edge (aFaceExpB.Current());
1340 BRepAdaptor_Curve aCurveA (anEdgeA);
1341 BRepAdaptor_Curve aCurveB (anEdgeB);
1342 gp_Pnt A = aCurveA.Value (0.1);
1343 gp_Pnt B = aCurveA.Value (0.9);
1344 gp_Pnt C = aCurveB.Value (0.5);
1346 GC_MakePlane aMkPlane (A, B, C);
1348 aRelation = new PrsDim_ParallelRelation (aFaceA, aFaceB, aMkPlane.Value());
1352 case PrsDim_KOR_PERPENDICULAR:
1354 if (aShapes.Extent() != 2)
1356 std::cerr << "Error: Wrong number of selected shapes.\n";
1360 const TopoDS_Shape& aShapeA = aShapes.First();
1361 const TopoDS_Shape& aShapeB = aShapes.Last();
1363 if (aShapeA.ShapeType() == TopAbs_EDGE)
1365 TopoDS_Edge anEdgeA = TopoDS::Edge (aShapeA);
1366 TopoDS_Edge anEdgeB = TopoDS::Edge (aShapeB);
1368 BRepAdaptor_Curve aCurveA (anEdgeA);
1369 BRepAdaptor_Curve aCurveB (anEdgeB);
1371 gp_Pnt A = aCurveA.Value (0.1);
1372 gp_Pnt B = aCurveA.Value (0.9);
1373 gp_Pnt C = aCurveB.Value (0.5);
1375 GC_MakePlane aMkPlane (A, B, C);
1377 aRelation = new PrsDim_PerpendicularRelation (anEdgeA, anEdgeB, aMkPlane.Value());
1381 TopoDS_Face aFaceA = TopoDS::Face (aShapeA);
1382 TopoDS_Face aFaceB = TopoDS::Face (aShapeB);
1384 TopExp_Explorer aFaceExpA (aFaceA, TopAbs_EDGE);
1385 TopExp_Explorer aFaceExpB (aFaceB, TopAbs_EDGE);
1387 TopoDS_Edge anEdgeA = TopoDS::Edge (aFaceExpA.Current());
1388 TopoDS_Edge anEdgeB = TopoDS::Edge (aFaceExpB.Current());
1390 BRepAdaptor_Curve aCurveA (anEdgeA);
1391 BRepAdaptor_Curve aCurveB (anEdgeB);
1393 gp_Pnt A = aCurveA.Value (0.1);
1394 gp_Pnt B = aCurveA.Value (0.9);
1395 gp_Pnt C = aCurveB.Value (0.5);
1397 GC_MakePlane aMkPlane (A, B, C);
1399 aRelation = new PrsDim_PerpendicularRelation (aFaceA, aFaceB);
1404 case PrsDim_KOR_TANGENT:
1406 if (aShapes.Extent() != 2)
1408 std::cerr << "Error: Wrong number of selected shapes.\n";
1412 const TopoDS_Shape& aShapeA = aShapes.First();
1413 const TopoDS_Shape& aShapeB = aShapes.Last();
1415 if (aShapeA.ShapeType() == TopAbs_EDGE)
1417 TopoDS_Edge anEdgeA = TopoDS::Edge (aShapeA);
1418 TopoDS_Edge anEdgeB = TopoDS::Edge (aShapeB);
1420 BRepAdaptor_Curve aCurveA (anEdgeA);
1421 BRepAdaptor_Curve aCurveB (anEdgeB);
1423 gp_Pnt A = aCurveA.Value (0.1);
1424 gp_Pnt B = aCurveA.Value (0.9);
1425 gp_Pnt C = aCurveB.Value (0.5);
1427 GC_MakePlane aMkPlane (A,B,C);
1429 aRelation = new PrsDim_TangentRelation (anEdgeA, anEdgeB, aMkPlane.Value());
1433 TopoDS_Face aFaceA = TopoDS::Face (aShapeA);
1434 TopoDS_Face aFaceB = TopoDS::Face (aShapeB);
1436 TopExp_Explorer aFaceExpA (aFaceA, TopAbs_EDGE);
1437 TopExp_Explorer aFaceExpB (aFaceB, TopAbs_EDGE);
1439 TopoDS_Edge anEdgeA = TopoDS::Edge (aFaceExpA.Current());
1440 TopoDS_Edge anEdgeB = TopoDS::Edge (aFaceExpB.Current());
1442 BRepAdaptor_Curve aCurveA (anEdgeA);
1443 BRepAdaptor_Curve aCurveB (anEdgeB);
1445 gp_Pnt A = aCurveA.Value (0.1);
1446 gp_Pnt B = aCurveA.Value (0.9);
1447 gp_Pnt C = aCurveB.Value (0.5);
1449 GC_MakePlane aMkPlane (A,B,C);
1451 aRelation = new PrsDim_TangentRelation (aFaceA, aFaceB, aMkPlane.Value());
1455 case PrsDim_KOR_SYMMETRIC:
1457 if (aShapes.Extent() != 3)
1459 std::cerr << "Error: Wrong number of selected shapes.\n";
1463 TopoDS_Shape aSelectedShapes[3];
1464 Standard_Integer anIdx = 0;
1465 TopTools_ListOfShape::Iterator anIter (aShapes);
1466 for (; anIter.More(); anIter.Next(), ++anIdx)
1468 aSelectedShapes[anIdx] = anIter.Value();
1471 TopoDS_Edge anEdgeA = TopoDS::Edge (aSelectedShapes[0]);
1472 if (aSelectedShapes[1].ShapeType() == TopAbs_EDGE)
1474 // 1 - edge, 2 - edge, 3 - edge.
1475 TopoDS_Edge anEdgeB = TopoDS::Edge (aSelectedShapes[1]);
1476 TopoDS_Edge anEdgeC = TopoDS::Edge (aSelectedShapes[2]);
1478 BRepExtrema_ExtCC aDeltaEdgeAB (anEdgeA, anEdgeB);
1479 BRepExtrema_ExtCC aDeltaEdgeAC (anEdgeA, anEdgeC);
1481 if (!aDeltaEdgeAB.IsParallel())
1483 std::cerr << "Syntax error: the edges are not parallel.\n";
1486 if (!aDeltaEdgeAC.IsParallel())
1488 std::cerr << "Syntax error: the edges are not parallel.\n";
1492 TopoDS_Vertex Va, Vb, Vc, Vd;
1493 TopExp::Vertices (anEdgeB, Va, Vb);
1494 TopExp::Vertices (anEdgeC, Vc, Vd);
1495 gp_Pnt A = BRep_Tool::Pnt (Va);
1496 gp_Pnt B = BRep_Tool::Pnt (Vc);
1497 gp_Pnt C = Get3DPointAtMousePosition();
1499 GC_MakePlane aMkPlane (A, B, C);
1501 aRelation = new PrsDim_SymmetricRelation (anEdgeA, anEdgeB, anEdgeC, aMkPlane.Value());
1505 // 1 - edge, 2 - vertex, 3 - vertex
1506 TopoDS_Vertex aVertexB = TopoDS::Vertex (aSelectedShapes[1]);
1507 TopoDS_Vertex aVertexC = TopoDS::Vertex (aSelectedShapes[2]);
1509 gp_Pnt B = BRep_Tool::Pnt (aVertexB);
1510 gp_Pnt C = BRep_Tool::Pnt (aVertexC);
1512 TopoDS_Vertex Va, Vb;
1513 TopExp::Vertices (anEdgeA, Va, Vb);
1514 gp_Pnt A = BRep_Tool::Pnt (Va);
1516 GC_MakePlane aMkPlane(A, B, C);
1517 aRelation = new PrsDim_SymmetricRelation (anEdgeA, aVertexB, aVertexC, aMkPlane.Value());
1522 case PrsDim_KOR_NONE:
1524 std::cerr << "Error: Unknown type of relation!\n";
1529 VDisplayAISObject (aName, aRelation);
1533 //=======================================================================
1534 //function : VDimParam
1535 //purpose : Sets aspect parameters to dimension.
1536 //=======================================================================
1537 static int VDimParam (Draw_Interpretor& theDi, Standard_Integer theArgNum, const char** theArgVec)
1541 theDi << theArgVec[0] << " error: the wrong number of input parameters.\n";
1546 TCollection_AsciiString aName (theArgVec[1]);
1547 gp_Pln aWorkingPlane;
1548 Standard_Boolean isCustomPlane = Standard_False;
1549 Standard_Boolean toUpdate = Standard_True;
1551 NCollection_DataMap<TCollection_AsciiString, Standard_Real> aRealParams;
1552 NCollection_DataMap<TCollection_AsciiString, TCollection_AsciiString> aStringParams;
1554 Handle(AIS_InteractiveObject) anObject;
1555 if (!GetMapOfAIS().Find2 (aName, anObject))
1557 theDi << theArgVec[0] << "error: no object with this name.\n";
1560 Handle(PrsDim_Dimension) aDim = Handle(PrsDim_Dimension)::DownCast (anObject);
1563 theDi << theArgVec[0] << "error: no dimension with this name.\n";
1567 Handle(Prs3d_DimensionAspect) anAspect = aDim->DimensionAspect();
1569 if (ParseDimensionParams (theArgNum, theArgVec, 2, anAspect,
1570 isCustomPlane, aWorkingPlane,
1571 aRealParams, aStringParams))
1578 aDim->SetCustomPlane (aWorkingPlane);
1581 SetDimensionParams (aDim, aRealParams, aStringParams);
1583 if (!aDim->IsValid())
1585 std::cerr << "Error: Dimension geometry or plane is not valid.\n";
1589 // Redisplay a dimension after parameter changing.
1590 if (ViewerTest::GetAISContext()->IsDisplayed (aDim))
1592 ViewerTest::GetAISContext()->Redisplay (aDim, toUpdate);
1598 //=======================================================================
1599 //function : VLengthParam
1600 //purpose : Sets parameters to length dimension.
1601 //=======================================================================
1602 static int VLengthParam (Draw_Interpretor&, Standard_Integer theArgNum, const char** theArgVec)
1606 std::cout << theArgVec[0] << " error: the wrong number of input parameters.\n";
1610 TCollection_AsciiString aName (theArgVec[1]);
1611 Handle(AIS_InteractiveObject) anObject;
1612 if (!GetMapOfAIS().Find2 (aName, anObject))
1614 std::cout << theArgVec[0] << "error: no object with this name.\n";
1618 Handle(PrsDim_LengthDimension) aLengthDim = Handle(PrsDim_LengthDimension)::DownCast (anObject);
1619 if (aLengthDim.IsNull())
1621 std::cout << theArgVec[0] << "error: no length dimension with this name.\n";
1625 // parse direction value
1627 int anArgumentIt = 2;
1628 TCollection_AsciiString aParam (theArgVec[anArgumentIt]);
1631 bool isCustomDirection = false;
1632 if (aParam.IsEqual ("-direction"))
1634 if (anArgumentIt + 1 >= theArgNum)
1636 std::cout << "Error: "<< aParam <<" direction should have value.\n";
1640 isCustomDirection = Standard_True;
1641 TCollection_AsciiString aValue = theArgVec[anArgumentIt];
1644 aDirection = gp::DX();
1645 else if (aValue == "oy")
1646 aDirection = gp::DY();
1647 else if (aValue == "oz")
1648 aDirection = gp::DZ();
1649 else if (aValue == "autodirection")
1650 isCustomDirection = false;
1653 if (anArgumentIt + 2 >= theArgNum)
1655 std::cout << "Error: wrong number of values for parameter '" << aParam << "'.\n";
1658 // access coordinate arguments
1659 TColStd_SequenceOfReal aCoords;
1660 for (; anArgumentIt < theArgNum; ++anArgumentIt)
1662 TCollection_AsciiString anArg (theArgVec[anArgumentIt]);
1663 if (!anArg.IsRealValue())
1667 aCoords.Append (anArg.RealValue());
1669 // non-numeric argument too early
1670 if (aCoords.IsEmpty() || aCoords.Size() != 3)
1672 std::cout << "Error: wrong number of direction arguments.\n";
1675 aDirection = gp_Dir (aCoords.Value (1), aCoords.Value (2), aCoords.Value (3));
1679 aLengthDim->SetDirection (aDirection, isCustomDirection);
1680 if (!aLengthDim->IsValid())
1682 std::cout << "Error: Dimension geometry or plane is not valid.\n";
1686 // Redisplay a dimension after parameter changing.
1687 if (ViewerTest::GetAISContext()->IsDisplayed (aLengthDim))
1689 ViewerTest::GetAISContext()->Redisplay (aLengthDim, true);
1695 //=======================================================================
1696 //function : VAngleParam
1697 //purpose : Sets aspect parameters to angle dimension.
1698 //=======================================================================
1699 static int VAngleParam (Draw_Interpretor& theDi, Standard_Integer theArgNum, const char** theArgVec)
1703 theDi << theArgVec[0] << " error: the wrong number of input parameters.\n";
1708 TCollection_AsciiString aName (theArgVec[1]);
1709 gp_Pln aWorkingPlane;
1710 Standard_Boolean toUpdate = Standard_True;
1712 NCollection_DataMap<TCollection_AsciiString, TCollection_AsciiString> aStringParams;
1713 Handle(AIS_InteractiveObject) anObject;
1714 if (!GetMapOfAIS().Find2 (aName, anObject))
1716 theDi << theArgVec[0] << "error: no object with this name.\n";
1720 Handle(PrsDim_Dimension) aDim = Handle(PrsDim_Dimension)::DownCast (anObject);
1723 theDi << theArgVec[0] << "error: no dimension with this name.\n";
1727 Handle(Prs3d_DimensionAspect) anAspect = aDim->DimensionAspect();
1728 if (ParseAngleDimensionParams (theArgNum, theArgVec, 2, aStringParams))
1733 SetAngleDimensionParams (aDim, aStringParams);
1735 if (!aDim->IsValid())
1737 std::cerr << "Error: Dimension geometry or plane is not valid.\n";
1741 // Redisplay a dimension after parameter changing.
1742 if (ViewerTest::GetAISContext()->IsDisplayed (aDim))
1744 ViewerTest::GetAISContext()->Redisplay (aDim, toUpdate);
1749 //=======================================================================
1750 //function : VMoveDim
1751 //purpose : Moves dimension or relation text label to defined or picked
1752 // position and updates the object.
1753 //draw args: vmovedim [name] [x y z]
1754 //=======================================================================
1755 static int VMoveDim (Draw_Interpretor& theDi, Standard_Integer theArgNum, const char** theArgVec)
1759 theDi << theArgVec[0] << " error: the wrong number of parameters.\n";
1763 // Parameters parsing
1764 Standard_Boolean isNameSet = (theArgNum ==2 || theArgNum == 5);
1765 Standard_Boolean isPointSet = (theArgNum == 4 || theArgNum == 5);
1767 Handle(AIS_InteractiveObject) aPickedObj;
1768 gp_Pnt aPoint (gp::Origin());
1769 Standard_Integer aMaxPickNum = 5;
1774 TCollection_AsciiString aName (theArgVec[1]);
1775 if (!GetMapOfAIS().Find2 (aName, aPickedObj)
1776 || aPickedObj.IsNull())
1778 theDi << theArgVec[0] << " error: no object with this name.\n";
1782 if (aPickedObj->Type() != AIS_KOI_Dimension && aPickedObj->Type() != AIS_KOI_Relation)
1784 theDi << theArgVec[0] << " error: no dimension or relation with this name.\n";
1788 else // Pick dimension or relation
1790 // Loop that will be handle picking.
1791 Standard_Integer anArgNum = 5;
1792 const char *aBuffer[] = { "VPick", "X", "VPickY","VPickZ", "VPickShape" };
1793 const char **anArgVec = (const char **) aBuffer;
1795 Standard_Boolean isPicked = Standard_False;
1796 Standard_Integer aPickNum = 0;
1797 while (!isPicked && aPickNum < aMaxPickNum)
1799 while (ViewerMainLoop (anArgNum, anArgVec)) { }
1801 for (TheAISContext()->InitSelected(); TheAISContext()->MoreSelected(); TheAISContext()->NextSelected())
1803 aPickedObj = TheAISContext()->SelectedInteractive();
1806 isPicked = (!aPickedObj.IsNull() && (aPickedObj->Type() == AIS_KOI_Dimension || aPickedObj->Type() == AIS_KOI_Relation));
1816 theDi << theArgVec[0] << ": no dimension or relation is selected.\n";
1824 aPoint = theArgNum == 4 ? gp_Pnt (atoi (theArgVec[1]), atoi (theArgVec[2]), atoi (theArgVec[3]))
1825 : gp_Pnt (atoi (theArgVec[2]), atoi (theArgVec[3]), atoi (theArgVec[4]));
1827 else // Pick the point
1829 Standard_Integer aPickArgNum = 5;
1830 const char *aPickBuff[] = {"VPick", "X", "VPickY", "VPickZ", "VPickShape"};
1831 const char **aPickArgVec = (const char **) aPickBuff;
1833 while (ViewerMainLoop (aPickArgNum, aPickArgVec)) { }
1835 // Set text position, update relation or dimension.
1836 if (aPickedObj->Type() == AIS_KOI_Relation)
1838 Handle(PrsDim_Relation) aRelation = Handle(PrsDim_Relation)::DownCast (aPickedObj);
1839 aPoint = Get3DPointAtMousePosition();
1840 aRelation->SetPosition (aPoint);
1841 TheAISContext()->Redisplay (aRelation, Standard_True);
1845 Handle(PrsDim_Dimension) aDim = Handle(PrsDim_Dimension)::DownCast (aPickedObj);
1846 gp_Pnt aFirstPoint, aSecondPoint;
1847 if (aDim->KindOfDimension() == PrsDim_KOD_PLANEANGLE)
1849 Handle(PrsDim_AngleDimension) anAngleDim = Handle(PrsDim_AngleDimension)::DownCast (aDim);
1850 aFirstPoint = anAngleDim->FirstPoint();
1851 aSecondPoint = anAngleDim->SecondPoint();
1853 else if (aDim->KindOfDimension() == PrsDim_KOD_LENGTH)
1855 Handle(PrsDim_LengthDimension) aLengthDim = Handle(PrsDim_LengthDimension)::DownCast (aDim);
1856 aFirstPoint = aLengthDim->FirstPoint();
1857 aSecondPoint = aLengthDim->SecondPoint();
1859 else if (aDim->KindOfDimension() == PrsDim_KOD_RADIUS)
1861 Handle(PrsDim_RadiusDimension) aRadiusDim = Handle(PrsDim_RadiusDimension)::DownCast (aDim);
1862 aFirstPoint = aRadiusDim->AnchorPoint();
1863 aSecondPoint = aRadiusDim->Circle().Location();
1865 else if (aDim->KindOfDimension() == PrsDim_KOD_DIAMETER)
1867 Handle(PrsDim_DiameterDimension) aDiameterDim = Handle(PrsDim_DiameterDimension)::DownCast (aDim);
1868 aFirstPoint = aDiameterDim->AnchorPoint();
1869 aSecondPoint = aDiameterDim->Circle().Location();
1872 if (!Get3DPointAtMousePosition (aFirstPoint, aSecondPoint, aPoint))
1877 aDim->SetTextPosition (aPoint);
1878 TheAISContext()->Redisplay (aDim, Standard_True);
1883 // Set text position, update relation or dimension.
1884 if (aPickedObj->Type() == AIS_KOI_Relation)
1886 Handle(PrsDim_Relation) aRelation = Handle(PrsDim_Relation)::DownCast (aPickedObj);
1887 aRelation->SetPosition (aPoint);
1888 TheAISContext()->Redisplay (aRelation, Standard_True);
1892 Handle(PrsDim_Dimension) aDim = Handle(PrsDim_Dimension)::DownCast (aPickedObj);
1893 aDim->SetTextPosition (aPoint);
1894 TheAISContext()->Redisplay (aDim, Standard_True);
1900 //=======================================================================
1901 //function : RelationsCommands
1903 //=======================================================================
1906 void ViewerTest::RelationCommands(Draw_Interpretor& theCommands)
1908 const char *group = "AISRelations";
1910 theCommands.Add("vdimension",
1911 "vdimension name {-angle|-length|-radius|-diameter}"
1912 "[-shapes shape1 [shape2 [shape3]]\n"
1914 "[-text 3d|2d wf|sh|wireframe|shading IntegerSize]\n"
1915 "[-font FontName]\n"
1916 "[-label left|right|hcenter|hfit top|bottom|vcenter|vfit]\n"
1917 "[-arrow external|internal|fit]\n"
1918 "[{-arrowlength|-arlen} RealArrowLength]\n"
1919 "[{-arrowangle|-arangle} ArrowAngle(degrees)]\n"
1920 "[-plane xoy|yoz|zox]\n"
1921 "[-flyout FloatValue -extension FloatValue]\n"
1923 "[-value CustomRealValue]\n"
1924 "[-textvalue CustomTextValue]\n"
1925 "[-dispunits DisplayUnitsString]\n"
1926 "[-modelunits ModelUnitsString]\n"
1927 "[-showunits | -hideunits]\n"
1928 " -Builds angle, length, radius and diameter dimensions.\n"
1929 " -See also: vdimparam, vmovedim.\n",
1930 __FILE__,VDimBuilder,group);
1932 theCommands.Add ("vrelation",
1933 "vrelation name {-concentric|-equaldistance|-equalradius|-fix|-identic|-offset|-parallel|-perpendicular|-tangent|-symmetric}"
1934 "\n\t\t: concentric - 2 circled edges."
1935 "\n\t\t: equaldistance - 4 vertex/edges."
1936 "\n\t\t: equalradius - 1 or 2 circled edges."
1937 "\n\t\t: fix - 1 edge."
1938 "\n\t\t: identic - 2 faces, edges or vertices."
1939 "\n\t\t: offset - 2 faces."
1940 "\n\t\t: parallel - 2 faces or 2 edges."
1941 "\n\t\t: perpendicular - 2 faces or 2 edges."
1942 "\n\t\t: tangent - two coplanar edges (first the circular edge then the tangent edge) or two faces."
1943 "\n\t\t: symmetric - 3 edges or 1 edge and 2 vertices."
1944 "-Builds specific relation from selected objects.",
1945 __FILE__, VRelationBuilder, group);
1947 theCommands.Add("vdimparam",
1949 "[-text 3d|2d wf|sh|wireframe|shading IntegerSize]\n"
1950 "[-font FontName]\n"
1951 "[-label left|right|hcenter|hfit top|bottom|vcenter|vfit]\n"
1952 "[-arrow external|internal|fit]\n"
1953 "[{-arrowlength|-arlen} RealArrowLength]\n"
1954 "[{-arrowangle|-arangle} ArrowAngle(degrees)]\n"
1955 "[-plane xoy|yoz|zox]\n"
1956 "[-flyout FloatValue -extension FloatValue]\n"
1957 "[-value CustomNumberValue]\n"
1958 "[-textvalue CustomTextValue]\n"
1959 "[-dispunits DisplayUnitsString]\n"
1960 "[-modelunits ModelUnitsString]\n"
1961 "[-showunits | -hideunits]\n"
1962 " -Sets parameters for angle, length, radius and diameter dimensions.\n"
1963 " -See also: vmovedim, vdimension.\n",
1964 __FILE__,VDimParam,group);
1966 theCommands.Add("vlengthparam",
1968 "[-direction {ox|oy|oz|x y z|autodirection}]\n"
1969 " -Sets parameters for length dimension.\n"
1970 " -See also: vdimparam, vdimension.\n",
1971 __FILE__,VLengthParam,group);
1973 theCommands.Add("vangleparam",
1975 "[-type interior|exterior]\n"
1976 "[-showarrow first|second|both|none]\n"
1977 " -Sets parameters for angle dimension.\n"
1978 " -See also: vdimparam, vdimension.\n",
1979 __FILE__,VAngleParam,group);
1981 theCommands.Add("vmovedim",
1982 "vmovedim : vmovedim [name] [x y z]"
1983 "\n\t\t: Moves picked or named (if name defined)"
1984 "\n\t\t: dimension to picked mouse position or input point."
1985 "\n\t\t: Text label of dimension 'name' is moved to position, another parts of dimensionare adjusted.",
1986 __FILE__,VMoveDim,group);