2 // File : GEOM_Sketcher.cxx
3 // Created : Wed Jul 5 10:12:09 2000
4 // Author : Martine LANGLOIS
6 // Modified : Tue Dec 11 21:28:07 2001
7 // Author : Nicolas REJNERI
10 // Copyright : Open CASCADE
13 #include "GEOM_Sketcher.h"
14 #include "utilities.h"
18 #include <Geom_Axis1Placement.hxx>
19 #include <Geom_Circle.hxx>
20 #include <Geom_Line.hxx>
21 #include <Geom_CartesianPoint.hxx>
22 #include <BRep_Tool.hxx>
23 #include <BRepBuilderAPI_MakeEdge2d.hxx>
24 #include <BRepBuilderAPI_MakeEdge.hxx>
25 #include <BRepBuilderAPI_MakeVertex.hxx>
26 #include <gp_Lin2d.hxx>
30 #include <gp_Circ2d.hxx>
31 #include <gp_Vec2d.hxx>
32 #include <IntAna_IntConicQuad.hxx>
33 #include <BRepLib.hxx>
35 #include <ProjLib.hxx>
36 #include <Precision.hxx>
38 #include <BRepTools_WireExplorer.hxx>
39 #include <GccAna_Pnt2dBisec.hxx>
40 #include <GeomAPI.hxx>
41 #include <Geom2dAPI_ProjectPointOnCurve.hxx>
42 #include <Geom2d_TrimmedCurve.hxx>
43 #include <Geom2d_Circle.hxx>
44 #include <gce_MakeCirc2d.hxx>
45 #include <GccAna_Circ2d2TanRad.hxx>
46 #include <GccAna_Circ2d2TanOn.hxx>
48 #include <GccEnt_QualifiedLin.hxx>
49 #include <GccEnt_QualifiedCirc.hxx>
50 #include <GccAna_Lin2dTanPer.hxx>
51 #include <GccAna_Lin2dTanObl.hxx>
52 #include <gce_MakeLin2d.hxx>
53 #include <GCE2d_MakeArcOfCircle.hxx>
54 #include <Precision.hxx>
56 #include <AIS_Point.hxx>
57 #include <TColgp_HArray1OfPnt2d.hxx>
58 #include <Geom2dAPI_Interpolate.hxx>
59 #include <TColgp_Array1OfVec2d.hxx>
60 #include <TColStd_HArray1OfBoolean.hxx>
61 #include <GeomAPI_ProjectPointOnCurve.hxx>
62 #include <DsgPrs_ArrowSide.hxx>
63 #include <BRepBuilderAPI_Transform.hxx>
65 #include <AIS_Drawer.hxx>
66 #include <Prs3d_TextAspect.hxx>
67 #include <Prs3d_LineAspect.hxx>
68 #include <Graphic3d_NameOfFont.hxx>
70 #include <TopoDS_Wire.hxx>
73 \class GEOM_Sketcher GEOM_Sketcher.h
77 Standard_Real resol = 1.0;
101 Sketch::Sketch(const Handle(V3d_Viewer)& aViewer) :
102 myInteractiveContext(new AIS_InteractiveContext(aViewer)),
103 myAxisColor(Quantity_Color(Quantity_NOC_YELLOW)),
104 myCurrentColor(Quantity_Color(Quantity_NOC_GREEN)),
105 myWireColor(Quantity_Color(Quantity_NOC_RED))
114 \param Quantity_Color
115 \param Quantity_Color
116 \param Quantity_Color
118 Sketch::Sketch(const Handle(V3d_Viewer)& aViewer,
119 const Quantity_Color& anAxisColor,
120 const Quantity_Color& aCurrentColor,
121 const Quantity_Color& aWireColor):
122 myInteractiveContext(new AIS_InteractiveContext(aViewer)),
123 myAxisColor(anAxisColor),
124 myCurrentColor(aCurrentColor),
125 myWireColor(aWireColor)
131 Build the current edge in a graphic mode.
132 The first signature with view coordinates is used to connect to the move event from the user interface.
133 The second signature is used when the current point is known by 2d real coordinates.
139 void Sketch::MakeCurrentEdge(const Standard_Integer Xp ,
140 const Standard_Integer Yp ,
141 const Handle(V3d_View)& aView )
143 /* 3d coordinates of the picked point */
144 Standard_Real Xv,Yv,Zv;
145 aView->Convert(Xp,Yp,Xv,Yv,Zv);
146 /* computation of real 2d coordinates in plane of sketch */
147 Standard_Real Vx,Vy,Vz;
148 aView->Proj(Vx,Vy,Vz);
154 IntAna_IntConicQuad Int(L,myPlane->Pln(),Precision::Angular());
156 if (!Int.IsParallel()) {
157 if (Int.NbPoints() > 0 ) {
159 ElSLib::Parameters(myPlane->Pln(),Sol,X,Y);
163 MakeCurrentEdge(X,Y);
167 Build the current edge in a graphic mode.
168 The first signature with view coordinates is used to connect to the move event from the user interface.
169 The second signature is used when the current point is known by 2d real coordinates.
174 void Sketch::MakeCurrentEdge(const Standard_Real X, const Standard_Real Y)
176 /* Create the current edge depending on the active mode */
177 switch (myCurrentStatus) {
179 myCurrentEdge = BRepBuilderAPI_MakeVertex(ElCLib::To3d(myPlane->Pln().Position().Ax2(),gp_Pnt2d(X,Y)));
182 MakeCurrentSegment(X,Y);
185 MakeCurrentSegment(X,Y);
191 DisplayCurrentEdge();
195 Build the current edge in a graphic mode.
196 Function to connect to the input event from the user interface.
198 void Sketch::ValidateEdge()
202 switch (myCurrentStatus) {
205 myFirstPointSketch = TopoDS::Vertex(myCurrentEdge);
206 myPresentableWire = new AIS_Shape(myFirstPointSketch);
207 myPresentableWire->SetColor(myWireColor.Name());
208 myInteractiveContext->Display(myPresentableWire);
209 pt = BRep_Tool::Pnt(myFirstPointSketch);
210 pt2d = ProjLib::Project(myPlane->Pln(),pt);
213 myCurrentStatus = SEGMENT;
218 Standard_Real first,last;
220 Handle(Geom2d_Curve) C = BRep_Tool::CurveOnSurface(TopoDS::Edge(myCurrentEdge),myPlane,L,first,last);
221 myCurrentEdge = BRepBuilderAPI_MakeEdge2d(Handle(Geom2d_Line)::DownCast(C)->Lin2d(),0.,myLengthDimension->Value());
222 if (myTransitionStatus == ANGLE ||
223 myTransitionStatus == LENGTH_FIXED ||
224 myTransitionStatus == X_FIXED ||
225 myTransitionStatus == Y_FIXED)
226 myTransitionStatus = NOCONSTRAINT;
232 myInteractiveContext->CloseLocalContext();
233 myInteractiveContext->OpenLocalContext();
234 gp_Pnt2d p1 (myLastX,myLastY);
235 pt = BRep_Tool::Pnt(TopExp::LastVertex(TopoDS::Edge(myCurrentEdge)));
236 gp_Pnt2d p2 = ProjLib::Project(myPlane->Pln(),pt);
237 GccAna_Pnt2dBisec ComputeMediatrice(p1,p2);
238 if (ComputeMediatrice.HasSolution()) {
239 myMediatrice = new Geom2d_Line(ComputeMediatrice.ThisSolution());
240 Handle(Geom_Curve) aMediatrice3d = GeomAPI::To3d(myMediatrice,myPlane->Pln());
241 myPresentableMediatrice = new AIS_Axis(Handle(Geom_Line)::DownCast(aMediatrice3d));
242 myInteractiveContext->Display(myPresentableMediatrice);
244 TopoDS_Edge e = BRepBuilderAPI_MakeEdge2d(gce_MakeCirc2d(gp_Pnt2d(0.,0),1.));
245 BRepLib::BuildCurve3d(e);
246 myLengthDimension->SetText(TCollection_ExtendedString());
247 myInteractiveContext->Redisplay(myLengthDimension,Standard_False);
248 if (myEdgesNumber == 0)
249 myPreviousEdge = TopoDS::Edge(myCurrentEdge);
250 pt2d = ProjLib::Project(myPlane->Pln(),pt);
253 myTransitionStatus = NOCONSTRAINT;
254 myCurrentStatus = ARC_CHORD_END;
258 myCurrentStatus = ARC_CHORD;
265 Add edge to current wire on an edge validation .
267 void Sketch::AddEdgeToWire()
269 myPreviousEdge = TopoDS::Edge(myCurrentEdge);
270 BRepLib::BuildCurve3d(myPreviousEdge);
271 myCurrentWire.Add(TopoDS::Edge(myPreviousEdge));
273 myPresentableWire->Set( myCurrentWire.Wire() );
274 myInteractiveContext->Redisplay(myPresentableWire);
275 myConstructionMode.Append(myCurrentStatus);
276 myConstraintMode.Append(myTransitionStatus);
277 myInteractiveContext->CloseLocalContext();
279 if (myPreviousEdge.Orientation() == TopAbs_FORWARD )
280 pt = BRep_Tool::Pnt(TopExp::LastVertex(TopoDS::Edge(myPreviousEdge)));
282 pt = BRep_Tool::Pnt(TopExp::FirstVertex(TopoDS::Edge(myPreviousEdge)));
283 gp_Pnt2d pt2d= ProjLib::Project(myPlane->Pln(),pt);
289 Set the numeric dimension for the current edge and validate creation.
292 \return Standard_Boolean
294 Standard_Boolean Sketch::SetDimension(Standard_Real& aValue)
297 if (myCurrentStatus == SEGMENT ||
298 myCurrentStatus == ARC_CHORD){
299 Standard_Real first,last;
301 Handle(Geom2d_Curve) C =
302 BRep_Tool::CurveOnSurface(TopoDS::Edge(myCurrentEdge),myPlane,L,first,last);
304 BRepBuilderAPI_MakeEdge2d(Handle(Geom2d_Line)::DownCast(C)->Lin2d(),0.,aValue);
305 DisplayCurrentEdge();
306 if (myTransitionStatus == NOCONSTRAINT) {
307 mySegmentLength = aValue;
308 myTransitionStatus = LENGTH_FIXED;
312 return Standard_True;
315 else if( myCurrentStatus == ARC_CHORD_END){
316 if (myTransitionStatus == TANGENT) return Standard_False;
318 if (myEdgesNumber > 0) {
319 if (myPreviousEdge.Orientation() == TopAbs_FORWARD)
320 p = ProjLib::Project(myPlane->Pln(),BRep_Tool::Pnt(TopExp::LastVertex(myPreviousEdge)));
322 p = ProjLib::Project(myPlane->Pln(),BRep_Tool::Pnt(TopExp::FirstVertex(myPreviousEdge)));
325 p = ProjLib::Project(myPlane->Pln(),BRep_Tool::Pnt(myFirstPointSketch));
326 GccAna_Circ2d2TanRad aSol(p, gp_Pnt2d(myLastX,myLastY),aValue,Precision::Confusion());
327 Standard_Real dist = RealLast();
328 if (aSol.NbSolutions() > 0) {
330 gp_Pnt2d pc = ProjLib::Project(myPlane->Pln(),BRep_Tool::Pnt(TopoDS::Vertex(myCenterCircle->Shape())));
331 for (Standard_Integer i =1; i<= aSol.NbSolutions(); i++) {
332 if (pc.Distance(aSol.ThisSolution(i).Location()) < dist)
333 CirSol = aSol.ThisSolution(i);
335 if (myCurrentEdge.Orientation() == TopAbs_FORWARD)
336 myCurrentEdge = BRepBuilderAPI_MakeEdge2d(aSol.ThisSolution(1),p,gp_Pnt2d(myLastX,myLastY));
338 myCurrentEdge = BRepBuilderAPI_MakeEdge2d(aSol.ThisSolution(1),gp_Pnt2d(myLastX,myLastY),p);
339 myCurrentEdge.Reverse();
341 DisplayCurrentEdge();
343 return Standard_True;
347 return Standard_False;
351 Set the numeric dimension for the current edge and validate creation.
356 void Sketch::SetDimension(Standard_Real& deltaX, Standard_Real& deltaY)
360 Standard_Real X = myLastX + deltaX;
361 Standard_Real Y = myLastY + deltaY;
362 MakeCurrentEdge(X,Y);
367 Set the numeric value of the X coordinate of current point giving a deltaX relative to previous point.
371 void Sketch::SetXDimension(Standard_Real& deltaX)
374 Standard_Real X = myLastX + deltaX;
375 Standard_Real Y = myLastY;
377 Y = Y + 100.0 * Precision::Confusion();
379 if (myTransitionStatus == NOCONSTRAINT) {
380 MakeCurrentEdge(X,Y);
381 myTransitionStatus = X_FIXED;
384 else if (myTransitionStatus == Y_FIXED) {
385 myTransitionStatus = NOCONSTRAINT;
386 MakeCurrentEdge(X,mySegmentY);
389 else if (myTransitionStatus == ANGLE) {
390 myTransitionStatus = NOCONSTRAINT;
392 if (0 <= mySegmentAngle && mySegmentAngle<= PI )
393 angle = PI - mySegmentAngle;
395 angle = mySegmentAngle - PI;
397 MakeCurrentEdge(X,Y);
401 myTransitionStatus = NOCONSTRAINT;
405 Set the numeric value of the Y coordinate of current point giving a deltaY relative to previous point.
409 void Sketch::SetYDimension(Standard_Real& deltaY)
412 Standard_Real X = myLastX;
413 Standard_Real Y = myLastY + deltaY;
416 X = X + 100.0 * Precision::Confusion();
418 if (myTransitionStatus == NOCONSTRAINT) {
419 MakeCurrentEdge(X,Y);
420 myTransitionStatus = Y_FIXED;
423 else if (myTransitionStatus == X_FIXED) {
424 myTransitionStatus = NOCONSTRAINT;
425 MakeCurrentEdge(mySegmentX,Y);
428 else if (myTransitionStatus == ANGLE) {
429 myTransitionStatus = NOCONSTRAINT;
431 if (0 <= mySegmentAngle && mySegmentAngle<= PI )
432 angle = PI - mySegmentAngle;
434 angle = mySegmentAngle - PI;
436 MakeCurrentEdge(X,Y);
440 myTransitionStatus = NOCONSTRAINT;
444 Set the numeric value of angle between 2 segments.
448 void Sketch::SetSegmentAngle(Standard_Real& aValue)
450 if (myEdgesNumber > 0) {
451 Standard_Real First,Last;
454 if (0 <= aValue && aValue<= PI )
458 Handle (Geom2d_Curve) PreviousCurve = BRep_Tool::CurveOnSurface(myPreviousEdge,myPlane,L,First,Last);
459 if (PreviousCurve->IsKind(STANDARD_TYPE(Geom2d_Line))) {
460 Handle (Geom2d_Curve) PreviousCurve = BRep_Tool::CurveOnSurface(TopoDS::Edge(myPreviousEdge),myPlane,L,First,Last);
462 GccAna_Lin2dTanObl aSol(gp_Pnt2d(myLastX,myLastY),Handle(Geom2d_Line)::DownCast(PreviousCurve)->Lin2d(),angle);
463 myCurrentEdge = BRepBuilderAPI_MakeEdge2d(aSol.ThisSolution(1),0.,myLengthDimension->Value());
465 if (myTransitionStatus == LENGTH_FIXED) {
468 else if (myTransitionStatus == X_FIXED) {
469 Standard_Real length = mySegmentX/Cos(angle);
470 SetDimension(length);
473 else if (myTransitionStatus == Y_FIXED) {
474 Standard_Real length = mySegmentY/Sin(angle);
475 SetDimension(length);
479 mySegmentAngle = aValue;
480 myTransitionStatus = ANGLE;
486 Get the angle value between 2 segments.
488 \return Standard_Real
490 Standard_Real Sketch::GetSegmentAngle()
492 return mySegmentAngle;
496 Close automatically an open sketch.
498 \return TopoDS_Wire. Return null shape if not possible.
500 TopoDS_Wire Sketch::Close()
502 myCurrentStatus = END_SKETCH;
503 myInteractiveContext->CloseAllContexts();
504 myInteractiveContext->EraseAll(Standard_False);
505 if (myEdgesNumber >= 2) {
506 BRepTools_WireExplorer Ex(myCurrentWire.Wire());
508 if (myPreviousEdge.Orientation() == TopAbs_FORWARD)
509 V1 = TopExp::LastVertex(myPreviousEdge);
511 V1 = TopExp::FirstVertex(myPreviousEdge);
512 myCurrentWire.Add(BRepBuilderAPI_MakeEdge(V1,myFirstPointSketch).Edge());
514 return myCurrentWire.Wire();
517 return TopoDS_Wire();
523 Clear sketch presentation.
527 myCurrentStatus = END_SKETCH;
528 myInteractiveContext->CloseAllContexts();
529 myInteractiveContext->EraseAll(Standard_False);
533 Terminate sketch without closing.
535 \return TopoDS_Wire. Return null shape if not possible.
537 TopoDS_Wire Sketch::End()
539 myCurrentStatus = END_SKETCH;
540 myInteractiveContext->CloseAllContexts();
541 myInteractiveContext->EraseAll(Standard_False);
542 if (myCurrentWire.IsDone()) {
543 return myCurrentWire.Wire();
546 return TopoDS_Wire();
553 Standard_Boolean Sketch::Delete()
555 myInteractiveContext->Erase(myAngleDimension,Standard_True,Standard_False);
556 myInteractiveContext->Erase(myLengthDimension,Standard_True,Standard_False);
557 myInteractiveContext->Erase(myRadiusDimension,Standard_True,Standard_False);
558 myInteractiveContext->Erase(myCenterCircle,Standard_True,Standard_False);
559 myInteractiveContext->Erase(myXDimension,Standard_True,Standard_False);
560 myInteractiveContext->Erase(myYDimension,Standard_True,Standard_False);
562 if (myCurrentStatus == BEGIN_SKETCH) {
563 myCurrentStatus = END_SKETCH;
564 myInteractiveContext->CloseAllContexts();
565 myInteractiveContext->EraseAll(Standard_False);
568 else if(myCurrentStatus == SEGMENT ||
569 myCurrentStatus == ARC_CHORD ) {
572 else if(myCurrentStatus == ARC_CHORD_END) {
573 myCurrentStatus = ARC_CHORD;
574 myInteractiveContext->CloseAllContexts();
577 if (myEdgesNumber == 0) {
578 //myInteractiveContext->EraseAll(Standard_False);
579 ChangeMode(BEGIN_SKETCH); // DCQ
580 pt = BRep_Tool::Pnt(myFirstPointSketch);
583 if (myPreviousEdge.Orientation() == TopAbs_FORWARD )
584 pt = BRep_Tool::Pnt(TopExp::LastVertex(TopoDS::Edge(myPreviousEdge)));
586 pt = BRep_Tool::Pnt(TopExp::FirstVertex(TopoDS::Edge(myPreviousEdge)));
588 gp_Pnt2d pt2d= ProjLib::Project(myPlane->Pln(),pt);
596 Set a specific plane for sketch.
600 void Sketch::SetPlane(const Handle(Geom_Plane)& aPlane)
606 Set display parameters.
610 void Sketch::SetWireColor(const Quantity_Color& aColor)
612 myWireColor = aColor;
616 Set display parameters.
620 void Sketch::SetCurrentColor(const Quantity_Color& aColor)
622 myCurrentColor = aColor;
626 Set display parameters.
630 void Sketch::SetAxisColor(const Quantity_Color& aColor)
632 myAxisColor = aColor;
637 Change mode of construction line.
639 \param aMode : SEGMENT, ARC_CHORD.
641 void Sketch::ChangeMode(const SketchStatus aMode)
644 if (myEdgesNumber > 0) {
645 if (myPreviousEdge.Orientation() == TopAbs_FORWARD)
646 p = ProjLib::Project(myPlane->Pln(),BRep_Tool::Pnt(TopExp::LastVertex(myPreviousEdge)));
648 p = ProjLib::Project(myPlane->Pln(),BRep_Tool::Pnt(TopExp::FirstVertex(myPreviousEdge)));
651 myInteractiveContext->CloseLocalContext(myInteractiveContext->IndexOfCurrentLocal());
653 if (!myCurrentStatus == BEGIN_SKETCH)
654 myCurrentStatus = aMode; /* change the mode only when the sketch is not in state BEGIN_SKETCH, i.d. fist point has been fixed */
659 Set transition constraint between consecutive edges.
661 \param aStatus : NOCONSTRAINT, TANGENT, PERPENDICULAR, ANGLE, LENGTH_FIXED, X_FIXED, Y_FIXED.
663 void Sketch::SetTransitionStatus(const TransitionStatus aStatus)
665 myTransitionStatus = aStatus;
669 Set or unset the display of dimensions.
674 void Sketch::SetParameterVisibility(const TypeOfParameter atype, const Standard_Boolean OnOff)
677 case ANGLE_PARAMETER:
678 myIsAngleDimensionVisible = OnOff;
679 if (!myIsAngleDimensionVisible && !myAngleDimension.IsNull())
680 myInteractiveContext->Erase(myAngleDimension,Standard_True,Standard_False);
682 // DisplayCurrentEdge();
684 case LENGTH_PARAMETER:
685 myIsLengthDimensionVisible = OnOff;
686 if (!myIsLengthDimensionVisible&& !myLengthDimension.IsNull())
687 myInteractiveContext->Erase(myLengthDimension,Standard_True,Standard_False);
689 // DisplayCurrentEdge();
691 case RADIUS_PARAMETER:
692 myIsRadiusDimensionVisible = OnOff;
693 if (!myIsRadiusDimensionVisible&& !myRadiusDimension.IsNull()){
694 myInteractiveContext->Erase(myRadiusDimension,Standard_True,Standard_False);
695 myInteractiveContext->Erase(myCenterCircle,Standard_True,Standard_False);
698 // DisplayCurrentEdge();
700 case XVALUE_PARAMETER:
701 myIsXDimensionVisible = OnOff;
702 if (!myIsXDimensionVisible&& !myXDimension.IsNull())
703 myInteractiveContext->Erase(myXDimension,Standard_True,Standard_False);
705 case YVALUE_PARAMETER:
706 myIsYDimensionVisible = OnOff;
707 if (!myIsYDimensionVisible&& !myYDimension.IsNull())
708 myInteractiveContext->Erase(myYDimension,Standard_True,Standard_False);
719 void Sketch::HiligthWithColor(const TypeOfParameter atype, const Quantity_NameOfColor acolor)
722 case ANGLE_PARAMETER:
723 myInteractiveContext->HilightWithColor(myAngleDimension, acolor);
725 case LENGTH_PARAMETER:
726 myInteractiveContext->HilightWithColor(myLengthDimension, acolor);
728 case RADIUS_PARAMETER:
729 myInteractiveContext->HilightWithColor(myRadiusDimension, acolor);
731 case XVALUE_PARAMETER:
732 myInteractiveContext->HilightWithColor(myXDimension, acolor);
734 case YVALUE_PARAMETER:
735 myInteractiveContext->HilightWithColor(myYDimension, acolor);
742 Unhilight parameters.
746 void Sketch::Unhiligth(const TypeOfParameter atype)
749 case ANGLE_PARAMETER:
750 myInteractiveContext->Unhilight(myAngleDimension);
752 case LENGTH_PARAMETER:
753 myInteractiveContext->Unhilight(myLengthDimension);
755 case RADIUS_PARAMETER:
756 myInteractiveContext->Unhilight(myRadiusDimension);
758 case XVALUE_PARAMETER:
759 myInteractiveContext->Unhilight(myXDimension);
761 case YVALUE_PARAMETER:
762 myInteractiveContext->Unhilight(myYDimension);
768 Check if the edition of a type of parameter is relevant depending on sketch current status.
771 \return Standard_Boolean
773 Standard_Boolean Sketch::IsValidCurrentParameter(const TypeOfParameter atype)
776 case ANGLE_PARAMETER:
777 if (myCurrentStatus != SEGMENT && myCurrentStatus != ARC_CHORD)
778 return Standard_False;
779 else if (myTransitionStatus == TANGENT || myTransitionStatus == PERPENDICULAR)
780 return Standard_False;
781 else if (myEdgesNumber < 1)
782 return Standard_False;
785 Standard_Real First,Last;
786 Handle (Geom2d_Curve) PreviousCurve = BRep_Tool::CurveOnSurface(myPreviousEdge,myPlane,L,First,Last);
787 if (!PreviousCurve->IsKind(STANDARD_TYPE(Geom2d_Line)))
788 return Standard_False;
791 case LENGTH_PARAMETER:
792 if (myCurrentStatus != SEGMENT &&
793 myCurrentStatus != ARC_CHORD /*&&
794 myCurrentStatus != CURVE_POINTS*/
796 return Standard_False;
797 else if (myTransitionStatus == LENGTH_FIXED)
798 return Standard_False;
800 case RADIUS_PARAMETER:
801 if (myCurrentStatus != ARC_CHORD_END)
802 return Standard_False;
804 case XVALUE_PARAMETER:
805 if (myCurrentStatus != SEGMENT &&
806 myCurrentStatus != ARC_CHORD /*&&
807 myCurrentStatus != CURVE_POINTS*/
809 return Standard_False;
810 else if (myTransitionStatus == X_FIXED)
811 return Standard_False;
813 case YVALUE_PARAMETER:
814 if (myCurrentStatus != SEGMENT &&
815 myCurrentStatus != ARC_CHORD /*&&
816 myCurrentStatus != CURVE_POINTS*/
818 return Standard_False;
819 else if (myTransitionStatus == Y_FIXED)
820 return Standard_False;
823 return Standard_True;
827 Set a parameter value.
832 void Sketch::SetParameterValue(const TypeOfParameter atype, Standard_Real aValue)
835 case ANGLE_PARAMETER:
836 SetSegmentAngle(aValue);
838 case LENGTH_PARAMETER:
839 SetDimension(aValue);
841 case RADIUS_PARAMETER:
842 SetDimension(aValue);
844 case XVALUE_PARAMETER:
845 SetXDimension(aValue);
847 case YVALUE_PARAMETER:
848 SetYDimension(aValue);
854 Initialisation of sketch parameters or options.
858 myPlane = new Geom_Plane (0.,0.,1.,0.);
860 BRepLib::Plane(myPlane);
862 myCurrentStatus = BEGIN_SKETCH;
863 /* In order to update the visulisation of current objects by using Redisplay method from InteractiveContext */
864 myCurrentEdge = BRepBuilderAPI_MakeVertex(gp_Pnt(0.,0.,0.));
865 myPresentableEdge = new AIS_Shape(myCurrentEdge);
866 myPresentableEdge->SetColor(myCurrentColor.Name());
867 myInteractiveContext->Display(myPresentableEdge);
868 myTransitionStatus = NOCONSTRAINT;
869 /* Init for display objects */
870 TopoDS_Vertex V1 = BRepBuilderAPI_MakeVertex(gp_Pnt(0.,0.,0.));
871 TopoDS_Vertex V2 = BRepBuilderAPI_MakeVertex(gp_Pnt(10.,0.,0.));
872 myLengthDimension = new AIS_LengthDimension (V1,V2,myPlane,0.,TCollection_ExtendedString());
873 myXDimension = new AIS_LengthDimension (V1,V2,myPlane,0.,TCollection_ExtendedString(),gp_Pnt(),DsgPrs_AS_NONE,
875 myYDimension = new AIS_LengthDimension (V1,V2,myPlane,0.,TCollection_ExtendedString(),gp_Pnt(),DsgPrs_AS_NONE,
877 myRadiusDimension = new AIS_LengthDimension (V1,V2,myPlane,0.,TCollection_ExtendedString());
878 myCenterCircle = new AIS_Shape(V1);
879 myIsLengthDimensionVisible = Standard_False;
880 myIsXDimensionVisible = Standard_False;
881 myIsYDimensionVisible = Standard_False;
882 myIsRadiusDimensionVisible = Standard_False;
886 Build the current segment.
891 void Sketch::MakeCurrentSegment(Standard_Real X, Standard_Real Y)
893 if (myTransitionStatus == NOCONSTRAINT)
894 myCurrentEdge = BRepBuilderAPI_MakeEdge2d(gp_Pnt2d(myLastX,myLastY), gp_Pnt2d(X,Y));
895 else if (myTransitionStatus == X_FIXED)
896 myCurrentEdge = BRepBuilderAPI_MakeEdge2d(gp_Pnt2d(myLastX,myLastY),gp_Pnt2d(mySegmentX,Y));
897 else if (myTransitionStatus == Y_FIXED)
898 myCurrentEdge = BRepBuilderAPI_MakeEdge2d(gp_Pnt2d(myLastX,myLastY),gp_Pnt2d(X,mySegmentY));
899 else if (myTransitionStatus == TANGENT && myEdgesNumber > 0) {
900 Standard_Real first,last;
902 Handle(Geom2d_Curve) C = BRep_Tool::CurveOnSurface(myPreviousEdge,myPlane,L,first,last);
905 if (myPreviousEdge.Orientation() == TopAbs_FORWARD)
909 gp_Lin2d aline(p1,Vt);
910 Geom2dAPI_ProjectPointOnCurve proj(gp_Pnt2d(X,Y),new Geom2d_Line(aline));
911 if (proj.NbPoints() > 0)
912 myCurrentEdge = BRepBuilderAPI_MakeEdge2d(p1,proj.Point(1));
914 else if (myTransitionStatus == PERPENDICULAR && myEdgesNumber > 0) {
915 Standard_Real first,last;
917 Handle(Geom2d_Curve) C = BRep_Tool::CurveOnSurface(myPreviousEdge,myPlane,L,first,last);
920 if (myPreviousEdge.Orientation() == TopAbs_FORWARD)
924 if (C->IsKind(STANDARD_TYPE(Geom2d_Line))) {
925 GccAna_Lin2dTanPer aSol(p1,Handle(Geom2d_Line)::DownCast(C)->Lin2d());
926 perpen = aSol.ThisSolution(1);
928 else if (C->IsKind(STANDARD_TYPE(Geom2d_Circle))) {
929 GccAna_Lin2dTanPer aSol(p1,Handle(Geom2d_Circle)::DownCast(C)->Circ2d());
930 perpen = aSol.ThisSolution(1);
932 Geom2dAPI_ProjectPointOnCurve proj(gp_Pnt2d(X,Y),new Geom2d_Line(perpen));
933 if (proj.NbPoints() > 0)
934 myCurrentEdge = BRepBuilderAPI_MakeEdge2d(p1,proj.Point(1));
936 else if (myTransitionStatus == ANGLE && myEdgesNumber > 0) {
937 Standard_Real First,Last;
939 Handle (Geom2d_Curve) PreviousCurve = BRep_Tool::CurveOnSurface(myPreviousEdge,myPlane,L,First,Last);
940 if (PreviousCurve->IsKind(STANDARD_TYPE(Geom2d_Line))) {
941 Handle (Geom2d_Curve) PreviousCurve = BRep_Tool::CurveOnSurface(TopoDS::Edge(myPreviousEdge),myPlane,L,First,Last);
943 if (0 <= mySegmentAngle && mySegmentAngle<= PI )
944 angle = PI - mySegmentAngle;
946 angle = mySegmentAngle - PI;
947 GccAna_Lin2dTanObl aSol(gp_Pnt2d(myLastX,myLastY),Handle(Geom2d_Line)::DownCast(PreviousCurve)->Lin2d(),angle);
948 Standard_Real dist = RealLast();
949 gp_Pnt2d pt(X,Y),ptproj;
950 for (Standard_Integer i =1; i<=aSol.NbSolutions(); i++) {
951 Geom2dAPI_ProjectPointOnCurve proj(pt,new Geom2d_Line(aSol.ThisSolution(i)));
952 if (pt.Distance(proj.Point(1)) < dist) {
953 dist = pt.Distance(proj.Point(1));
954 ptproj = proj.Point(1);
957 myCurrentEdge = BRepBuilderAPI_MakeEdge2d(gp_Pnt2d(myLastX,myLastY),ptproj);
960 else if (myTransitionStatus == LENGTH_FIXED && myEdgesNumber > 0) {
961 Standard_Real First,Last;
963 Handle (Geom2d_Curve) PreviousCurve = BRep_Tool::CurveOnSurface(myPreviousEdge,myPlane,L,First,Last);
964 if (PreviousCurve->IsKind(STANDARD_TYPE(Geom2d_Line))) {
965 Handle (Geom2d_Curve) PreviousCurve = BRep_Tool::CurveOnSurface(TopoDS::Edge(myPreviousEdge),myPlane,L,First,Last);
966 gp_Lin2d aline = gce_MakeLin2d(gp_Pnt2d(myLastX,myLastY), gp_Pnt2d(X,Y));
967 myCurrentEdge = BRepBuilderAPI_MakeEdge2d(aline,0.,mySegmentLength);
973 Build the current arc.
978 void Sketch::MakeCurrentArc(Standard_Real X, Standard_Real Y)
981 Standard_Boolean OK(Standard_False);
983 if (myTransitionStatus == NOCONSTRAINT) {
984 GccAna_Circ2d2TanOn aSol(gp_Pnt2d(myLastX,myLastY), gp_Pnt2d(X,Y),myMediatrice->Lin2d(),Precision::Confusion());
985 if (aSol.NbSolutions() > 0){
986 CircSol = aSol.ThisSolution(1);
990 /* Tangency with previous edge */
991 else if (myTransitionStatus == TANGENT && myEdgesNumber > 0) {
992 Standard_Real first,last;
994 Handle(Geom2d_Curve) C = BRep_Tool::CurveOnSurface(myPreviousEdge,myPlane,L,first,last);
995 if (C->IsKind(STANDARD_TYPE(Geom2d_Line))){
996 GccAna_Circ2d2TanOn aSol(GccEnt::Unqualified(Handle(Geom2d_Line)::DownCast(C)->Lin2d()), gp_Pnt2d(myLastX,myLastY),myMediatrice->Lin2d(),Precision::Confusion());
997 if (aSol.NbSolutions() > 0){
998 CircSol = aSol.ThisSolution(1);
1002 else if (C->IsKind(STANDARD_TYPE(Geom2d_Circle))) {
1003 GccAna_Circ2d2TanOn aSol(GccEnt::Unqualified(Handle(Geom2d_Circle)::DownCast(C)->Circ2d()), gp_Pnt2d(myLastX,myLastY),myMediatrice->Lin2d(),Precision::Confusion());
1004 if (aSol.NbSolutions() > 0){
1005 CircSol = aSol.ThisSolution(1);
1009 else if(C->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))) {
1013 gp_Lin2d alin2d(pc,gp_Dir2d(Vt));
1014 GccAna_Circ2d2TanOn aSol(GccEnt::Unqualified(alin2d), gp_Pnt2d(myLastX,myLastY),myMediatrice->Lin2d(),Precision::Confusion());
1015 if (aSol.NbSolutions() > 0){
1016 CircSol = aSol.ThisSolution(1);
1021 /* Tangency with the perpendicular to the previous edge */
1022 else if (myTransitionStatus == PERPENDICULAR && myEdgesNumber > 0) {
1023 Standard_Real first,last;
1025 Handle(Geom2d_Curve) C = BRep_Tool::CurveOnSurface(myPreviousEdge,myPlane,L,first,last);
1028 if (myPreviousEdge.Orientation() == TopAbs_FORWARD)
1032 if (C->IsKind(STANDARD_TYPE(Geom2d_Line))) {
1033 GccAna_Lin2dTanPer aSol(p1,Handle(Geom2d_Line)::DownCast(C)->Lin2d());
1034 perpen = aSol.ThisSolution(1);
1036 else if (C->IsKind(STANDARD_TYPE(Geom2d_Circle))) {
1037 GccAna_Lin2dTanPer aSol(p1,Handle(Geom2d_Circle)::DownCast(C)->Circ2d());
1038 perpen = aSol.ThisSolution(1);
1040 GccAna_Circ2d2TanOn aSol(GccEnt::Unqualified(perpen), gp_Pnt2d(myLastX,myLastY),myMediatrice->Lin2d(),Precision::Confusion());
1041 if (aSol.NbSolutions() > 0){
1042 CircSol = aSol.ThisSolution(1);
1048 if (myEdgesNumber > 0) {
1049 if (myPreviousEdge.Orientation() == TopAbs_FORWARD)
1050 p = ProjLib::Project(myPlane->Pln(),BRep_Tool::Pnt(TopExp::LastVertex(myPreviousEdge)));
1052 p = ProjLib::Project(myPlane->Pln(),BRep_Tool::Pnt(TopExp::FirstVertex(myPreviousEdge)));
1055 p = ProjLib::Project(myPlane->Pln(),BRep_Tool::Pnt(myFirstPointSketch));
1057 gp_Vec2d V1(p,gp_Pnt2d(X,Y));
1058 gp_Vec2d V2(p,gp_Pnt2d(myLastX,myLastY));
1059 if (V1.Angle(V2) > 0 )
1060 myCurrentEdge = BRepBuilderAPI_MakeEdge2d(CircSol,p,gp_Pnt2d(myLastX,myLastY));
1062 myCurrentEdge = BRepBuilderAPI_MakeEdge2d(CircSol,gp_Pnt2d(myLastX,myLastY),p);
1063 myCurrentEdge.Reverse();
1067 myCurrentStatus = ARC_CHORD;
1070 myInteractiveContext->CloseLocalContext();
1076 Display the current edge under construction with it's dimension.
1078 void Sketch::DisplayCurrentEdge()
1080 myPresentableEdge->Set(myCurrentEdge);
1081 myInteractiveContext->Redisplay(myPresentableEdge);
1082 if (myCurrentStatus == SEGMENT ||
1083 myCurrentStatus == ARC_CHORD ) {
1084 /* Length dimension */
1085 TopoDS_Vertex V1 = TopExp::FirstVertex(TopoDS::Edge(myCurrentEdge));
1086 TopoDS_Vertex V2 = TopExp::LastVertex(TopoDS::Edge(myCurrentEdge));
1087 DisplayLengthDimension(V1,V2);
1088 /* Angular dimension */
1089 DisplayAngleDimension();
1090 DisplayXDimension(V1,V2);
1091 DisplayYDimension(V1,V2);
1093 else if (myCurrentStatus == ARC_CHORD_END )
1094 DisplayRadiusDimension();
1096 TopoDS_Vertex V1 = TopoDS::Vertex(myCurrentEdge);
1097 TopoDS_Vertex V2 = BRepBuilderAPI_MakeVertex(gp_Pnt(0.,0.,0.));
1098 DisplayXDimension(V1,V2);
1099 DisplayYDimension(V1,V2);
1105 Display the current length dimension.
1110 void Sketch::DisplayLengthDimension(const TopoDS_Vertex& V1,const TopoDS_Vertex& V2)
1112 gp_Pnt p1 = BRep_Tool::Pnt(TopoDS::Vertex(V1));
1113 gp_Pnt p2 = BRep_Tool::Pnt(TopoDS::Vertex(V2));
1114 Standard_Real length = p1.Distance(p2);
1115 if (length <= Precision::Confusion()) return;
1116 myLengthDimension->SetFirstShape(V1);
1117 myLengthDimension->SetSecondShape(V2);
1119 myLengthDimension->SetValue(length);
1121 S.sprintf("%.1f",length);
1122 myLengthDimension->SetText(TCollection_ExtendedString(strdup(S)));
1123 if (myIsLengthDimensionVisible) {
1124 if (myInteractiveContext->IsDisplayed(myLengthDimension))
1125 myInteractiveContext->Redisplay(myLengthDimension);
1127 myInteractiveContext->Display(myLengthDimension);
1132 Display the current X dimension.
1137 void Sketch::DisplayXDimension(const TopoDS_Vertex& V1,const TopoDS_Vertex& V2)
1139 if (myTransitionStatus != X_FIXED) {
1140 gp_Pnt p1 = BRep_Tool::Pnt(TopoDS::Vertex(V1));
1141 gp_Pnt p2 = BRep_Tool::Pnt(TopoDS::Vertex(V2));
1143 gp_Lin aline(p1,myPlane->Pln().XAxis().Direction());
1144 GeomAPI_ProjectPointOnCurve proj(p2,new Geom_Line(aline));
1148 if (proj.NbPoints() > 0) {
1149 Standard_Real length = p1.Distance(proj.Point(1));
1150 if (length <= Precision::Confusion()) return;
1151 myXDimension->SetFirstShape(V1);
1152 myXDimension->SetSecondShape(V2);
1154 myXDimension->SetValue(length);
1156 S.sprintf("%.1f",length);
1157 myXDimension->SetText(TCollection_ExtendedString(strdup(S)));
1158 // myXDimension->SetPosition(proj.Point(1));
1159 pb.BaryCenter(5,proj.Point(1),5);
1160 myXDimension->SetPosition(pb);
1161 if (myIsXDimensionVisible) {
1162 if (myInteractiveContext->IsDisplayed(myXDimension))
1163 myInteractiveContext->Redisplay(myXDimension);
1165 myInteractiveContext->Display(myXDimension);
1169 myInteractiveContext->Erase(myXDimension,Standard_True,Standard_False);
1173 Display the current Y dimension.
1178 void Sketch::DisplayYDimension(const TopoDS_Vertex& V1,const TopoDS_Vertex& V2)
1180 if (myTransitionStatus != Y_FIXED) {
1182 gp_Pnt p1 = BRep_Tool::Pnt(TopoDS::Vertex(V1));
1183 gp_Pnt p2 = BRep_Tool::Pnt(TopoDS::Vertex(V2));
1184 gp_Lin aline(p2 /*p1*/, myPlane->Pln().YAxis().Direction());
1185 gp_Pnt pb = p2 /*p1*/;
1186 GeomAPI_ProjectPointOnCurve proj(p1 /*p2*/,new Geom_Line(aline));
1187 if (proj.NbPoints() > 0) {
1188 Standard_Real length = /*p1*/ p2.Distance(proj.Point(1));
1189 if (length <= Precision::Confusion()) return;
1190 myYDimension->SetFirstShape(V1);
1191 myYDimension->SetSecondShape(V2);
1193 myYDimension->SetValue(length);
1195 S.sprintf("%.1f",length);
1196 myYDimension->SetText(TCollection_ExtendedString(strdup(S)));
1197 pb.BaryCenter(5,proj.Point(1),5);
1198 myYDimension->SetPosition(pb);
1199 // myYDimension->SetPosition(p2);
1200 if (myIsYDimensionVisible) {
1201 if (myInteractiveContext->IsDisplayed(myYDimension))
1202 myInteractiveContext->Redisplay(myYDimension);
1204 myInteractiveContext->Display(myYDimension);
1208 myInteractiveContext->Erase(myYDimension,Standard_True,Standard_False);
1212 Display the current angle dimension.
1214 void Sketch::DisplayAngleDimension()
1216 if (!myIsAngleDimensionVisible)
1218 if (myEdgesNumber > 0) {
1219 Standard_Real First,Last;
1221 Handle (Geom2d_Curve) PreviousCurve = BRep_Tool::CurveOnSurface(myPreviousEdge,myPlane,L,First,Last);
1222 Handle (Geom2d_Curve) CurrentCurve = BRep_Tool::CurveOnSurface(TopoDS::Edge(myCurrentEdge),myPlane,L,First,Last);
1223 if (PreviousCurve->IsKind(STANDARD_TYPE(Geom2d_Line)) && CurrentCurve->IsKind(STANDARD_TYPE(Geom2d_Line))) {
1224 Standard_Real angle = Handle(Geom2d_Line)::DownCast(PreviousCurve)->Lin2d().Angle(Handle(Geom2d_Line)::DownCast(CurrentCurve)->Lin2d());
1226 if (0 <= angle && angle<= PI)
1230 CurrentCurve->D0((First+Last)/5.,apos);
1231 gp_Pnt apos3d = ElCLib::To3d(myPlane->Pln().Position().Ax2(),apos);
1232 Standard_Real angtext = angle*180./PI;
1233 mySegmentAngle = angle;
1234 BRepLib::BuildCurve3d(TopoDS::Edge(myCurrentEdge));
1235 fitInResol(angtext);
1238 S.sprintf("%.1f",angtext);
1239 if (myInteractiveContext->IndexOfCurrentLocal() == 0) {
1240 myInteractiveContext->OpenLocalContext();
1241 myAngleDimension = new AIS_AngleDimension(myPreviousEdge,TopoDS::Edge(myCurrentEdge),myPlane,angle,
1242 TCollection_ExtendedString(strdup(S)));
1243 myInteractiveContext->Display(myAngleDimension);
1246 myAngleDimension->SetSecondShape(myCurrentEdge);
1247 myAngleDimension->SetValue(angle);
1248 myAngleDimension->SetPosition(apos3d);
1249 myAngleDimension->SetText(TCollection_ExtendedString(strdup(S)));
1250 myInteractiveContext->Redisplay(myAngleDimension);
1257 Display the current radius dimension.
1259 void Sketch::DisplayRadiusDimension()
1261 if (! myIsRadiusDimensionVisible)
1263 BRepLib::BuildCurve3d(TopoDS::Edge(myCurrentEdge));
1264 Standard_Real First,Last;
1265 Handle (Geom_Circle) C = Handle (Geom_Circle)::DownCast(BRep_Tool::Curve(TopoDS::Edge(myCurrentEdge),First,Last));
1267 Standard_Real R = C->Radius();
1268 TopoDS_Shape V1 = BRepBuilderAPI_MakeVertex(C->Location());
1270 C->D0((First+Last)/2.,MidlePoint);
1271 TopoDS_Vertex V2 = BRepBuilderAPI_MakeVertex(MidlePoint);
1272 myRadiusDimension->SetFirstShape(V1);
1273 myRadiusDimension->SetSecondShape(V2);
1274 myRadiusDimension->SetValue(R);
1277 S.sprintf("%.1f",R);
1278 myRadiusDimension->SetText(TCollection_ExtendedString(strdup(S)));
1279 if (myInteractiveContext->IsDisplayed(myRadiusDimension))
1280 myInteractiveContext->Redisplay(myRadiusDimension);
1282 myInteractiveContext->Display(myRadiusDimension);
1283 myCenterCircle->Set(V1);
1284 if (myInteractiveContext->IsDisplayed(myCenterCircle))
1285 myInteractiveContext->Redisplay(myCenterCircle);
1287 myInteractiveContext->Display(myCenterCircle);
1292 Remove last edge from the current wire.
1294 void Sketch::RemoveLastEdge()
1296 if (myEdgesNumber == 0) {
1297 myCurrentStatus = END_SKETCH;
1298 myInteractiveContext->CloseAllContexts();
1299 myInteractiveContext->EraseAll(Standard_False);
1303 BRepTools_WireExplorer Ex;
1304 BRepBuilderAPI_MakeWire MW;
1305 Standard_Integer index = 1;
1306 myCurrentEdge = myPreviousEdge;
1307 for (Ex.Init(myCurrentWire.Wire());Ex.More();Ex.Next()){
1308 if (index <= myEdgesNumber-1) {
1309 MW.Add(Ex.Current());
1310 myPreviousEdge = Ex.Current();
1315 myCurrentStatus = (SketchStatus)myConstructionMode(myEdgesNumber);
1316 myTransitionStatus = (TransitionStatus)myConstraintMode(myEdgesNumber);
1318 myConstructionMode.Remove(index);
1319 myConstraintMode.Remove(index);
1320 if (myEdgesNumber == 0)
1321 myPresentableWire->Set(myFirstPointSketch);
1323 myPresentableWire->Set(myCurrentWire.Wire());
1324 myInteractiveContext->Redisplay(myPresentableWire);
1325 myInteractiveContext->CloseLocalContext();
1326 myPresentableEdge->Set(myCurrentEdge);
1327 myInteractiveContext->Redisplay(myPresentableEdge);
1332 Create initial constraints.
1334 void Sketch::CreateConstraints()
1336 Handle(Geom_Axis1Placement) xAxis = new Geom_Axis1Placement(myPlane->Pln().XAxis());
1337 Handle(Geom_Axis1Placement) yAxis = new Geom_Axis1Placement(myPlane->Pln().YAxis());
1338 myHAxis = new AIS_Axis(xAxis);
1339 myVAxis = new AIS_Axis(yAxis);
1340 myAngularAxis = myVAxis;
1341 myHAxis->SetColor(myAxisColor.Name());
1342 myVAxis->SetColor(myAxisColor.Name());
1343 myAngularAxis->SetColor(myAxisColor.Name());
1352 void Sketch::fitInResol(Standard_Real &toFit, Standard_Boolean minIsResol)
1354 Standard_Real sign = (toFit < 0) ? -1. : +1.;
1355 Standard_Real value = toFit + sign * resol/2.0; /* why "+ resol/2.0" ? because if resol = 0.5, 3.3 is rounded to 3.5 */
1356 int nTimesResol = int(value/resol);
1357 if ((nTimesResol == 0) && (minIsResol)) nTimesResol = 1;
1358 toFit = nTimesResol*resol;
1361 SketchStatus Sketch::GetCurrentStatus()
1363 return myCurrentStatus;
1366 Standard_Integer Sketch::GetmyEdgesNumber()
1368 return myEdgesNumber;