mirror of
https://git.salome-platform.org/gitpub/modules/geom.git
synced 2024-12-26 01:10:36 +05:00
1390 lines
41 KiB
C++
1390 lines
41 KiB
C++
// GEOM SKETCHER : basic sketcher
|
|
//
|
|
// Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
|
|
// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
|
|
//
|
|
// This library is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU Lesser General Public
|
|
// License as published by the Free Software Foundation; either
|
|
// version 2.1 of the License.
|
|
//
|
|
// This library is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
// Lesser General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Lesser General Public
|
|
// License along with this library; if not, write to the Free Software
|
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
//
|
|
// See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
|
|
//
|
|
//
|
|
//
|
|
// File : GEOM_Sketcher.cxx
|
|
// Author : Nicolas REJNERI
|
|
// Module : GEOM
|
|
// $Header$
|
|
|
|
using namespace std;
|
|
#include "GEOM_Sketcher.h"
|
|
#include "utilities.h"
|
|
|
|
#include <qstring.h>
|
|
|
|
#include <Geom_Axis1Placement.hxx>
|
|
#include <Geom_Circle.hxx>
|
|
#include <Geom_Line.hxx>
|
|
#include <Geom_CartesianPoint.hxx>
|
|
#include <BRep_Tool.hxx>
|
|
#include <BRepBuilderAPI_MakeEdge2d.hxx>
|
|
#include <BRepBuilderAPI_MakeEdge.hxx>
|
|
#include <BRepBuilderAPI_MakeVertex.hxx>
|
|
#include <gp_Lin2d.hxx>
|
|
#include <gp_Pln.hxx>
|
|
#include <gp_Lin.hxx>
|
|
#include <gp_Dir.hxx>
|
|
#include <gp_Circ2d.hxx>
|
|
#include <gp_Vec2d.hxx>
|
|
#include <IntAna_IntConicQuad.hxx>
|
|
#include <BRepLib.hxx>
|
|
#include <TopExp.hxx>
|
|
#include <ProjLib.hxx>
|
|
#include <Precision.hxx>
|
|
#include <ElSLib.hxx>
|
|
#include <BRepTools_WireExplorer.hxx>
|
|
#include <GccAna_Pnt2dBisec.hxx>
|
|
#include <GeomAPI.hxx>
|
|
#include <Geom2dAPI_ProjectPointOnCurve.hxx>
|
|
#include <Geom2d_TrimmedCurve.hxx>
|
|
#include <Geom2d_Circle.hxx>
|
|
#include <gce_MakeCirc2d.hxx>
|
|
#include <GccAna_Circ2d2TanRad.hxx>
|
|
#include <GccAna_Circ2d2TanOn.hxx>
|
|
#include <GccEnt.hxx>
|
|
#include <GccEnt_QualifiedLin.hxx>
|
|
#include <GccEnt_QualifiedCirc.hxx>
|
|
#include <GccAna_Lin2dTanPer.hxx>
|
|
#include <GccAna_Lin2dTanObl.hxx>
|
|
#include <gce_MakeLin2d.hxx>
|
|
#include <GCE2d_MakeArcOfCircle.hxx>
|
|
#include <Precision.hxx>
|
|
#include <ElCLib.hxx>
|
|
#include <AIS_Point.hxx>
|
|
#include <TColgp_HArray1OfPnt2d.hxx>
|
|
#include <Geom2dAPI_Interpolate.hxx>
|
|
#include <TColgp_Array1OfVec2d.hxx>
|
|
#include <TColStd_HArray1OfBoolean.hxx>
|
|
#include <GeomAPI_ProjectPointOnCurve.hxx>
|
|
#include <DsgPrs_ArrowSide.hxx>
|
|
#include <BRepBuilderAPI_Transform.hxx>
|
|
|
|
#include <AIS_Drawer.hxx>
|
|
#include <Prs3d_TextAspect.hxx>
|
|
#include <Prs3d_LineAspect.hxx>
|
|
#include <Graphic3d_NameOfFont.hxx>
|
|
|
|
#include <TopoDS_Wire.hxx>
|
|
|
|
/*!
|
|
\class GEOM_Sketcher GEOM_Sketcher.h
|
|
\brief ...
|
|
*/
|
|
|
|
Standard_Real resol = 1.0;
|
|
|
|
/*!
|
|
Constructor.
|
|
*/
|
|
Sketch::Sketch()
|
|
{
|
|
|
|
}
|
|
|
|
/*!
|
|
Destructor.
|
|
*/
|
|
Sketch::~Sketch()
|
|
{
|
|
|
|
}
|
|
|
|
|
|
/*!
|
|
Constructor.
|
|
|
|
\param V3d_Viewer
|
|
*/
|
|
Sketch::Sketch(const Handle(V3d_Viewer)& aViewer) :
|
|
myInteractiveContext(new AIS_InteractiveContext(aViewer)),
|
|
myAxisColor(Quantity_Color(Quantity_NOC_YELLOW)),
|
|
myCurrentColor(Quantity_Color(Quantity_NOC_GREEN)),
|
|
myWireColor(Quantity_Color(Quantity_NOC_RED))
|
|
{
|
|
Init();
|
|
}
|
|
|
|
/*!
|
|
Constructor.
|
|
|
|
\param V3d_Viewer
|
|
\param Quantity_Color
|
|
\param Quantity_Color
|
|
\param Quantity_Color
|
|
*/
|
|
Sketch::Sketch(const Handle(V3d_Viewer)& aViewer,
|
|
const Quantity_Color& anAxisColor,
|
|
const Quantity_Color& aCurrentColor,
|
|
const Quantity_Color& aWireColor):
|
|
myInteractiveContext(new AIS_InteractiveContext(aViewer)),
|
|
myAxisColor(anAxisColor),
|
|
myCurrentColor(aCurrentColor),
|
|
myWireColor(aWireColor)
|
|
{
|
|
Init();
|
|
}
|
|
|
|
/*!
|
|
Build the current edge in a graphic mode.
|
|
The first signature with view coordinates is used to connect to the move event from the user interface.
|
|
The second signature is used when the current point is known by 2d real coordinates.
|
|
|
|
\param Xp
|
|
\param Yp
|
|
\param V3d_View
|
|
*/
|
|
void Sketch::MakeCurrentEdge(const Standard_Integer Xp ,
|
|
const Standard_Integer Yp ,
|
|
const Handle(V3d_View)& aView )
|
|
{
|
|
/* 3d coordinates of the picked point */
|
|
Standard_Real Xv,Yv,Zv;
|
|
aView->Convert(Xp,Yp,Xv,Yv,Zv);
|
|
/* computation of real 2d coordinates in plane of sketch */
|
|
Standard_Real Vx,Vy,Vz;
|
|
aView->Proj(Vx,Vy,Vz);
|
|
gp_Dir D(Vx,Vy,Vz);
|
|
gp_Pnt P(Xv,Yv,Zv);
|
|
gp_Lin L(P,D);
|
|
Standard_Real X,Y;
|
|
gp_Pnt Sol;
|
|
IntAna_IntConicQuad Int(L,myPlane->Pln(),Precision::Angular());
|
|
if (Int.IsDone()) {
|
|
if (!Int.IsParallel()) {
|
|
if (Int.NbPoints() > 0 ) {
|
|
Sol = Int.Point(1);
|
|
ElSLib::Parameters(myPlane->Pln(),Sol,X,Y);
|
|
}
|
|
}
|
|
}
|
|
MakeCurrentEdge(X,Y);
|
|
}
|
|
|
|
/*!
|
|
Build the current edge in a graphic mode.
|
|
The first signature with view coordinates is used to connect to the move event from the user interface.
|
|
The second signature is used when the current point is known by 2d real coordinates.
|
|
|
|
\param X
|
|
\param Y
|
|
*/
|
|
void Sketch::MakeCurrentEdge(const Standard_Real X, const Standard_Real Y)
|
|
{
|
|
/* Create the current edge depending on the active mode */
|
|
switch (myCurrentStatus) {
|
|
case BEGIN_SKETCH:
|
|
myCurrentEdge = BRepBuilderAPI_MakeVertex(ElCLib::To3d(myPlane->Pln().Position().Ax2(),gp_Pnt2d(X,Y)));
|
|
break;
|
|
case SEGMENT:
|
|
MakeCurrentSegment(X,Y);
|
|
break;
|
|
case ARC_CHORD:
|
|
MakeCurrentSegment(X,Y);
|
|
break;
|
|
case ARC_CHORD_END:
|
|
MakeCurrentArc(X,Y);
|
|
break;
|
|
}
|
|
DisplayCurrentEdge();
|
|
}
|
|
|
|
/*!
|
|
Build the current edge in a graphic mode.
|
|
Function to connect to the input event from the user interface.
|
|
*/
|
|
void Sketch::ValidateEdge()
|
|
{
|
|
gp_Pnt pt;
|
|
gp_Pnt2d pt2d;
|
|
switch (myCurrentStatus) {
|
|
case BEGIN_SKETCH:
|
|
{
|
|
myFirstPointSketch = TopoDS::Vertex(myCurrentEdge);
|
|
myPresentableWire = new AIS_Shape(myFirstPointSketch);
|
|
myPresentableWire->SetColor(myWireColor.Name());
|
|
myInteractiveContext->Display(myPresentableWire);
|
|
pt = BRep_Tool::Pnt(myFirstPointSketch);
|
|
pt2d = ProjLib::Project(myPlane->Pln(),pt);
|
|
myLastX = pt2d.X();
|
|
myLastY = pt2d.Y();
|
|
myCurrentStatus = SEGMENT;
|
|
break;
|
|
}
|
|
case SEGMENT:
|
|
{
|
|
Standard_Real first,last;
|
|
TopLoc_Location L;
|
|
Handle(Geom2d_Curve) C = BRep_Tool::CurveOnSurface(TopoDS::Edge(myCurrentEdge),myPlane,L,first,last);
|
|
myCurrentEdge = BRepBuilderAPI_MakeEdge2d(Handle(Geom2d_Line)::DownCast(C)->Lin2d(),0.,myLengthDimension->Value());
|
|
if (myTransitionStatus == ANGLE ||
|
|
myTransitionStatus == LENGTH_FIXED ||
|
|
myTransitionStatus == X_FIXED ||
|
|
myTransitionStatus == Y_FIXED)
|
|
myTransitionStatus = NOCONSTRAINT;
|
|
AddEdgeToWire();
|
|
break;
|
|
}
|
|
case ARC_CHORD:
|
|
{
|
|
myInteractiveContext->CloseLocalContext();
|
|
myInteractiveContext->OpenLocalContext();
|
|
gp_Pnt2d p1 (myLastX,myLastY);
|
|
pt = BRep_Tool::Pnt(TopExp::LastVertex(TopoDS::Edge(myCurrentEdge)));
|
|
gp_Pnt2d p2 = ProjLib::Project(myPlane->Pln(),pt);
|
|
GccAna_Pnt2dBisec ComputeMediatrice(p1,p2);
|
|
if (ComputeMediatrice.HasSolution()) {
|
|
myMediatrice = new Geom2d_Line(ComputeMediatrice.ThisSolution());
|
|
Handle(Geom_Curve) aMediatrice3d = GeomAPI::To3d(myMediatrice,myPlane->Pln());
|
|
myPresentableMediatrice = new AIS_Axis(Handle(Geom_Line)::DownCast(aMediatrice3d));
|
|
myInteractiveContext->Display(myPresentableMediatrice);
|
|
}
|
|
TopoDS_Edge e = BRepBuilderAPI_MakeEdge2d(gce_MakeCirc2d(gp_Pnt2d(0.,0),1.));
|
|
BRepLib::BuildCurve3d(e);
|
|
myLengthDimension->SetText(TCollection_ExtendedString());
|
|
myInteractiveContext->Redisplay(myLengthDimension,Standard_False);
|
|
if (myEdgesNumber == 0)
|
|
myPreviousEdge = TopoDS::Edge(myCurrentEdge);
|
|
pt2d = ProjLib::Project(myPlane->Pln(),pt);
|
|
myLastX = pt2d.X();
|
|
myLastY = pt2d.Y();
|
|
myTransitionStatus = NOCONSTRAINT;
|
|
myCurrentStatus = ARC_CHORD_END;
|
|
break;
|
|
}
|
|
case ARC_CHORD_END:
|
|
myCurrentStatus = ARC_CHORD;
|
|
AddEdgeToWire();
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*!
|
|
Add edge to current wire on an edge validation .
|
|
*/
|
|
void Sketch::AddEdgeToWire()
|
|
{
|
|
myPreviousEdge = TopoDS::Edge(myCurrentEdge);
|
|
BRepLib::BuildCurve3d(myPreviousEdge);
|
|
myCurrentWire.Add(TopoDS::Edge(myPreviousEdge));
|
|
myEdgesNumber++;
|
|
myPresentableWire->Set( myCurrentWire.Wire() );
|
|
myInteractiveContext->Redisplay(myPresentableWire);
|
|
myConstructionMode.Append(myCurrentStatus);
|
|
myConstraintMode.Append(myTransitionStatus);
|
|
myInteractiveContext->CloseLocalContext();
|
|
gp_Pnt pt;
|
|
if (myPreviousEdge.Orientation() == TopAbs_FORWARD )
|
|
pt = BRep_Tool::Pnt(TopExp::LastVertex(TopoDS::Edge(myPreviousEdge)));
|
|
else
|
|
pt = BRep_Tool::Pnt(TopExp::FirstVertex(TopoDS::Edge(myPreviousEdge)));
|
|
gp_Pnt2d pt2d= ProjLib::Project(myPlane->Pln(),pt);
|
|
myLastX = pt2d.X();
|
|
myLastY = pt2d.Y();
|
|
}
|
|
|
|
/*!
|
|
Set the numeric dimension for the current edge and validate creation.
|
|
|
|
\param aValue
|
|
\return Standard_Boolean
|
|
*/
|
|
Standard_Boolean Sketch::SetDimension(Standard_Real& aValue)
|
|
{
|
|
fitInResol(aValue);
|
|
if (myCurrentStatus == SEGMENT ||
|
|
myCurrentStatus == ARC_CHORD){
|
|
Standard_Real first,last;
|
|
TopLoc_Location L;
|
|
Handle(Geom2d_Curve) C =
|
|
BRep_Tool::CurveOnSurface(TopoDS::Edge(myCurrentEdge),myPlane,L,first,last);
|
|
myCurrentEdge =
|
|
BRepBuilderAPI_MakeEdge2d(Handle(Geom2d_Line)::DownCast(C)->Lin2d(),0.,aValue);
|
|
DisplayCurrentEdge();
|
|
if (myTransitionStatus == NOCONSTRAINT) {
|
|
mySegmentLength = aValue;
|
|
myTransitionStatus = LENGTH_FIXED;
|
|
}
|
|
else
|
|
ValidateEdge();
|
|
return Standard_True;
|
|
}
|
|
|
|
else if( myCurrentStatus == ARC_CHORD_END){
|
|
if (myTransitionStatus == TANGENT) return Standard_False;
|
|
gp_Pnt2d p;
|
|
if (myEdgesNumber > 0) {
|
|
if (myPreviousEdge.Orientation() == TopAbs_FORWARD)
|
|
p = ProjLib::Project(myPlane->Pln(),BRep_Tool::Pnt(TopExp::LastVertex(myPreviousEdge)));
|
|
else
|
|
p = ProjLib::Project(myPlane->Pln(),BRep_Tool::Pnt(TopExp::FirstVertex(myPreviousEdge)));
|
|
}
|
|
else
|
|
p = ProjLib::Project(myPlane->Pln(),BRep_Tool::Pnt(myFirstPointSketch));
|
|
GccAna_Circ2d2TanRad aSol(p, gp_Pnt2d(myLastX,myLastY),aValue,Precision::Confusion());
|
|
Standard_Real dist = RealLast();
|
|
if (aSol.NbSolutions() > 0) {
|
|
gp_Circ2d CirSol;
|
|
gp_Pnt2d pc = ProjLib::Project(myPlane->Pln(),BRep_Tool::Pnt(TopoDS::Vertex(myCenterCircle->Shape())));
|
|
for (Standard_Integer i =1; i<= aSol.NbSolutions(); i++) {
|
|
if (pc.Distance(aSol.ThisSolution(i).Location()) < dist)
|
|
CirSol = aSol.ThisSolution(i);
|
|
}
|
|
if (myCurrentEdge.Orientation() == TopAbs_FORWARD)
|
|
myCurrentEdge = BRepBuilderAPI_MakeEdge2d(aSol.ThisSolution(1),p,gp_Pnt2d(myLastX,myLastY));
|
|
else {
|
|
myCurrentEdge = BRepBuilderAPI_MakeEdge2d(aSol.ThisSolution(1),gp_Pnt2d(myLastX,myLastY),p);
|
|
myCurrentEdge.Reverse();
|
|
}
|
|
DisplayCurrentEdge();
|
|
ValidateEdge();
|
|
return Standard_True;
|
|
}
|
|
}
|
|
|
|
return Standard_False;
|
|
}
|
|
|
|
/*!
|
|
Set the numeric dimension for the current edge and validate creation.
|
|
|
|
\param deltaX
|
|
\param deltaY
|
|
*/
|
|
void Sketch::SetDimension(Standard_Real& deltaX, Standard_Real& deltaY)
|
|
{
|
|
fitInResol(deltaX);
|
|
fitInResol(deltaY);
|
|
Standard_Real X = myLastX + deltaX;
|
|
Standard_Real Y = myLastY + deltaY;
|
|
MakeCurrentEdge(X,Y);
|
|
ValidateEdge();
|
|
}
|
|
|
|
/*!
|
|
Set the numeric value of the X coordinate of current point giving a deltaX relative to previous point.
|
|
|
|
\param deltaX
|
|
*/
|
|
void Sketch::SetXDimension(Standard_Real& deltaX)
|
|
{
|
|
fitInResol(deltaX);
|
|
Standard_Real X = myLastX + deltaX;
|
|
Standard_Real Y = myLastY;
|
|
if ( deltaX == 0. )
|
|
Y = Y + 100.0 * Precision::Confusion();
|
|
|
|
if (myTransitionStatus == NOCONSTRAINT) {
|
|
MakeCurrentEdge(X,Y);
|
|
myTransitionStatus = X_FIXED;
|
|
mySegmentX = X;
|
|
}
|
|
else if (myTransitionStatus == Y_FIXED) {
|
|
myTransitionStatus = NOCONSTRAINT;
|
|
MakeCurrentEdge(X,mySegmentY);
|
|
ValidateEdge();
|
|
}
|
|
else if (myTransitionStatus == ANGLE) {
|
|
myTransitionStatus = NOCONSTRAINT;
|
|
Standard_Real angle;
|
|
if (0 <= mySegmentAngle && mySegmentAngle<= PI )
|
|
angle = PI - mySegmentAngle;
|
|
else
|
|
angle = mySegmentAngle - PI;
|
|
Y = X*Tan(angle);
|
|
MakeCurrentEdge(X,Y);
|
|
ValidateEdge();
|
|
}
|
|
else
|
|
myTransitionStatus = NOCONSTRAINT;
|
|
}
|
|
|
|
/*!
|
|
Set the numeric value of the Y coordinate of current point giving a deltaY relative to previous point.
|
|
|
|
\param deltaY
|
|
*/
|
|
void Sketch::SetYDimension(Standard_Real& deltaY)
|
|
{
|
|
fitInResol(deltaY);
|
|
Standard_Real X = myLastX;
|
|
Standard_Real Y = myLastY + deltaY;
|
|
|
|
if ( deltaY == 0. )
|
|
X = X + 100.0 * Precision::Confusion();
|
|
|
|
if (myTransitionStatus == NOCONSTRAINT) {
|
|
MakeCurrentEdge(X,Y);
|
|
myTransitionStatus = Y_FIXED;
|
|
mySegmentY = Y;
|
|
}
|
|
else if (myTransitionStatus == X_FIXED) {
|
|
myTransitionStatus = NOCONSTRAINT;
|
|
MakeCurrentEdge(mySegmentX,Y);
|
|
ValidateEdge();
|
|
}
|
|
else if (myTransitionStatus == ANGLE) {
|
|
myTransitionStatus = NOCONSTRAINT;
|
|
Standard_Real angle;
|
|
if (0 <= mySegmentAngle && mySegmentAngle<= PI )
|
|
angle = PI - mySegmentAngle;
|
|
else
|
|
angle = mySegmentAngle - PI;
|
|
X = Y/Tan(angle);
|
|
MakeCurrentEdge(X,Y);
|
|
ValidateEdge();
|
|
}
|
|
else
|
|
myTransitionStatus = NOCONSTRAINT;
|
|
}
|
|
|
|
/*!
|
|
Set the numeric value of angle between 2 segments.
|
|
|
|
\param aValue
|
|
*/
|
|
void Sketch::SetSegmentAngle(Standard_Real& aValue)
|
|
{
|
|
if (myEdgesNumber > 0) {
|
|
Standard_Real First,Last;
|
|
TopLoc_Location L;
|
|
Standard_Real angle;
|
|
if (0 <= aValue && aValue<= PI )
|
|
angle = PI - aValue;
|
|
else
|
|
angle = aValue - PI;
|
|
Handle (Geom2d_Curve) PreviousCurve = BRep_Tool::CurveOnSurface(myPreviousEdge,myPlane,L,First,Last);
|
|
if (PreviousCurve->IsKind(STANDARD_TYPE(Geom2d_Line))) {
|
|
Handle (Geom2d_Curve) PreviousCurve = BRep_Tool::CurveOnSurface(TopoDS::Edge(myPreviousEdge),myPlane,L,First,Last);
|
|
|
|
GccAna_Lin2dTanObl aSol(gp_Pnt2d(myLastX,myLastY),Handle(Geom2d_Line)::DownCast(PreviousCurve)->Lin2d(),angle);
|
|
myCurrentEdge = BRepBuilderAPI_MakeEdge2d(aSol.ThisSolution(1),0.,myLengthDimension->Value());
|
|
}
|
|
if (myTransitionStatus == LENGTH_FIXED) {
|
|
ValidateEdge();
|
|
}
|
|
else if (myTransitionStatus == X_FIXED) {
|
|
Standard_Real length = mySegmentX/Cos(angle);
|
|
SetDimension(length);
|
|
ValidateEdge();
|
|
}
|
|
else if (myTransitionStatus == Y_FIXED) {
|
|
Standard_Real length = mySegmentY/Sin(angle);
|
|
SetDimension(length);
|
|
ValidateEdge();
|
|
}
|
|
else {
|
|
mySegmentAngle = aValue;
|
|
myTransitionStatus = ANGLE;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*!
|
|
Get the angle value between 2 segments.
|
|
|
|
\return Standard_Real
|
|
*/
|
|
Standard_Real Sketch::GetSegmentAngle()
|
|
{
|
|
return mySegmentAngle;
|
|
}
|
|
|
|
/*!
|
|
Close automatically an open sketch.
|
|
|
|
\return TopoDS_Wire. Return null shape if not possible.
|
|
*/
|
|
TopoDS_Wire Sketch::Close()
|
|
{
|
|
myCurrentStatus = END_SKETCH;
|
|
myInteractiveContext->CloseAllContexts();
|
|
myInteractiveContext->EraseAll(Standard_False);
|
|
if (myEdgesNumber >= 2) {
|
|
BRepTools_WireExplorer Ex(myCurrentWire.Wire());
|
|
TopoDS_Vertex V1;
|
|
if (myPreviousEdge.Orientation() == TopAbs_FORWARD)
|
|
V1 = TopExp::LastVertex(myPreviousEdge);
|
|
else
|
|
V1 = TopExp::FirstVertex(myPreviousEdge);
|
|
myCurrentWire.Add(BRepBuilderAPI_MakeEdge(V1,myFirstPointSketch).Edge());
|
|
myEdgesNumber++;
|
|
return myCurrentWire.Wire();
|
|
}
|
|
else
|
|
return TopoDS_Wire();
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
Clear sketch presentation.
|
|
*/
|
|
void Sketch::Clear()
|
|
{
|
|
myCurrentStatus = END_SKETCH;
|
|
myInteractiveContext->CloseAllContexts();
|
|
myInteractiveContext->EraseAll(Standard_False);
|
|
}
|
|
|
|
/*!
|
|
Terminate sketch without closing.
|
|
|
|
\return TopoDS_Wire. Return null shape if not possible.
|
|
*/
|
|
TopoDS_Wire Sketch::End()
|
|
{
|
|
myCurrentStatus = END_SKETCH;
|
|
myInteractiveContext->CloseAllContexts();
|
|
myInteractiveContext->EraseAll(Standard_False);
|
|
if (myCurrentWire.IsDone()) {
|
|
return myCurrentWire.Wire();
|
|
}
|
|
else
|
|
return TopoDS_Wire();
|
|
}
|
|
|
|
|
|
/*!
|
|
Delete current edge.
|
|
*/
|
|
Standard_Boolean Sketch::Delete()
|
|
{
|
|
myInteractiveContext->Erase(myAngleDimension,Standard_True,Standard_False);
|
|
myInteractiveContext->Erase(myLengthDimension,Standard_True,Standard_False);
|
|
myInteractiveContext->Erase(myRadiusDimension,Standard_True,Standard_False);
|
|
myInteractiveContext->Erase(myCenterCircle,Standard_True,Standard_False);
|
|
myInteractiveContext->Erase(myXDimension,Standard_True,Standard_False);
|
|
myInteractiveContext->Erase(myYDimension,Standard_True,Standard_False);
|
|
|
|
if (myCurrentStatus == BEGIN_SKETCH) {
|
|
myCurrentStatus = END_SKETCH;
|
|
myInteractiveContext->CloseAllContexts();
|
|
myInteractiveContext->EraseAll(Standard_False);
|
|
return true;
|
|
}
|
|
else if(myCurrentStatus == SEGMENT ||
|
|
myCurrentStatus == ARC_CHORD ) {
|
|
RemoveLastEdge();
|
|
}
|
|
else if(myCurrentStatus == ARC_CHORD_END) {
|
|
myCurrentStatus = ARC_CHORD;
|
|
myInteractiveContext->CloseAllContexts();
|
|
}
|
|
gp_Pnt pt;
|
|
if (myEdgesNumber == 0) {
|
|
//myInteractiveContext->EraseAll(Standard_False);
|
|
ChangeMode(BEGIN_SKETCH); // DCQ
|
|
pt = BRep_Tool::Pnt(myFirstPointSketch);
|
|
}
|
|
else {
|
|
if (myPreviousEdge.Orientation() == TopAbs_FORWARD )
|
|
pt = BRep_Tool::Pnt(TopExp::LastVertex(TopoDS::Edge(myPreviousEdge)));
|
|
else
|
|
pt = BRep_Tool::Pnt(TopExp::FirstVertex(TopoDS::Edge(myPreviousEdge)));
|
|
}
|
|
gp_Pnt2d pt2d= ProjLib::Project(myPlane->Pln(),pt);
|
|
myLastX = pt2d.X();
|
|
myLastY = pt2d.Y();
|
|
|
|
return false;
|
|
}
|
|
|
|
/*!
|
|
Set a specific plane for sketch.
|
|
|
|
\param GeomyPlane
|
|
*/
|
|
void Sketch::SetPlane(const Handle(Geom_Plane)& aPlane)
|
|
{
|
|
myPlane = aPlane;
|
|
}
|
|
|
|
/*!
|
|
Set display parameters.
|
|
|
|
\param aColor
|
|
*/
|
|
void Sketch::SetWireColor(const Quantity_Color& aColor)
|
|
{
|
|
myWireColor = aColor;
|
|
}
|
|
|
|
/*!
|
|
Set display parameters.
|
|
|
|
\param aColor
|
|
*/
|
|
void Sketch::SetCurrentColor(const Quantity_Color& aColor)
|
|
{
|
|
myCurrentColor = aColor;
|
|
}
|
|
|
|
/*!
|
|
Set display parameters.
|
|
|
|
\param aColor
|
|
*/
|
|
void Sketch::SetAxisColor(const Quantity_Color& aColor)
|
|
{
|
|
myAxisColor = aColor;
|
|
}
|
|
|
|
|
|
/*!
|
|
Change mode of construction line.
|
|
|
|
\param aMode : SEGMENT, ARC_CHORD.
|
|
*/
|
|
void Sketch::ChangeMode(const SketchStatus aMode)
|
|
{
|
|
gp_Pnt2d p;
|
|
if (myEdgesNumber > 0) {
|
|
if (myPreviousEdge.Orientation() == TopAbs_FORWARD)
|
|
p = ProjLib::Project(myPlane->Pln(),BRep_Tool::Pnt(TopExp::LastVertex(myPreviousEdge)));
|
|
else
|
|
p = ProjLib::Project(myPlane->Pln(),BRep_Tool::Pnt(TopExp::FirstVertex(myPreviousEdge)));
|
|
myLastX = p.X();
|
|
myLastY = p.Y();
|
|
myInteractiveContext->CloseLocalContext(myInteractiveContext->IndexOfCurrentLocal());
|
|
}
|
|
if (!myCurrentStatus == BEGIN_SKETCH)
|
|
myCurrentStatus = aMode; /* change the mode only when the sketch is not in state BEGIN_SKETCH, i.d. fist point has been fixed */
|
|
|
|
}
|
|
|
|
/*!
|
|
Set transition constraint between consecutive edges.
|
|
|
|
\param aStatus : NOCONSTRAINT, TANGENT, PERPENDICULAR, ANGLE, LENGTH_FIXED, X_FIXED, Y_FIXED.
|
|
*/
|
|
void Sketch::SetTransitionStatus(const TransitionStatus aStatus)
|
|
{
|
|
myTransitionStatus = aStatus;
|
|
}
|
|
|
|
/*!
|
|
Set or unset the display of dimensions.
|
|
|
|
\param atype
|
|
\param OnOff
|
|
*/
|
|
void Sketch::SetParameterVisibility(const TypeOfParameter atype, const Standard_Boolean OnOff)
|
|
{
|
|
switch (atype) {
|
|
case ANGLE_PARAMETER:
|
|
myIsAngleDimensionVisible = OnOff;
|
|
if (!myIsAngleDimensionVisible && !myAngleDimension.IsNull())
|
|
myInteractiveContext->Erase(myAngleDimension,Standard_True,Standard_False);
|
|
//else DCQ
|
|
// DisplayCurrentEdge();
|
|
break;
|
|
case LENGTH_PARAMETER:
|
|
myIsLengthDimensionVisible = OnOff;
|
|
if (!myIsLengthDimensionVisible&& !myLengthDimension.IsNull())
|
|
myInteractiveContext->Erase(myLengthDimension,Standard_True,Standard_False);
|
|
//else DCQ
|
|
// DisplayCurrentEdge();
|
|
break;
|
|
case RADIUS_PARAMETER:
|
|
myIsRadiusDimensionVisible = OnOff;
|
|
if (!myIsRadiusDimensionVisible&& !myRadiusDimension.IsNull()){
|
|
myInteractiveContext->Erase(myRadiusDimension,Standard_True,Standard_False);
|
|
myInteractiveContext->Erase(myCenterCircle,Standard_True,Standard_False);
|
|
}
|
|
//else DCQ
|
|
// DisplayCurrentEdge();
|
|
break;
|
|
case XVALUE_PARAMETER:
|
|
myIsXDimensionVisible = OnOff;
|
|
if (!myIsXDimensionVisible&& !myXDimension.IsNull())
|
|
myInteractiveContext->Erase(myXDimension,Standard_True,Standard_False);
|
|
break;
|
|
case YVALUE_PARAMETER:
|
|
myIsYDimensionVisible = OnOff;
|
|
if (!myIsYDimensionVisible&& !myYDimension.IsNull())
|
|
myInteractiveContext->Erase(myYDimension,Standard_True,Standard_False);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*!
|
|
Hilight parameters.
|
|
|
|
\param atype
|
|
\param acolor
|
|
*/
|
|
void Sketch::HiligthWithColor(const TypeOfParameter atype, const Quantity_NameOfColor acolor)
|
|
{
|
|
switch (atype) {
|
|
case ANGLE_PARAMETER:
|
|
myInteractiveContext->HilightWithColor(myAngleDimension, acolor);
|
|
break;
|
|
case LENGTH_PARAMETER:
|
|
myInteractiveContext->HilightWithColor(myLengthDimension, acolor);
|
|
break;
|
|
case RADIUS_PARAMETER:
|
|
myInteractiveContext->HilightWithColor(myRadiusDimension, acolor);
|
|
break;
|
|
case XVALUE_PARAMETER:
|
|
myInteractiveContext->HilightWithColor(myXDimension, acolor);
|
|
break;
|
|
case YVALUE_PARAMETER:
|
|
myInteractiveContext->HilightWithColor(myYDimension, acolor);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/*!
|
|
Unhilight parameters.
|
|
|
|
\param atype
|
|
*/
|
|
void Sketch::Unhiligth(const TypeOfParameter atype)
|
|
{
|
|
switch (atype) {
|
|
case ANGLE_PARAMETER:
|
|
myInteractiveContext->Unhilight(myAngleDimension);
|
|
break;
|
|
case LENGTH_PARAMETER:
|
|
myInteractiveContext->Unhilight(myLengthDimension);
|
|
break;
|
|
case RADIUS_PARAMETER:
|
|
myInteractiveContext->Unhilight(myRadiusDimension);
|
|
break;
|
|
case XVALUE_PARAMETER:
|
|
myInteractiveContext->Unhilight(myXDimension);
|
|
break;
|
|
case YVALUE_PARAMETER:
|
|
myInteractiveContext->Unhilight(myYDimension);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*!
|
|
Check if the edition of a type of parameter is relevant depending on sketch current status.
|
|
|
|
\param atype
|
|
\return Standard_Boolean
|
|
*/
|
|
Standard_Boolean Sketch::IsValidCurrentParameter(const TypeOfParameter atype)
|
|
{
|
|
switch (atype) {
|
|
case ANGLE_PARAMETER:
|
|
if (myCurrentStatus != SEGMENT && myCurrentStatus != ARC_CHORD)
|
|
return Standard_False;
|
|
else if (myTransitionStatus == TANGENT || myTransitionStatus == PERPENDICULAR)
|
|
return Standard_False;
|
|
else if (myEdgesNumber < 1)
|
|
return Standard_False;
|
|
else {
|
|
TopLoc_Location L;
|
|
Standard_Real First,Last;
|
|
Handle (Geom2d_Curve) PreviousCurve = BRep_Tool::CurveOnSurface(myPreviousEdge,myPlane,L,First,Last);
|
|
if (!PreviousCurve->IsKind(STANDARD_TYPE(Geom2d_Line)))
|
|
return Standard_False;
|
|
}
|
|
break;
|
|
case LENGTH_PARAMETER:
|
|
if (myCurrentStatus != SEGMENT &&
|
|
myCurrentStatus != ARC_CHORD /*&&
|
|
myCurrentStatus != CURVE_POINTS*/
|
|
)
|
|
return Standard_False;
|
|
else if (myTransitionStatus == LENGTH_FIXED)
|
|
return Standard_False;
|
|
break;
|
|
case RADIUS_PARAMETER:
|
|
if (myCurrentStatus != ARC_CHORD_END)
|
|
return Standard_False;
|
|
break;
|
|
case XVALUE_PARAMETER:
|
|
if (myCurrentStatus != SEGMENT &&
|
|
myCurrentStatus != ARC_CHORD /*&&
|
|
myCurrentStatus != CURVE_POINTS*/
|
|
)
|
|
return Standard_False;
|
|
else if (myTransitionStatus == X_FIXED)
|
|
return Standard_False;
|
|
break;
|
|
case YVALUE_PARAMETER:
|
|
if (myCurrentStatus != SEGMENT &&
|
|
myCurrentStatus != ARC_CHORD /*&&
|
|
myCurrentStatus != CURVE_POINTS*/
|
|
)
|
|
return Standard_False;
|
|
else if (myTransitionStatus == Y_FIXED)
|
|
return Standard_False;
|
|
break;
|
|
}
|
|
return Standard_True;
|
|
}
|
|
|
|
/*!
|
|
Set a parameter value.
|
|
|
|
\param atype
|
|
\param aValue
|
|
*/
|
|
void Sketch::SetParameterValue(const TypeOfParameter atype, Standard_Real aValue)
|
|
{
|
|
switch (atype) {
|
|
case ANGLE_PARAMETER:
|
|
SetSegmentAngle(aValue);
|
|
break;
|
|
case LENGTH_PARAMETER:
|
|
SetDimension(aValue);
|
|
break;
|
|
case RADIUS_PARAMETER:
|
|
SetDimension(aValue);
|
|
break;
|
|
case XVALUE_PARAMETER:
|
|
SetXDimension(aValue);
|
|
break;
|
|
case YVALUE_PARAMETER:
|
|
SetYDimension(aValue);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*!
|
|
Initialisation of sketch parameters or options.
|
|
*/
|
|
void Sketch::Init()
|
|
{
|
|
myPlane = new Geom_Plane (0.,0.,1.,0.);
|
|
CreateConstraints();
|
|
BRepLib::Plane(myPlane);
|
|
myEdgesNumber = 0;
|
|
myCurrentStatus = BEGIN_SKETCH;
|
|
/* In order to update the visulisation of current objects by using Redisplay method from InteractiveContext */
|
|
myCurrentEdge = BRepBuilderAPI_MakeVertex(gp_Pnt(0.,0.,0.));
|
|
myPresentableEdge = new AIS_Shape(myCurrentEdge);
|
|
myPresentableEdge->SetColor(myCurrentColor.Name());
|
|
myInteractiveContext->Display(myPresentableEdge);
|
|
myTransitionStatus = NOCONSTRAINT;
|
|
/* Init for display objects */
|
|
TopoDS_Vertex V1 = BRepBuilderAPI_MakeVertex(gp_Pnt(0.,0.,0.));
|
|
TopoDS_Vertex V2 = BRepBuilderAPI_MakeVertex(gp_Pnt(10.,0.,0.));
|
|
myLengthDimension = new AIS_LengthDimension (V1,V2,myPlane,0.,TCollection_ExtendedString());
|
|
myXDimension = new AIS_LengthDimension (V1,V2,myPlane,0.,TCollection_ExtendedString(),gp_Pnt(),DsgPrs_AS_NONE,
|
|
AIS_TOD_Horizontal);
|
|
myYDimension = new AIS_LengthDimension (V1,V2,myPlane,0.,TCollection_ExtendedString(),gp_Pnt(),DsgPrs_AS_NONE,
|
|
AIS_TOD_Vertical);
|
|
myRadiusDimension = new AIS_LengthDimension (V1,V2,myPlane,0.,TCollection_ExtendedString());
|
|
myCenterCircle = new AIS_Shape(V1);
|
|
myIsLengthDimensionVisible = Standard_False;
|
|
myIsXDimensionVisible = Standard_False;
|
|
myIsYDimensionVisible = Standard_False;
|
|
myIsRadiusDimensionVisible = Standard_False;
|
|
}
|
|
|
|
/*!
|
|
Build the current segment.
|
|
|
|
\param X
|
|
\param Y
|
|
*/
|
|
void Sketch::MakeCurrentSegment(Standard_Real X, Standard_Real Y)
|
|
{
|
|
if (myTransitionStatus == NOCONSTRAINT)
|
|
myCurrentEdge = BRepBuilderAPI_MakeEdge2d(gp_Pnt2d(myLastX,myLastY), gp_Pnt2d(X,Y));
|
|
else if (myTransitionStatus == X_FIXED)
|
|
myCurrentEdge = BRepBuilderAPI_MakeEdge2d(gp_Pnt2d(myLastX,myLastY),gp_Pnt2d(mySegmentX,Y));
|
|
else if (myTransitionStatus == Y_FIXED)
|
|
myCurrentEdge = BRepBuilderAPI_MakeEdge2d(gp_Pnt2d(myLastX,myLastY),gp_Pnt2d(X,mySegmentY));
|
|
else if (myTransitionStatus == TANGENT && myEdgesNumber > 0) {
|
|
Standard_Real first,last;
|
|
TopLoc_Location L;
|
|
Handle(Geom2d_Curve) C = BRep_Tool::CurveOnSurface(myPreviousEdge,myPlane,L,first,last);
|
|
gp_Pnt2d p1;
|
|
gp_Vec2d Vt;
|
|
if (myPreviousEdge.Orientation() == TopAbs_FORWARD)
|
|
C->D1(last,p1,Vt);
|
|
else
|
|
C->D1(first,p1,Vt);
|
|
gp_Lin2d aline(p1,Vt);
|
|
Geom2dAPI_ProjectPointOnCurve proj(gp_Pnt2d(X,Y),new Geom2d_Line(aline));
|
|
if (proj.NbPoints() > 0)
|
|
myCurrentEdge = BRepBuilderAPI_MakeEdge2d(p1,proj.Point(1));
|
|
}
|
|
else if (myTransitionStatus == PERPENDICULAR && myEdgesNumber > 0) {
|
|
Standard_Real first,last;
|
|
TopLoc_Location L;
|
|
Handle(Geom2d_Curve) C = BRep_Tool::CurveOnSurface(myPreviousEdge,myPlane,L,first,last);
|
|
gp_Pnt2d p1;
|
|
gp_Lin2d perpen;
|
|
if (myPreviousEdge.Orientation() == TopAbs_FORWARD)
|
|
C->D0(last,p1);
|
|
else
|
|
C->D0(first,p1);
|
|
if (C->IsKind(STANDARD_TYPE(Geom2d_Line))) {
|
|
GccAna_Lin2dTanPer aSol(p1,Handle(Geom2d_Line)::DownCast(C)->Lin2d());
|
|
perpen = aSol.ThisSolution(1);
|
|
}
|
|
else if (C->IsKind(STANDARD_TYPE(Geom2d_Circle))) {
|
|
GccAna_Lin2dTanPer aSol(p1,Handle(Geom2d_Circle)::DownCast(C)->Circ2d());
|
|
perpen = aSol.ThisSolution(1);
|
|
}
|
|
Geom2dAPI_ProjectPointOnCurve proj(gp_Pnt2d(X,Y),new Geom2d_Line(perpen));
|
|
if (proj.NbPoints() > 0)
|
|
myCurrentEdge = BRepBuilderAPI_MakeEdge2d(p1,proj.Point(1));
|
|
}
|
|
else if (myTransitionStatus == ANGLE && myEdgesNumber > 0) {
|
|
Standard_Real First,Last;
|
|
TopLoc_Location L;
|
|
Handle (Geom2d_Curve) PreviousCurve = BRep_Tool::CurveOnSurface(myPreviousEdge,myPlane,L,First,Last);
|
|
if (PreviousCurve->IsKind(STANDARD_TYPE(Geom2d_Line))) {
|
|
Handle (Geom2d_Curve) PreviousCurve = BRep_Tool::CurveOnSurface(TopoDS::Edge(myPreviousEdge),myPlane,L,First,Last);
|
|
Standard_Real angle;
|
|
if (0 <= mySegmentAngle && mySegmentAngle<= PI )
|
|
angle = PI - mySegmentAngle;
|
|
else
|
|
angle = mySegmentAngle - PI;
|
|
GccAna_Lin2dTanObl aSol(gp_Pnt2d(myLastX,myLastY),Handle(Geom2d_Line)::DownCast(PreviousCurve)->Lin2d(),angle);
|
|
Standard_Real dist = RealLast();
|
|
gp_Pnt2d pt(X,Y),ptproj;
|
|
for (Standard_Integer i =1; i<=aSol.NbSolutions(); i++) {
|
|
Geom2dAPI_ProjectPointOnCurve proj(pt,new Geom2d_Line(aSol.ThisSolution(i)));
|
|
if (pt.Distance(proj.Point(1)) < dist) {
|
|
dist = pt.Distance(proj.Point(1));
|
|
ptproj = proj.Point(1);
|
|
}
|
|
}
|
|
myCurrentEdge = BRepBuilderAPI_MakeEdge2d(gp_Pnt2d(myLastX,myLastY),ptproj);
|
|
}
|
|
}
|
|
else if (myTransitionStatus == LENGTH_FIXED && myEdgesNumber > 0) {
|
|
Standard_Real First,Last;
|
|
TopLoc_Location L;
|
|
Handle (Geom2d_Curve) PreviousCurve = BRep_Tool::CurveOnSurface(myPreviousEdge,myPlane,L,First,Last);
|
|
if (PreviousCurve->IsKind(STANDARD_TYPE(Geom2d_Line))) {
|
|
Handle (Geom2d_Curve) PreviousCurve = BRep_Tool::CurveOnSurface(TopoDS::Edge(myPreviousEdge),myPlane,L,First,Last);
|
|
gp_Lin2d aline = gce_MakeLin2d(gp_Pnt2d(myLastX,myLastY), gp_Pnt2d(X,Y));
|
|
myCurrentEdge = BRepBuilderAPI_MakeEdge2d(aline,0.,mySegmentLength);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*!
|
|
Build the current arc.
|
|
|
|
\param X
|
|
\param Y
|
|
*/
|
|
void Sketch::MakeCurrentArc(Standard_Real X, Standard_Real Y)
|
|
{
|
|
gp_Circ2d CircSol;
|
|
Standard_Boolean OK(Standard_False);
|
|
|
|
if (myTransitionStatus == NOCONSTRAINT) {
|
|
GccAna_Circ2d2TanOn aSol(gp_Pnt2d(myLastX,myLastY), gp_Pnt2d(X,Y),myMediatrice->Lin2d(),Precision::Confusion());
|
|
if (aSol.NbSolutions() > 0){
|
|
CircSol = aSol.ThisSolution(1);
|
|
OK = Standard_True;
|
|
}
|
|
}
|
|
/* Tangency with previous edge */
|
|
else if (myTransitionStatus == TANGENT && myEdgesNumber > 0) {
|
|
Standard_Real first,last;
|
|
TopLoc_Location L;
|
|
Handle(Geom2d_Curve) C = BRep_Tool::CurveOnSurface(myPreviousEdge,myPlane,L,first,last);
|
|
if (C->IsKind(STANDARD_TYPE(Geom2d_Line))){
|
|
GccAna_Circ2d2TanOn aSol(GccEnt::Unqualified(Handle(Geom2d_Line)::DownCast(C)->Lin2d()), gp_Pnt2d(myLastX,myLastY),myMediatrice->Lin2d(),Precision::Confusion());
|
|
if (aSol.NbSolutions() > 0){
|
|
CircSol = aSol.ThisSolution(1);
|
|
OK = Standard_True;
|
|
}
|
|
}
|
|
else if (C->IsKind(STANDARD_TYPE(Geom2d_Circle))) {
|
|
GccAna_Circ2d2TanOn aSol(GccEnt::Unqualified(Handle(Geom2d_Circle)::DownCast(C)->Circ2d()), gp_Pnt2d(myLastX,myLastY),myMediatrice->Lin2d(),Precision::Confusion());
|
|
if (aSol.NbSolutions() > 0){
|
|
CircSol = aSol.ThisSolution(1);
|
|
OK = Standard_True;
|
|
}
|
|
}
|
|
else if(C->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve))) {
|
|
gp_Pnt2d pc;
|
|
gp_Vec2d Vt;
|
|
C->D1(last,pc,Vt);
|
|
gp_Lin2d alin2d(pc,gp_Dir2d(Vt));
|
|
GccAna_Circ2d2TanOn aSol(GccEnt::Unqualified(alin2d), gp_Pnt2d(myLastX,myLastY),myMediatrice->Lin2d(),Precision::Confusion());
|
|
if (aSol.NbSolutions() > 0){
|
|
CircSol = aSol.ThisSolution(1);
|
|
OK = Standard_True;
|
|
}
|
|
}
|
|
}
|
|
/* Tangency with the perpendicular to the previous edge */
|
|
else if (myTransitionStatus == PERPENDICULAR && myEdgesNumber > 0) {
|
|
Standard_Real first,last;
|
|
TopLoc_Location L;
|
|
Handle(Geom2d_Curve) C = BRep_Tool::CurveOnSurface(myPreviousEdge,myPlane,L,first,last);
|
|
gp_Pnt2d p1;
|
|
gp_Lin2d perpen;
|
|
if (myPreviousEdge.Orientation() == TopAbs_FORWARD)
|
|
C->D0(last,p1);
|
|
else
|
|
C->D0(first,p1);
|
|
if (C->IsKind(STANDARD_TYPE(Geom2d_Line))) {
|
|
GccAna_Lin2dTanPer aSol(p1,Handle(Geom2d_Line)::DownCast(C)->Lin2d());
|
|
perpen = aSol.ThisSolution(1);
|
|
}
|
|
else if (C->IsKind(STANDARD_TYPE(Geom2d_Circle))) {
|
|
GccAna_Lin2dTanPer aSol(p1,Handle(Geom2d_Circle)::DownCast(C)->Circ2d());
|
|
perpen = aSol.ThisSolution(1);
|
|
}
|
|
GccAna_Circ2d2TanOn aSol(GccEnt::Unqualified(perpen), gp_Pnt2d(myLastX,myLastY),myMediatrice->Lin2d(),Precision::Confusion());
|
|
if (aSol.NbSolutions() > 0){
|
|
CircSol = aSol.ThisSolution(1);
|
|
OK = Standard_True;
|
|
}
|
|
}
|
|
|
|
gp_Pnt2d p;
|
|
if (myEdgesNumber > 0) {
|
|
if (myPreviousEdge.Orientation() == TopAbs_FORWARD)
|
|
p = ProjLib::Project(myPlane->Pln(),BRep_Tool::Pnt(TopExp::LastVertex(myPreviousEdge)));
|
|
else
|
|
p = ProjLib::Project(myPlane->Pln(),BRep_Tool::Pnt(TopExp::FirstVertex(myPreviousEdge)));
|
|
}
|
|
else
|
|
p = ProjLib::Project(myPlane->Pln(),BRep_Tool::Pnt(myFirstPointSketch));
|
|
if (OK){
|
|
gp_Vec2d V1(p,gp_Pnt2d(X,Y));
|
|
gp_Vec2d V2(p,gp_Pnt2d(myLastX,myLastY));
|
|
if (V1.Angle(V2) > 0 )
|
|
myCurrentEdge = BRepBuilderAPI_MakeEdge2d(CircSol,p,gp_Pnt2d(myLastX,myLastY));
|
|
else {
|
|
myCurrentEdge = BRepBuilderAPI_MakeEdge2d(CircSol,gp_Pnt2d(myLastX,myLastY),p);
|
|
myCurrentEdge.Reverse();
|
|
}
|
|
}
|
|
else {
|
|
myCurrentStatus = ARC_CHORD;
|
|
myLastX = p.X();
|
|
myLastY = p.Y();
|
|
myInteractiveContext->CloseLocalContext();
|
|
}
|
|
|
|
}
|
|
|
|
/*!
|
|
Display the current edge under construction with it's dimension.
|
|
*/
|
|
void Sketch::DisplayCurrentEdge()
|
|
{
|
|
myPresentableEdge->Set(myCurrentEdge);
|
|
myInteractiveContext->Redisplay(myPresentableEdge);
|
|
if (myCurrentStatus == SEGMENT ||
|
|
myCurrentStatus == ARC_CHORD ) {
|
|
/* Length dimension */
|
|
TopoDS_Vertex V1 = TopExp::FirstVertex(TopoDS::Edge(myCurrentEdge));
|
|
TopoDS_Vertex V2 = TopExp::LastVertex(TopoDS::Edge(myCurrentEdge));
|
|
DisplayLengthDimension(V1,V2);
|
|
/* Angular dimension */
|
|
DisplayAngleDimension();
|
|
DisplayXDimension(V1,V2);
|
|
DisplayYDimension(V1,V2);
|
|
}
|
|
else if (myCurrentStatus == ARC_CHORD_END )
|
|
DisplayRadiusDimension();
|
|
else {
|
|
TopoDS_Vertex V1 = TopoDS::Vertex(myCurrentEdge);
|
|
TopoDS_Vertex V2 = BRepBuilderAPI_MakeVertex(gp_Pnt(0.,0.,0.));
|
|
DisplayXDimension(V1,V2);
|
|
DisplayYDimension(V1,V2);
|
|
}
|
|
|
|
}
|
|
|
|
/*!
|
|
Display the current length dimension.
|
|
|
|
\param V1
|
|
\param V2
|
|
*/
|
|
void Sketch::DisplayLengthDimension(const TopoDS_Vertex& V1,const TopoDS_Vertex& V2)
|
|
{
|
|
gp_Pnt p1 = BRep_Tool::Pnt(TopoDS::Vertex(V1));
|
|
gp_Pnt p2 = BRep_Tool::Pnt(TopoDS::Vertex(V2));
|
|
Standard_Real length = p1.Distance(p2);
|
|
if (length <= Precision::Confusion()) return;
|
|
myLengthDimension->SetFirstShape(V1);
|
|
myLengthDimension->SetSecondShape(V2);
|
|
fitInResol(length);
|
|
myLengthDimension->SetValue(length);
|
|
QString S;
|
|
S.sprintf("%.1f",length);
|
|
myLengthDimension->SetText(TCollection_ExtendedString(strdup(S)));
|
|
if (myIsLengthDimensionVisible) {
|
|
if (myInteractiveContext->IsDisplayed(myLengthDimension))
|
|
myInteractiveContext->Redisplay(myLengthDimension);
|
|
else
|
|
myInteractiveContext->Display(myLengthDimension);
|
|
}
|
|
}
|
|
|
|
/*!
|
|
Display the current X dimension.
|
|
|
|
\param V1
|
|
\param V2
|
|
*/
|
|
void Sketch::DisplayXDimension(const TopoDS_Vertex& V1,const TopoDS_Vertex& V2)
|
|
{
|
|
if (myTransitionStatus != X_FIXED) {
|
|
gp_Pnt p1 = BRep_Tool::Pnt(TopoDS::Vertex(V1));
|
|
gp_Pnt p2 = BRep_Tool::Pnt(TopoDS::Vertex(V2));
|
|
|
|
gp_Lin aline(p1,myPlane->Pln().XAxis().Direction());
|
|
GeomAPI_ProjectPointOnCurve proj(p2,new Geom_Line(aline));
|
|
|
|
gp_Pnt pb = p1;
|
|
|
|
if (proj.NbPoints() > 0) {
|
|
Standard_Real length = p1.Distance(proj.Point(1));
|
|
if (length <= Precision::Confusion()) return;
|
|
myXDimension->SetFirstShape(V1);
|
|
myXDimension->SetSecondShape(V2);
|
|
fitInResol(length);
|
|
myXDimension->SetValue(length);
|
|
QString S;
|
|
S.sprintf("%.1f",length);
|
|
myXDimension->SetText(TCollection_ExtendedString(strdup(S)));
|
|
// myXDimension->SetPosition(proj.Point(1));
|
|
pb.BaryCenter(5,proj.Point(1),5);
|
|
myXDimension->SetPosition(pb);
|
|
if (myIsXDimensionVisible) {
|
|
if (myInteractiveContext->IsDisplayed(myXDimension))
|
|
myInteractiveContext->Redisplay(myXDimension);
|
|
else
|
|
myInteractiveContext->Display(myXDimension);
|
|
}
|
|
}
|
|
} else
|
|
myInteractiveContext->Erase(myXDimension,Standard_True,Standard_False);
|
|
}
|
|
|
|
/*!
|
|
Display the current Y dimension.
|
|
|
|
\param V1
|
|
\param V2
|
|
*/
|
|
void Sketch::DisplayYDimension(const TopoDS_Vertex& V1,const TopoDS_Vertex& V2)
|
|
{
|
|
if (myTransitionStatus != Y_FIXED) {
|
|
|
|
gp_Pnt p1 = BRep_Tool::Pnt(TopoDS::Vertex(V1));
|
|
gp_Pnt p2 = BRep_Tool::Pnt(TopoDS::Vertex(V2));
|
|
gp_Lin aline(p2 /*p1*/, myPlane->Pln().YAxis().Direction());
|
|
gp_Pnt pb = p2 /*p1*/;
|
|
GeomAPI_ProjectPointOnCurve proj(p1 /*p2*/,new Geom_Line(aline));
|
|
if (proj.NbPoints() > 0) {
|
|
Standard_Real length = /*p1*/ p2.Distance(proj.Point(1));
|
|
if (length <= Precision::Confusion()) return;
|
|
myYDimension->SetFirstShape(V1);
|
|
myYDimension->SetSecondShape(V2);
|
|
fitInResol(length);
|
|
myYDimension->SetValue(length);
|
|
QString S;
|
|
S.sprintf("%.1f",length);
|
|
myYDimension->SetText(TCollection_ExtendedString(strdup(S)));
|
|
pb.BaryCenter(5,proj.Point(1),5);
|
|
myYDimension->SetPosition(pb);
|
|
// myYDimension->SetPosition(p2);
|
|
if (myIsYDimensionVisible) {
|
|
if (myInteractiveContext->IsDisplayed(myYDimension))
|
|
myInteractiveContext->Redisplay(myYDimension);
|
|
else
|
|
myInteractiveContext->Display(myYDimension);
|
|
}
|
|
}
|
|
} else
|
|
myInteractiveContext->Erase(myYDimension,Standard_True,Standard_False);
|
|
}
|
|
|
|
/*!
|
|
Display the current angle dimension.
|
|
*/
|
|
void Sketch::DisplayAngleDimension()
|
|
{
|
|
if (!myIsAngleDimensionVisible)
|
|
return;
|
|
if (myEdgesNumber > 0) {
|
|
Standard_Real First,Last;
|
|
TopLoc_Location L;
|
|
Handle (Geom2d_Curve) PreviousCurve = BRep_Tool::CurveOnSurface(myPreviousEdge,myPlane,L,First,Last);
|
|
Handle (Geom2d_Curve) CurrentCurve = BRep_Tool::CurveOnSurface(TopoDS::Edge(myCurrentEdge),myPlane,L,First,Last);
|
|
if (PreviousCurve->IsKind(STANDARD_TYPE(Geom2d_Line)) && CurrentCurve->IsKind(STANDARD_TYPE(Geom2d_Line))) {
|
|
Standard_Real angle = Handle(Geom2d_Line)::DownCast(PreviousCurve)->Lin2d().Angle(Handle(Geom2d_Line)::DownCast(CurrentCurve)->Lin2d());
|
|
gp_Pnt2d apos;
|
|
if (0 <= angle && angle<= PI)
|
|
angle = PI - angle;
|
|
else
|
|
angle = PI + angle;
|
|
CurrentCurve->D0((First+Last)/5.,apos);
|
|
gp_Pnt apos3d = ElCLib::To3d(myPlane->Pln().Position().Ax2(),apos);
|
|
Standard_Real angtext = angle*180./PI;
|
|
mySegmentAngle = angle;
|
|
BRepLib::BuildCurve3d(TopoDS::Edge(myCurrentEdge));
|
|
fitInResol(angtext);
|
|
|
|
QString S;
|
|
S.sprintf("%.1f",angtext);
|
|
if (myInteractiveContext->IndexOfCurrentLocal() == 0) {
|
|
myInteractiveContext->OpenLocalContext();
|
|
myAngleDimension = new AIS_AngleDimension(myPreviousEdge,TopoDS::Edge(myCurrentEdge),myPlane,angle,
|
|
TCollection_ExtendedString(strdup(S)));
|
|
myInteractiveContext->Display(myAngleDimension);
|
|
}
|
|
else {
|
|
myAngleDimension->SetSecondShape(myCurrentEdge);
|
|
myAngleDimension->SetValue(angle);
|
|
myAngleDimension->SetPosition(apos3d);
|
|
myAngleDimension->SetText(TCollection_ExtendedString(strdup(S)));
|
|
myInteractiveContext->Redisplay(myAngleDimension);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*!
|
|
Display the current radius dimension.
|
|
*/
|
|
void Sketch::DisplayRadiusDimension()
|
|
{
|
|
if (! myIsRadiusDimensionVisible)
|
|
return;
|
|
BRepLib::BuildCurve3d(TopoDS::Edge(myCurrentEdge));
|
|
Standard_Real First,Last;
|
|
Handle (Geom_Circle) C = Handle (Geom_Circle)::DownCast(BRep_Tool::Curve(TopoDS::Edge(myCurrentEdge),First,Last));
|
|
if (!C.IsNull()) {
|
|
Standard_Real R = C->Radius();
|
|
TopoDS_Shape V1 = BRepBuilderAPI_MakeVertex(C->Location());
|
|
gp_Pnt MidlePoint ;
|
|
C->D0((First+Last)/2.,MidlePoint);
|
|
TopoDS_Vertex V2 = BRepBuilderAPI_MakeVertex(MidlePoint);
|
|
myRadiusDimension->SetFirstShape(V1);
|
|
myRadiusDimension->SetSecondShape(V2);
|
|
myRadiusDimension->SetValue(R);
|
|
fitInResol(R);
|
|
QString S;
|
|
S.sprintf("%.1f",R);
|
|
myRadiusDimension->SetText(TCollection_ExtendedString(strdup(S)));
|
|
if (myInteractiveContext->IsDisplayed(myRadiusDimension))
|
|
myInteractiveContext->Redisplay(myRadiusDimension);
|
|
else
|
|
myInteractiveContext->Display(myRadiusDimension);
|
|
myCenterCircle->Set(V1);
|
|
if (myInteractiveContext->IsDisplayed(myCenterCircle))
|
|
myInteractiveContext->Redisplay(myCenterCircle);
|
|
else
|
|
myInteractiveContext->Display(myCenterCircle);
|
|
}
|
|
}
|
|
|
|
/*!
|
|
Remove last edge from the current wire.
|
|
*/
|
|
void Sketch::RemoveLastEdge()
|
|
{
|
|
if (myEdgesNumber == 0) {
|
|
myCurrentStatus = END_SKETCH;
|
|
myInteractiveContext->CloseAllContexts();
|
|
myInteractiveContext->EraseAll(Standard_False);
|
|
return;
|
|
}
|
|
else {
|
|
BRepTools_WireExplorer Ex;
|
|
BRepBuilderAPI_MakeWire MW;
|
|
Standard_Integer index = 1;
|
|
myCurrentEdge = myPreviousEdge;
|
|
for (Ex.Init(myCurrentWire.Wire());Ex.More();Ex.Next()){
|
|
if (index <= myEdgesNumber-1) {
|
|
MW.Add(Ex.Current());
|
|
myPreviousEdge = Ex.Current();
|
|
index++;
|
|
}
|
|
}
|
|
myCurrentWire = MW;
|
|
myCurrentStatus = (SketchStatus)myConstructionMode(myEdgesNumber);
|
|
myTransitionStatus = (TransitionStatus)myConstraintMode(myEdgesNumber);
|
|
myEdgesNumber--;
|
|
myConstructionMode.Remove(index);
|
|
myConstraintMode.Remove(index);
|
|
if (myEdgesNumber == 0)
|
|
myPresentableWire->Set(myFirstPointSketch);
|
|
else
|
|
myPresentableWire->Set(myCurrentWire.Wire());
|
|
myInteractiveContext->Redisplay(myPresentableWire);
|
|
myInteractiveContext->CloseLocalContext();
|
|
myPresentableEdge->Set(myCurrentEdge);
|
|
myInteractiveContext->Redisplay(myPresentableEdge);
|
|
}
|
|
}
|
|
|
|
/*!
|
|
Create initial constraints.
|
|
*/
|
|
void Sketch::CreateConstraints()
|
|
{
|
|
Handle(Geom_Axis1Placement) xAxis = new Geom_Axis1Placement(myPlane->Pln().XAxis());
|
|
Handle(Geom_Axis1Placement) yAxis = new Geom_Axis1Placement(myPlane->Pln().YAxis());
|
|
myHAxis = new AIS_Axis(xAxis);
|
|
myVAxis = new AIS_Axis(yAxis);
|
|
myAngularAxis = myVAxis;
|
|
myHAxis->SetColor(myAxisColor.Name());
|
|
myVAxis->SetColor(myAxisColor.Name());
|
|
myAngularAxis->SetColor(myAxisColor.Name());
|
|
}
|
|
|
|
/*!
|
|
fitInResol.
|
|
|
|
\param toFit
|
|
\param minIsResol
|
|
*/
|
|
void Sketch::fitInResol(Standard_Real &toFit, Standard_Boolean minIsResol)
|
|
{
|
|
Standard_Real sign = (toFit < 0) ? -1. : +1.;
|
|
Standard_Real value = toFit + sign * resol/2.0; /* why "+ resol/2.0" ? because if resol = 0.5, 3.3 is rounded to 3.5 */
|
|
int nTimesResol = int(value/resol);
|
|
if ((nTimesResol == 0) && (minIsResol)) nTimesResol = 1;
|
|
toFit = nTimesResol*resol;
|
|
}
|
|
|
|
SketchStatus Sketch::GetCurrentStatus()
|
|
{
|
|
return myCurrentStatus;
|
|
}
|
|
|
|
Standard_Integer Sketch::GetmyEdgesNumber()
|
|
{
|
|
return myEdgesNumber;
|
|
}
|
|
|
|
|
|
|