Files
OCCT/src/Draft/Draft_Modification_1.cxx
dpasukhi a5a7b3185b Coding - Apply .clang-format formatting #286
Update empty method guards to new style with regex (see PR).
Used clang-format 18.1.8.
New actions to validate code formatting is added.
Update .clang-format with disabling of include sorting.
  It is temporary changes, then include will be sorted.
Apply formatting for /src and /tools folder.
The files with .hxx,.cxx,.lxx,.h,.pxx,.hpp,*.cpp extensions.
2025-01-26 00:43:57 +00:00

2378 lines
80 KiB
C++

// Created on: 1994-12-02
// Created by: Jacques GOUSSARD
// Copyright (c) 1994-1999 Matra Datavision
// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <Adaptor3d_CurveOnSurface.hxx>
#include <Adaptor3d_CurveOnSurface.hxx>
#include <GeomAdaptor_SurfaceOfLinearExtrusion.hxx>
#include <Approx_CurveOnSurface.hxx>
#include <BRep_Builder.hxx>
#include <BRep_Tool.hxx>
#include <BRepExtrema_ExtCF.hxx>
#include <BRepTools.hxx>
#include <Draft_Modification.hxx>
#include <Draft_VertexInfo.hxx>
#include <ElCLib.hxx>
#include <ElSLib.hxx>
#include <Geom2d_BezierCurve.hxx>
#include <Geom2d_Curve.hxx>
#include <Geom2d_Line.hxx>
#include <Geom2d_TrimmedCurve.hxx>
#include <Geom2dAPI_ProjectPointOnCurve.hxx>
#include <Geom2dConvert.hxx>
#include <Geom2dConvert_CompCurveToBSplineCurve.hxx>
#include <Geom_BSplineCurve.hxx>
#include <Geom_Circle.hxx>
#include <Geom_Conic.hxx>
#include <Geom_ConicalSurface.hxx>
#include <Geom_Curve.hxx>
#include <Geom_CylindricalSurface.hxx>
#include <Geom_ElementarySurface.hxx>
#include <Geom_Ellipse.hxx>
#include <Geom_Hyperbola.hxx>
#include <Geom_Line.hxx>
#include <Geom_Parabola.hxx>
#include <Geom_Plane.hxx>
#include <Geom_RectangularTrimmedSurface.hxx>
#include <Geom_Surface.hxx>
#include <Geom_SurfaceOfLinearExtrusion.hxx>
#include <Geom_TrimmedCurve.hxx>
#include <GeomAdaptor_Surface.hxx>
#include <GeomAPI_ProjectPointOnCurve.hxx>
#include <GeomAPI_ProjectPointOnSurf.hxx>
#include <GeomConvert_CompCurveToBSplineCurve.hxx>
#include <GeomInt_IntSS.hxx>
#include <GeomProjLib.hxx>
#include <gp.hxx>
#include <gp_Circ.hxx>
#include <gp_Dir.hxx>
#include <gp_Elips.hxx>
#include <gp_Lin.hxx>
#include <gp_Pln.hxx>
#include <gp_Pnt.hxx>
#include <gp_Vec.hxx>
#include <IntAna_IntConicQuad.hxx>
#include <IntAna_QuadQuadGeo.hxx>
#include <IntCurveSurface_HInter.hxx>
#include <IntCurveSurface_IntersectionPoint.hxx>
#include <Precision.hxx>
#include <ProjLib_HCompProjectedCurve.hxx>
#include <Standard_ConstructionError.hxx>
#include <Standard_Failure.hxx>
#include <Standard_NotImplemented.hxx>
#include <TColgp_Array1OfPnt2d.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#include <TopLoc_Location.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Shape.hxx>
#include <TopoDS_Vertex.hxx>
#include <TopTools_MapOfShape.hxx>
static Standard_Boolean Choose(const Draft_IndexedDataMapOfFaceFaceInfo&,
Draft_IndexedDataMapOfEdgeEdgeInfo&,
const TopoDS_Vertex&,
Draft_VertexInfo&,
GeomAdaptor_Curve&,
GeomAdaptor_Surface&);
static Standard_Real Parameter(const Handle(Geom_Curve)&, const gp_Pnt&, Standard_Integer&);
static Standard_Real SmartParameter(Draft_EdgeInfo&,
const Standard_Real EdgeTol,
const gp_Pnt&,
const Standard_Integer,
const Handle(Geom_Surface)&,
const Handle(Geom_Surface)&);
static TopAbs_Orientation Orientation(const TopoDS_Shape&, const TopoDS_Face&);
static Standard_Boolean FindRotation(const gp_Pln&,
const TopAbs_Orientation,
const gp_Dir&,
const Standard_Real,
const gp_Pln&,
gp_Ax1&,
Standard_Real&);
//=================================================================================================
Standard_Boolean Draft_Modification::InternalAdd(const TopoDS_Face& F,
const gp_Dir& Direction,
const Standard_Real Angle,
const gp_Pln& NeutralPlane,
const Standard_Boolean Flag)
{
if (myFMap.Contains(F))
{
return (badShape.IsNull());
}
TopAbs_Orientation oris = Orientation(myShape, F);
TopLoc_Location Lo;
// gp_Dir NewDirection = Direction;
// Standard_Real NewAngle = Angle;
Handle(Geom_Surface) S = BRep_Tool::Surface(F, Lo);
S = Handle(Geom_Surface)::DownCast(S->Transformed(Lo.Transformation()));
if (S->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface))
{
S = Handle(Geom_RectangularTrimmedSurface)::DownCast(S)->BasisSurface();
}
Handle(Geom_Surface) NewS;
Handle(Geom_Circle) theCircle;
Standard_Boolean postponed = (Flag == Standard_False);
if (postponed)
{
Handle(Standard_Type) typS = S->DynamicType();
if (typS == STANDARD_TYPE(Geom_CylindricalSurface)
|| typS == STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion))
{
gp_Circ Cir;
if (typS == STANDARD_TYPE(Geom_CylindricalSurface))
{
gp_Cylinder cyl = Handle(Geom_CylindricalSurface)::DownCast(S)->Cylinder();
gp_Ax1 axcyl = cyl.Axis();
Cir = ElSLib::CylinderVIso(cyl.Position(), cyl.Radius(), 0.);
gp_Vec VV(cyl.Location(), NeutralPlane.Location());
Cir.Translate(VV.Dot(axcyl.Direction()) * axcyl.Direction());
}
else
{
Handle(Geom_Curve) Cbas = Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(S)->BasisCurve();
gp_Dir theDirextr = Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(S)->Direction();
if (Cbas->IsKind(STANDARD_TYPE(Geom_TrimmedCurve)))
{
Cbas = Handle(Geom_TrimmedCurve)::DownCast(Cbas)->BasisCurve();
}
if (Cbas->IsKind(STANDARD_TYPE(Geom_Circle)))
{
Cir = Handle(Geom_Circle)::DownCast(Cbas)->Circ();
gp_Dir dircir = Cir.Axis().Direction();
if (!Direction.IsParallel(dircir, Precision::Angular()))
{
badShape = F;
errStat = Draft_FaceRecomputation;
return Standard_False;
}
}
else
{
badShape = F;
errStat = Draft_FaceRecomputation;
return Standard_False;
}
gp_Ax3 Axis = NeutralPlane.Position();
Standard_Real L = gp_Vec(Cir.Location(), Axis.Location()).Dot(Axis.Direction());
Standard_Real Cos = theDirextr.Dot(Axis.Direction());
gp_Vec VV = (L / Cos) * theDirextr;
Cir.Translate(VV);
}
theCircle = new Geom_Circle(Cir);
}
else
{
postponed = Standard_False;
}
}
if (!postponed)
{
NewS = NewSurface(S, oris, Direction, Angle, NeutralPlane);
if (NewS.IsNull())
{
badShape = F;
errStat = Draft_FaceRecomputation;
return Standard_False;
}
// To avoid some problems with infinite restrictions
const Handle(Standard_Type)& typs = NewS->DynamicType();
if (typs == STANDARD_TYPE(Geom_CylindricalSurface)
|| typs == STANDARD_TYPE(Geom_ConicalSurface))
{
Standard_Real umin, umax, vmin, vmax;
BRepTools::UVBounds(F, umin, umax, vmin, vmax);
if (!Precision::IsNegativeInfinite(vmin) && !Precision::IsPositiveInfinite(vmax))
{
Standard_Real deltav = 10. * (vmax - vmin);
if (typs == STANDARD_TYPE(Geom_CylindricalSurface))
{
vmin = vmin - deltav;
vmax = vmax + deltav;
}
else
{
gp_Cone Co = Handle(Geom_ConicalSurface)::DownCast(NewS)->Cone();
Standard_Real Vapex = -Co.RefRadius() / Sin(Co.SemiAngle());
if (vmin < Vapex)
{ // vmax should not exceed Vapex
if (vmax + deltav > Vapex)
{
vmax = Vapex;
vmin = vmin - 10. * (vmax - vmin);
// JAG debug to avoid apex
vmax = vmax - Precision::Confusion();
}
else
{
vmin = vmin - deltav;
vmax = vmax + deltav;
}
}
else
{ // Vapex <= vmin < vmax
if (vmin - deltav < Vapex)
{
vmin = Vapex;
vmax = vmax + 10. * (vmax - vmin);
// JAG debug to avoid apex
vmin = vmin + Precision::Confusion();
}
else
{
vmin = vmin - deltav;
vmax = vmax + deltav;
}
}
}
NewS = new Geom_RectangularTrimmedSurface(NewS, 0., 2. * M_PI, vmin, vmax);
}
}
}
if (postponed || S != NewS)
{
Draft_FaceInfo FI(NewS, Standard_True);
FI.RootFace(curFace);
myFMap.Add(F, FI);
if (postponed)
{
myFMap.ChangeFromKey(F).ChangeCurve() = theCircle;
}
}
TopExp_Explorer aExp(F, TopAbs_EDGE);
TopTools_MapOfShape MapOfE;
while (aExp.More() && badShape.IsNull())
{
const TopoDS_Edge& edg = TopoDS::Edge(aExp.Current());
if (!myEMap.Contains(edg))
{
Standard_Boolean addedg = Standard_False;
Standard_Boolean addface = Standard_False;
TopoDS_Face OtherF;
// if (BRep_Tool::IsClosed(edg,F)) {
if (BRepTools::IsReallyClosed(edg, F))
{
addedg = Standard_True;
addface = Standard_False;
}
else
{
// Find the other face containing the edge.
TopTools_ListIteratorOfListOfShape it;
it.Initialize(myEFMap.FindFromKey(edg));
Standard_Integer nbother = 0;
while (it.More())
{
if (!it.Value().IsSame(F))
{
if (OtherF.IsNull())
{
OtherF = TopoDS::Face(it.Value());
}
nbother++;
}
it.Next();
}
if (nbother >= 2)
{
badShape = edg;
errStat = Draft_EdgeRecomputation;
}
else if (!OtherF.IsNull() && BRep_Tool::Continuity(edg, F, OtherF) >= GeomAbs_G1)
{
addface = Standard_True;
addedg = Standard_True;
}
else if (nbother == 0)
{
// badShape = F;
}
}
if (addedg)
{
if (postponed)
{
myFMap.ChangeFromKey(F).Add(OtherF);
}
Standard_Real f, l;
TopLoc_Location L;
Handle(Geom_Curve) C = BRep_Tool::Curve(edg, L, f, l);
C = Handle(Geom_Curve)::DownCast(C->Transformed(L));
if (C->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve))
{
C = Handle(Geom_TrimmedCurve)::DownCast(C)->BasisCurve();
}
Handle(Geom_Curve) NewC;
Draft_EdgeInfo EInf(Standard_True);
if (postponed)
{
EInf.Add(F);
EInf.Add(OtherF);
// find fixed point
Handle(Geom_Line) aLocalGeom = Handle(Geom_Line)::DownCast(C);
if (aLocalGeom.IsNull())
{
badShape = edg;
errStat = Draft_EdgeRecomputation;
}
else
{
gp_Lin lin = aLocalGeom->Lin();
IntAna_IntConicQuad ilipl(lin, NeutralPlane, Precision::Angular());
if (ilipl.IsDone() && ilipl.NbPoints() != 0)
{
EInf.Tangent(ilipl.Point(1));
}
else
{
badShape = edg;
errStat = Draft_EdgeRecomputation;
}
}
}
else
{
NewC = NewCurve(C, S, oris, Direction, Angle, NeutralPlane, Flag);
if (NewC.IsNull())
{
badShape = edg;
errStat = Draft_EdgeRecomputation;
}
}
Handle(Geom_TrimmedCurve) T = Handle(Geom_TrimmedCurve)::DownCast(NewC);
if (!T.IsNull())
NewC = T->BasisCurve();
EInf.ChangeGeometry() = NewC;
EInf.RootFace(curFace);
myEMap.Add(edg, EInf);
MapOfE.Add(edg);
if (addface)
{
Standard_Boolean Fl = Flag;
Handle(Geom_Surface) alocalSurface = BRep_Tool::Surface(OtherF, Lo);
if (alocalSurface->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface))
{
alocalSurface =
Handle(Geom_RectangularTrimmedSurface)::DownCast(alocalSurface)->BasisSurface();
}
Handle(Standard_Type) typS = alocalSurface->DynamicType();
if (typS == STANDARD_TYPE(Geom_CylindricalSurface)
|| typS == STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion))
{
if (myFMap.Contains(F))
{
if (Flag == Standard_False && !postponed)
{
myFMap.RemoveKey(F);
TopTools_MapIteratorOfMapOfShape itm(MapOfE);
for (; itm.More(); itm.Next())
{
myEMap.RemoveKey(TopoDS::Edge(itm.Key()));
}
}
}
}
InternalAdd(OtherF, Direction, Angle, NeutralPlane, Fl);
}
}
}
aExp.Next();
}
return (badShape.IsNull());
}
//=================================================================================================
Standard_Boolean Draft_Modification::Propagate()
{
if (!badShape.IsNull())
return Standard_False;
// Set all edges and vertices of modified faces
TopoDS_Face F;
TopoDS_Edge E;
TopoDS_Vertex V;
TopExp_Explorer editer;
TopExp_Explorer vtiter;
for (Standard_Integer i = 1; i <= myFMap.Extent(); i++)
{
const TopoDS_Face& Fc = myFMap.FindKey(i);
// Exploration of the edges of the face
editer.Init(Fc, TopAbs_EDGE);
while (editer.More())
{
E = TopoDS::Edge(editer.Current());
if (!myEMap.Contains(E))
{
Draft_EdgeInfo EInf(Standard_True);
myEMap.Add(E, EInf);
}
myEMap.ChangeFromKey(E).Add(Fc);
// Exploration of the vertices of the edge
vtiter.Init(E, TopAbs_VERTEX);
while (vtiter.More())
{
V = TopoDS::Vertex(vtiter.Current());
if (!myVMap.Contains(V))
{
Draft_VertexInfo VInf;
myVMap.Add(V, VInf);
}
myVMap.ChangeFromKey(V).Add(E);
myVMap.ChangeFromKey(V).ChangeParameter(E) = BRep_Tool::Parameter(V, E);
vtiter.Next();
}
editer.Next();
}
}
TopExp_Explorer anc;
Standard_Boolean found;
// Set edges containing modified vertices.
for (Standard_Integer i = 1; i <= myVMap.Extent(); i++)
{
const TopoDS_Vertex& Vt = myVMap.FindKey(i);
// Exploration of the ancestors of the vertex
anc.Init(myShape, TopAbs_EDGE);
while (anc.More())
{
E = TopoDS::Edge(anc.Current());
vtiter.Init(E, TopAbs_VERTEX);
found = Standard_False;
while (vtiter.More())
{
if (Vt.IsSame(TopoDS::Vertex(vtiter.Current())))
{
found = Standard_True;
break;
}
vtiter.Next();
}
if (found)
{
if (!myEMap.Contains(E))
{
Draft_EdgeInfo EInf(Standard_False);
myEMap.Add(E, EInf);
}
myVMap.ChangeFromKey(Vt).Add(E);
myVMap.ChangeFromKey(Vt).ChangeParameter(E) = BRep_Tool::Parameter(Vt, E);
}
anc.Next();
}
}
// Set faces containing modified edges
for (Standard_Integer i = 1; i <= myEMap.Extent(); i++)
{
const TopoDS_Edge& Ed = myEMap.FindKey(i);
TopTools_ListIteratorOfListOfShape it;
for (it.Initialize(myEFMap.FindFromKey(Ed)); it.More(); it.Next())
{
F = TopoDS::Face(it.Value());
if (!myFMap.Contains(F))
{
TopLoc_Location L;
Handle(Geom_Surface) S = BRep_Tool::Surface(F, L);
Handle(Geom_Surface) NewS =
Handle(Geom_Surface)::DownCast(S->Transformed(L.Transformation()));
const Handle(Standard_Type)& typs = S->DynamicType();
if (typs == STANDARD_TYPE(Geom_CylindricalSurface)
|| typs == STANDARD_TYPE(Geom_ConicalSurface))
{
Standard_Real umin, umax, vmin, vmax;
BRepTools::UVBounds(F, umin, umax, vmin, vmax);
if (!Precision::IsNegativeInfinite(vmin) && !Precision::IsPositiveInfinite(vmax))
{
Standard_Real deltav = 10. * (vmax - vmin);
vmin = vmin - deltav;
vmax = vmax + deltav;
NewS = new Geom_RectangularTrimmedSurface(NewS, 0., 2. * M_PI, vmin, vmax);
}
}
Draft_FaceInfo FInf(NewS, Standard_False);
myFMap.Add(F, FInf);
}
myEMap.ChangeFromKey(Ed).Add(F);
}
}
// Try to add faces for free borders...
// JAG 09.11.95
for (Standard_Integer i = 1; i <= myEMap.Extent(); i++)
{
Draft_EdgeInfo& Einf = myEMap.ChangeFromIndex(i);
if (Einf.NewGeometry() && Einf.Geometry().IsNull() && Einf.SecondFace().IsNull())
{
TopLoc_Location Loc;
Handle(Geom_Surface) S1 = BRep_Tool::Surface(Einf.FirstFace(), Loc);
S1 = Handle(Geom_Surface)::DownCast(S1->Transformed(Loc.Transformation()));
Handle(Geom_Surface) S2;
Standard_Real f, l;
const TopoDS_Edge& EK = myEMap.FindKey(i);
Handle(Geom_Curve) C = BRep_Tool::Curve(EK, Loc, f, l);
C = Handle(Geom_Curve)::DownCast(C->Transformed(Loc.Transformation()));
if (C->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve))
{
C = Handle(Geom_TrimmedCurve)::DownCast(C)->BasisCurve();
}
if (!S1->IsKind(STANDARD_TYPE(Geom_Plane)))
{
if (C->IsKind(STANDARD_TYPE(Geom_Conic)))
{
gp_Ax3 thePl(Handle(Geom_Conic)::DownCast(C)->Position());
S2 = new Geom_Plane(thePl);
}
else if (C->DynamicType() == STANDARD_TYPE(Geom_Line))
{
gp_Ax1 axis;
if (S1->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface))
{
axis = Handle(Geom_ElementarySurface)::DownCast(
Handle(Geom_RectangularTrimmedSurface)::DownCast(S1)->BasisSurface())
->Axis();
}
else
{
axis = Handle(Geom_ElementarySurface)::DownCast(S1)->Axis();
}
gp_Vec they(axis.Location(), C->Value(0.));
gp_Dir axz(axis.Direction().Crossed(they));
S2 = new Geom_Plane(gp_Ax3(axis.Location(), axz, axis.Direction()));
}
else
{
badShape = EK;
errStat = Draft_EdgeRecomputation;
break; // leave from for
}
}
else
{ // on the plane
for (Standard_Integer j = 1; j <= myVMap.Extent(); j++)
{
Draft_VertexInfo& Vinf = myVMap.ChangeFromIndex(j);
for (Vinf.InitEdgeIterator(); Vinf.MoreEdge(); Vinf.NextEdge())
{
if (Vinf.Edge().IsSame(EK))
{
break;
}
}
if (Vinf.MoreEdge())
{
for (Vinf.InitEdgeIterator(); Vinf.MoreEdge(); Vinf.NextEdge())
{
const TopoDS_Edge& edg = Vinf.Edge();
if (!edg.IsSame(EK))
{
const Draft_EdgeInfo& EI = myEMap.FindFromKey(edg);
if (!EI.FirstFace().IsSame(Einf.FirstFace())
&& (EI.SecondFace().IsNull() || !EI.SecondFace().IsSame(Einf.FirstFace())))
{
break;
}
}
}
if (Vinf.MoreEdge())
{
Handle(Geom_Curve) C2 = BRep_Tool::Curve(Vinf.Edge(), Loc, f, l);
Handle(GeomAdaptor_Curve) HCur;
gp_Vec Direc;
C2 = Handle(Geom_Curve)::DownCast(C2->Transformed(Loc.Transformation()));
if (C2->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve))
{
C2 = Handle(Geom_TrimmedCurve)::DownCast(C2)->BasisCurve();
}
if (C->DynamicType() == STANDARD_TYPE(Geom_Line))
{
Direc = Handle(Geom_Line)::DownCast(C)->Lin().Direction();
HCur = new GeomAdaptor_Curve(C2);
}
else if (C2->DynamicType() == STANDARD_TYPE(Geom_Line))
{
Direc = Handle(Geom_Line)::DownCast(C2)->Lin().Direction();
HCur = new GeomAdaptor_Curve(C);
}
else
{
badShape = EK;
errStat = Draft_EdgeRecomputation;
break; // leave from while
}
GeomAdaptor_SurfaceOfLinearExtrusion SLE(HCur, Direc);
switch (SLE.GetType())
{
case GeomAbs_Plane: {
S2 = new Geom_Plane(SLE.Plane());
}
break;
case GeomAbs_Cylinder: {
S2 = new Geom_CylindricalSurface(SLE.Cylinder());
}
break;
default: {
S2 = new Geom_SurfaceOfLinearExtrusion(HCur->Curve(), Direc);
}
break;
}
}
else
{
badShape = EK;
errStat = Draft_EdgeRecomputation;
break; // leave from while
}
break;
}
// j++;
}
}
if (badShape.IsNull())
{
BRep_Builder B;
TopoDS_Face TheNewFace;
B.MakeFace(TheNewFace, S2, Precision::Confusion());
Einf.Add(TheNewFace);
Draft_FaceInfo FI(S2, Standard_False);
myFMap.Add(TheNewFace, FI);
}
else
{
break; // leave from for
}
// Fin JAG 09.11.95
}
}
return (badShape.IsNull());
}
//=================================================================================================
void Draft_Modification::Perform()
{
if (!badShape.IsNull())
throw Standard_ConstructionError();
if (!myComp)
{
myComp = Standard_True;
if (!Propagate())
{
return;
}
// Calculate eventual faces
for (Standard_Integer i = 1; i <= myFMap.Extent(); i++)
{
const TopoDS_Face& FK = myFMap.FindKey(i);
Draft_FaceInfo& Finf = myFMap.ChangeFromIndex(i);
if (Finf.NewGeometry() && Finf.Geometry().IsNull())
{
const TopoDS_Face& F1 = Finf.FirstFace();
const TopoDS_Face& F2 = Finf.SecondFace();
if (F1.IsNull() || F2.IsNull())
{
errStat = Draft_FaceRecomputation;
badShape = FK;
return;
}
Handle(Geom_Surface) S1 = myFMap.FindFromKey(F1).Geometry();
Handle(Geom_Surface) S2 = myFMap.FindFromKey(F2).Geometry();
if (S1.IsNull() || S2.IsNull())
{
errStat = Draft_FaceRecomputation;
badShape = FK;
return;
}
if (S1->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface))
{
S1 = Handle(Geom_RectangularTrimmedSurface)::DownCast(S1)->BasisSurface();
}
if (S2->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface))
{
S2 = Handle(Geom_RectangularTrimmedSurface)::DownCast(S2)->BasisSurface();
}
Handle(Geom_Plane) P1 = Handle(Geom_Plane)::DownCast(S1);
Handle(Geom_Plane) P2 = Handle(Geom_Plane)::DownCast(S2);
if (P1.IsNull() || P2.IsNull())
{
errStat = Draft_FaceRecomputation;
badShape = FK;
return;
}
gp_Pln pp1 = P1->Pln();
gp_Pln pp2 = P2->Pln();
IntAna_QuadQuadGeo i2p(pp1, pp2, Precision::Angular(), Precision::Confusion());
if (!i2p.IsDone() || i2p.TypeInter() != IntAna_Line)
{
errStat = Draft_FaceRecomputation;
badShape = FK;
return;
}
gp_Dir extrdir = i2p.Line(1).Direction();
// Preserve the same direction as the base face
Handle(Geom_Surface) RefSurf = BRep_Tool::Surface(FK);
if (RefSurf->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface))
{
RefSurf = Handle(Geom_RectangularTrimmedSurface)::DownCast(RefSurf)->BasisSurface();
}
gp_Dir DirRef;
if (RefSurf->DynamicType() == STANDARD_TYPE(Geom_CylindricalSurface))
{
gp_Ax3 AxeRef = Handle(Geom_CylindricalSurface)::DownCast(RefSurf)->Cylinder().Position();
DirRef = AxeRef.Direction();
}
else if (RefSurf->DynamicType() == STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion))
{
DirRef = Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(RefSurf)->Direction();
}
if (extrdir.Dot(DirRef) < 0.)
extrdir.Reverse();
// it is possible to accelerate speed by storing the info during
// InternalAdd --> modification of FaceInfo to preserve the circle
Handle(Geom_Circle) CCir = Handle(Geom_Circle)::DownCast(Finf.Curve());
Handle(Geom_Surface) NewS = new Geom_SurfaceOfLinearExtrusion(CCir, extrdir);
Standard_Real umin, umax, vmin, vmax;
BRepTools::UVBounds(FK, umin, umax, vmin, vmax);
if (!Precision::IsNegativeInfinite(vmin) && !Precision::IsPositiveInfinite(vmax))
{
Standard_Real deltav = 2. * (vmax - vmin);
vmin = vmin - deltav;
vmax = vmax + deltav;
}
// very temporary
else
{
vmax = 300;
vmin = -300;
}
NewS = new Geom_RectangularTrimmedSurface(NewS, 0., 1.9 * M_PI, vmin, vmax);
Finf.ChangeGeometry() = NewS;
}
}
// Calculate new edges.
for (Standard_Integer ii = 1; ii <= myEMap.Extent(); ii++)
{
Draft_EdgeInfo& Einf = myEMap.ChangeFromIndex(ii);
const TopoDS_Edge& theEdge = TopoDS::Edge(myEMap.FindKey(ii));
Handle(Geom_Surface) S1, S2;
Handle(Geom_Curve) C, newC;
Standard_Real f, l;
TopLoc_Location L;
C = BRep_Tool::Curve(theEdge, L, f, l);
C = Handle(Geom_Curve)::DownCast(C->Transformed(L.Transformation()));
if (Einf.NewGeometry() && Einf.Geometry().IsNull())
{
gp_Pnt ptfixe;
if (!Einf.IsTangent(ptfixe))
{
const TopoDS_Face& FirstFace = Einf.FirstFace();
const TopoDS_Face& SecondFace = Einf.SecondFace();
S1 = myFMap.FindFromKey(FirstFace).Geometry();
S2 = myFMap.FindFromKey(SecondFace).Geometry();
Standard_Integer detrompeur = 0;
// Return FirstVertex and the tangent at this point.
TopoDS_Vertex FV = TopExp::FirstVertex(theEdge);
TopoDS_Vertex LV = TopExp::LastVertex(theEdge);
Standard_Real pmin = 0.;
Standard_Real prmfv = BRep_Tool::Parameter(FV, theEdge);
Standard_Real prmlv = BRep_Tool::Parameter(LV, theEdge);
gp_Pnt pfv, plv;
gp_Vec d1fv, d1lv, newd1;
C->D1(prmfv, pfv, d1fv);
C->D1(prmlv, plv, d1lv);
Standard_Real TolF1 = BRep_Tool::Tolerance(FirstFace);
Standard_Real TolF2 = BRep_Tool::Tolerance(SecondFace);
// Pass the tolerance of the face to project
GeomAPI_ProjectPointOnSurf proj1(pfv, S1, TolF1);
GeomAPI_ProjectPointOnSurf proj2(plv, S1, TolF1);
GeomAPI_ProjectPointOnSurf proj3(pfv, S2, TolF2);
GeomAPI_ProjectPointOnSurf proj4(plv, S2, TolF2);
if (proj1.IsDone() && proj2.IsDone())
{
if (proj1.LowerDistance() <= Precision::Confusion()
&& proj2.LowerDistance() <= Precision::Confusion())
{
detrompeur = 1;
}
}
if (proj3.IsDone() && proj4.IsDone())
{
if (proj3.LowerDistance() <= Precision::Confusion()
&& proj4.LowerDistance() <= Precision::Confusion())
{
detrompeur = 2;
}
}
gp_Dir TheDirExtr;
gp_Ax3 Axis;
Handle(Geom_Curve) TheNewCurve;
Standard_Boolean KPart = Standard_False;
if (S1->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface))
{
S1 = Handle(Geom_RectangularTrimmedSurface)::DownCast(S1)->BasisSurface();
}
if (S2->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface))
{
S2 = Handle(Geom_RectangularTrimmedSurface)::DownCast(S2)->BasisSurface();
}
Standard_Boolean PC1 = Standard_True; // KPart on S1
if (S1->DynamicType() == STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion)
&& S2->DynamicType() == STANDARD_TYPE(Geom_Plane))
{
KPart = Standard_True;
Axis = Handle(Geom_Plane)::DownCast(S2)->Position();
TheNewCurve = Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(S1)->BasisCurve();
TheDirExtr = Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(S1)->Direction();
}
else if (S2->DynamicType() == STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion)
&& S1->DynamicType() == STANDARD_TYPE(Geom_Plane))
{
KPart = Standard_True;
PC1 = Standard_False;
Axis = Handle(Geom_Plane)::DownCast(S1)->Position();
TheNewCurve = Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(S2)->BasisCurve();
TheDirExtr = Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(S2)->Direction();
}
Handle(Geom_Circle) aCirc;
if (KPart)
{ // very temporary on circles !!!
aCirc = Handle(Geom_Circle)::DownCast(TheNewCurve);
if (aCirc.IsNull())
KPart = Standard_False;
else
{
gp_Dir AxofCirc = aCirc->Position().Direction();
if (AxofCirc.IsParallel(Axis.Direction(), Precision::Angular()))
KPart = Standard_True;
else
KPart = Standard_False;
}
}
Standard_Integer imin;
GeomInt_IntSS i2s;
if (KPart)
{
// direct calculation of NewC
Standard_Real aLocalReal =
gp_Vec(aCirc->Circ().Location(), Axis.Location()).Dot(Axis.Direction());
Standard_Real Cos = TheDirExtr.Dot(Axis.Direction());
gp_Vec VV = (aLocalReal / Cos) * TheDirExtr;
newC = Handle(Geom_Curve)::DownCast(TheNewCurve->Translated(VV));
// it is possible to calculate PCurve
Handle(Geom2d_Line) L2d = new Geom2d_Line(gp_Pnt2d(0., aLocalReal / Cos), gp::DX2d());
if (PC1)
Einf.ChangeFirstPC() = L2d;
else
Einf.ChangeSecondPC() = L2d;
}
else
{
S1 = myFMap.FindFromKey(Einf.FirstFace()).Geometry();
S2 = myFMap.FindFromKey(Einf.SecondFace()).Geometry();
// PCurves are not calculated immediately for 2 reasons:
// 1 - If ProjLib should make an Approx, it is stupid to approximate the
// entire intersection curve.
// 2 - Additionally, if YaRev, there is a risk to not be SameRange.
i2s.Perform(S1,
S2,
Precision::Confusion(),
Standard_True,
Standard_False,
Standard_False);
if (!i2s.IsDone() || i2s.NbLines() <= 0)
{
errStat = Draft_EdgeRecomputation;
badShape = theEdge;
return;
}
Standard_Real Glob2Min = RealLast();
GeomAdaptor_Curve TheCurve;
Standard_Integer i, j; //,jmin;
if (i2s.Line(1)->DynamicType() != STANDARD_TYPE(Geom_BSplineCurve))
{
Standard_Real Dist2Min = RealLast();
imin = 0;
for (i = 1; i <= i2s.NbLines(); i++)
{
TheCurve.Load(i2s.Line(i));
Extrema_ExtPC myExtPC(pfv, TheCurve);
Standard_Real locpmin = 0.;
if (myExtPC.IsDone())
{
if (myExtPC.NbExt() >= 1)
{
Dist2Min = myExtPC.SquareDistance(1);
locpmin = myExtPC.Point(1).Parameter();
}
if (myExtPC.NbExt() == 2 && Dist2Min > Precision::SquareConfusion())
{
// to avoid incorrectly choosing the image
// of the first vertex of the initial edge
Standard_Real d1_2 = myExtPC.SquareDistance(1);
Standard_Real d2_2 = myExtPC.SquareDistance(2);
if (d1_2 > 1.21 * d2_2)
{
Dist2Min = myExtPC.SquareDistance(2);
locpmin = myExtPC.Point(2).Parameter();
}
else if (d2_2 > 1.21 * d1_2)
{
Dist2Min = myExtPC.SquareDistance(1);
locpmin = myExtPC.Point(1).Parameter();
}
else
{
Standard_Real pfvpar = myExtPC.Point(1).Parameter();
Standard_Real plvpar = myExtPC.Point(2).Parameter();
newC = i2s.Line(i);
gp_Pnt pfvprim, plvprim;
newC->D0(pfvpar, pfvprim);
newC->D0(plvpar, plvprim);
Handle(Geom_Surface) theSurf;
if (detrompeur == 1)
{
if (S1->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface))
S1 = Handle(Geom_RectangularTrimmedSurface)::DownCast(S1)->BasisSurface();
theSurf = S1;
}
else if (detrompeur == 2)
{
if (S2->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface))
S2 = Handle(Geom_RectangularTrimmedSurface)::DownCast(S2)->BasisSurface();
theSurf = S2;
}
if (detrompeur != 0 && detrompeur != 4)
{
Standard_Real ul = 0., vl = 0., uf = 0., vf = 0.;
Standard_Real ufprim = 0., ulprim = 0., vfprim = 0., vlprim = 0.;
if (theSurf->DynamicType() == STANDARD_TYPE(Geom_Plane))
{
gp_Pln pl = Handle(Geom_Plane)::DownCast(S2)->Pln();
ElSLib::Parameters(pl, plv, ul, vl);
ElSLib::Parameters(pl, pfv, uf, vf);
ElSLib::Parameters(pl, plvprim, ulprim, vlprim);
ElSLib::Parameters(pl, pfvprim, ufprim, vfprim);
}
else if (theSurf->DynamicType() == STANDARD_TYPE(Geom_CylindricalSurface))
{
gp_Cylinder cy =
Handle(Geom_CylindricalSurface)::DownCast(S2)->Cylinder();
ElSLib::Parameters(cy, plv, ul, vl);
ElSLib::Parameters(cy, pfv, uf, vf);
ElSLib::Parameters(cy, plvprim, ulprim, vlprim);
ElSLib::Parameters(cy, pfvprim, ufprim, vfprim);
}
else
detrompeur = 4;
if (detrompeur == 1 || detrompeur == 2)
{
gp_Vec2d v1((ul - ufprim), (vl - vfprim));
gp_Vec2d norm((vf - vfprim), (ufprim - uf));
gp_Vec2d v2((ulprim - ufprim), (vlprim - vfprim));
if ((v1.Dot(norm)) * (v2.Dot(norm)) < 0)
{
Dist2Min = myExtPC.SquareDistance(2);
locpmin = myExtPC.Point(2).Parameter();
}
}
}
}
}
if (myExtPC.NbExt() == 1 || myExtPC.NbExt() > 2 || detrompeur == 4)
{
Dist2Min = myExtPC.SquareDistance(1);
locpmin = myExtPC.Point(1).Parameter();
for (j = 2; j <= myExtPC.NbExt(); j++)
{
const Standard_Real Dist2 = myExtPC.SquareDistance(j);
if (Dist2 < Dist2Min)
{
Dist2Min = Dist2;
locpmin = myExtPC.Point(j).Parameter();
}
}
}
else if (myExtPC.NbExt() < 1)
{
Standard_Real dist1_2, dist2_2;
gp_Pnt p1b, p2b;
myExtPC.TrimmedSquareDistances(dist1_2, dist2_2, p1b, p2b);
if (dist1_2 < dist2_2)
{
Dist2Min = dist1_2;
locpmin = TheCurve.FirstParameter();
}
else
{
Dist2Min = dist2_2;
locpmin = TheCurve.LastParameter();
}
}
if (Dist2Min < Glob2Min)
{
Glob2Min = Dist2Min;
imin = i;
pmin = locpmin;
}
}
}
if (imin == 0)
{
errStat = Draft_EdgeRecomputation;
badShape = theEdge;
return;
}
newC = i2s.Line(imin);
newC->D1(pmin, pfv, newd1);
Standard_Boolean YaRev = d1fv.Dot(newd1) < 0.;
if (YaRev)
newC->Reverse();
if (i2s.HasLineOnS1(imin))
{
Einf.ChangeFirstPC() = i2s.LineOnS1(imin);
if (YaRev)
Einf.ChangeFirstPC()->Reverse();
}
if (i2s.HasLineOnS2(imin))
{
Einf.ChangeSecondPC() = i2s.LineOnS2(imin);
if (YaRev)
Einf.ChangeSecondPC()->Reverse();
}
} // if (i2s.Line(1)->DynamicType() != STANDARD_TYPE(Geom_BSplineCurve))
else // i2s.Line(1) is BSplineCurve
{
// Find the first curve to glue
TColGeom_SequenceOfCurve Candidates;
if (S1->DynamicType() == STANDARD_TYPE(Geom_CylindricalSurface)
|| S1->DynamicType() == STANDARD_TYPE(Geom_ConicalSurface))
{
for (i = 1; i <= i2s.NbLines(); i++)
{
const Handle(Geom_Curve)& aCurve = i2s.Line(i);
gp_Pnt Pnt = aCurve->Value(aCurve->FirstParameter());
GeomAPI_ProjectPointOnSurf projector(Pnt, S1, Precision::Confusion());
Standard_Real U, V;
projector.LowerDistanceParameters(U, V);
if (Abs(U) <= Precision::Confusion()
|| Abs(U - 2. * M_PI) <= Precision::Confusion())
Candidates.Append(aCurve);
else
{
Pnt = aCurve->Value(aCurve->LastParameter());
projector.Init(Pnt, S1, Precision::Confusion());
projector.LowerDistanceParameters(U, V);
if (Abs(U) <= Precision::Confusion()
|| Abs(U - 2. * M_PI) <= Precision::Confusion())
{
aCurve->Reverse();
Candidates.Append(aCurve);
}
}
}
if (Candidates.Length() == 0)
{
// errStat = Draft_EdgeRecomputation;
// badShape = TopoDS::Edge(ite.Key());
// return;
for (i = 1; i <= i2s.NbLines(); i++)
Candidates.Append(i2s.Line(i));
}
}
else
{
for (i = 1; i <= i2s.NbLines(); i++)
Candidates.Append(i2s.Line(i));
}
Handle(Geom_Curve) FirstCurve;
if (Candidates.Length() > 1)
{
Standard_Real DistMin = Precision::Infinite();
for (i = 1; i <= Candidates.Length(); i++)
{
Handle(Geom_Curve) aCurve = Candidates(i);
gp_Pnt Pnt = aCurve->Value(aCurve->FirstParameter());
const Standard_Real Dist = Pnt.Distance(pfv);
if (Dist - DistMin < -Precision::Confusion())
{
DistMin = Dist;
FirstCurve = aCurve;
}
}
}
else
FirstCurve = Candidates(1);
// Glueing
TColGeom_SequenceOfCurve Curves;
for (i = 1; i <= i2s.NbLines(); i++)
if (FirstCurve != i2s.Line(i))
Curves.Append(i2s.Line(i));
TColGeom_SequenceOfCurve ToGlue;
gp_Pnt EndPoint = FirstCurve->Value(FirstCurve->LastParameter());
Standard_Boolean added = Standard_True;
while (added)
{
added = Standard_False;
for (i = 1; i <= Curves.Length(); i++)
{
Handle(Geom_Curve) aCurve = Curves(i);
gp_Pnt pfirst, plast;
pfirst = aCurve->Value(aCurve->FirstParameter());
plast = aCurve->Value(aCurve->LastParameter());
if (pfirst.Distance(EndPoint) <= Precision::Confusion())
{
ToGlue.Append(aCurve);
EndPoint = plast;
Curves.Remove(i);
added = Standard_True;
break;
}
if (plast.Distance(EndPoint) <= Precision::Confusion())
{
aCurve->Reverse();
ToGlue.Append(aCurve);
EndPoint = pfirst;
Curves.Remove(i);
added = Standard_True;
break;
}
}
}
if (FirstCurve.IsNull())
{
errStat = Draft_EdgeRecomputation;
badShape = theEdge;
return;
}
GeomConvert_CompCurveToBSplineCurve Concat(
Handle(Geom_BSplineCurve)::DownCast(FirstCurve));
for (i = 1; i <= ToGlue.Length(); i++)
Concat.Add(Handle(Geom_BSplineCurve)::DownCast(ToGlue(i)),
Precision::Confusion(),
Standard_True);
newC = Concat.BSplineCurve();
TheCurve.Load(newC);
Extrema_ExtPC myExtPC(pfv, TheCurve);
Standard_Real Dist2Min = RealLast();
for (i = 1; i <= myExtPC.NbExt(); i++)
{
if (myExtPC.IsMin(i))
{
const Standard_Real Dist2 = myExtPC.SquareDistance(i);
if (Dist2 < Dist2Min)
{
Dist2Min = Dist2;
pmin = myExtPC.Point(i).Parameter();
}
}
}
newC->D1(pmin, pfv, newd1);
Standard_Boolean YaRev = d1fv.Dot(newd1) < 0.;
if (YaRev)
newC->Reverse();
/*
if (i2s.HasLineOnS1(imin)) {
Einf.ChangeFirstPC() = i2s.LineOnS1(imin);
if ( YaRev)
Einf.ChangeFirstPC()->Reverse();
}
if (i2s.HasLineOnS2(imin)) {
Einf.ChangeSecondPC() = i2s.LineOnS2(imin);
if ( YaRev)
Einf.ChangeSecondPC()->Reverse();
}
*/
} // else: i2s.NbLines() > 2 && S1 is Cylinder or Cone
Einf.Tolerance(Max(Einf.Tolerance(), i2s.TolReached3d()));
} // End step KPart
}
else
{ // case of tangency
const TopoDS_Face& F1 = Einf.FirstFace();
const TopoDS_Face& F2 = Einf.SecondFace();
Handle(Geom_Surface) aLocalS1 = myFMap.FindFromKey(F1).Geometry();
Handle(Geom_Surface) aLocalS2 = myFMap.FindFromKey(F2).Geometry();
if (aLocalS1.IsNull() || aLocalS2.IsNull())
{
errStat = Draft_EdgeRecomputation;
badShape = theEdge;
return;
}
if (aLocalS1->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface))
{
aLocalS1 = Handle(Geom_RectangularTrimmedSurface)::DownCast(aLocalS1)->BasisSurface();
}
if (aLocalS2->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface))
{
aLocalS2 = Handle(Geom_RectangularTrimmedSurface)::DownCast(aLocalS2)->BasisSurface();
}
gp_Dir dirextr;
// Standard_Boolean dirfound = Standard_False;
if (aLocalS1->DynamicType() == STANDARD_TYPE(Geom_CylindricalSurface))
{
gp_Cylinder cyl = Handle(Geom_CylindricalSurface)::DownCast(aLocalS1)->Cylinder();
dirextr = cyl.Axis().Direction();
// dirfound = Standard_True;
// see direction...
}
else if (aLocalS1->DynamicType() == STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion))
{
dirextr = Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(aLocalS1)->Direction();
// dirfound = Standard_True;
// see direction...
// Here it is possible to calculate PCurve.
Handle(Geom_SurfaceOfLinearExtrusion) SEL =
Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(aLocalS1);
Handle(Geom_Circle) GCir = Handle(Geom_Circle)::DownCast(SEL->BasisCurve());
if (!GCir.IsNull())
{
Standard_Real U = ElCLib::Parameter(GCir->Circ(), ptfixe);
Handle(Geom2d_Line) PC1 = new Geom2d_Line(gp_Pnt2d(U, 0.), gp::DY2d());
Einf.ChangeFirstPC() = PC1;
}
}
else if (aLocalS2->DynamicType() == STANDARD_TYPE(Geom_CylindricalSurface))
{
gp_Cylinder cyl = Handle(Geom_CylindricalSurface)::DownCast(aLocalS2)->Cylinder();
dirextr = cyl.Axis().Direction();
// dirfound = Standard_True;
// see direction...
}
else if (aLocalS2->DynamicType() == STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion))
{
dirextr = Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(aLocalS2)->Direction();
// dirfound = Standard_True;
// see direction...
// Here it is possible to calculate PCurve.
Handle(Geom_SurfaceOfLinearExtrusion) SEL =
Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(aLocalS2);
Handle(Geom_Circle) GCir = Handle(Geom_Circle)::DownCast(SEL->BasisCurve());
if (!GCir.IsNull())
{
Standard_Real U = ElCLib::Parameter(GCir->Circ(), ptfixe);
Handle(Geom2d_Line) PC2 = new Geom2d_Line(gp_Pnt2d(U, 0.), gp::DY2d());
Einf.ChangeSecondPC() = PC2;
}
}
newC = new Geom_Line(ptfixe, dirextr);
gp_Pnt pfv;
gp_Vec d1fv, newd1;
C->D1(0., pfv, d1fv);
newC->D1(0., pfv, newd1);
Standard_Boolean YaRev = d1fv.Dot(newd1) < 0.;
if (YaRev)
{
newC->Reverse();
if (!Einf.FirstPC().IsNull())
{
Einf.ChangeFirstPC()->Reverse();
}
if (!Einf.SecondPC().IsNull())
{
Einf.ChangeSecondPC()->Reverse();
}
}
}
Handle(Geom_TrimmedCurve) T = Handle(Geom_TrimmedCurve)::DownCast(newC);
if (!T.IsNull())
newC = T->BasisCurve();
Einf.ChangeGeometry() = newC;
}
else if (!Einf.NewGeometry())
{
// set existing curve 3D
Handle(Geom_TrimmedCurve) T = Handle(Geom_TrimmedCurve)::DownCast(C);
if (!T.IsNull())
C = T->BasisCurve();
Einf.ChangeGeometry() = C;
}
}
// Calculate new vertices.
Handle(GeomAdaptor_Curve) HAC = new GeomAdaptor_Curve;
Handle(GeomAdaptor_Surface) HAS = new GeomAdaptor_Surface;
for (Standard_Integer ii = 1; ii <= myVMap.Extent(); ii++)
{
GeomAdaptor_Curve& AC = *HAC;
GeomAdaptor_Surface& AS = *HAS;
const TopoDS_Vertex& TVV = myVMap.FindKey(ii);
Draft_VertexInfo& Vinf = myVMap.ChangeFromIndex(ii);
if (!Choose(myFMap, myEMap, TVV, Vinf, AC, AS))
{
// no concerted edge => alignment of two consecutive edges.
gp_Pnt pvt;
Vinf.ChangeGeometry() = pvt;
Vinf.InitEdgeIterator();
if (Vinf.MoreEdge())
{
const TopoDS_Edge& Edg1 = Vinf.Edge();
// const Draft_EdgeInfo& Einf1 = myEMap(Edg1);
Draft_EdgeInfo& Einf1 = myEMap.ChangeFromKey(Edg1);
gp_Pnt vtori = BRep_Tool::Pnt(TVV);
// Einf1.Geometry()->D0(Vinf.Parameter(Edg1), pvt);
GeomAPI_ProjectPointOnCurve Projector(vtori, Einf1.Geometry()); // patch
pvt = Projector.NearestPoint();
#ifdef OCCT_DEBUG
static Standard_Integer VertexRecomp = 1;
if (VertexRecomp != 0)
{
std::cout << "pori :" << vtori.X() << " " << vtori.Y() << " " << vtori.Z() << std::endl;
std::cout << " Edg 1 :" << Vinf.Parameter(Edg1) << std::endl;
std::cout << "pvt :" << pvt.X() << " " << pvt.Y() << " " << pvt.Z() << std::endl;
}
#endif
Standard_Real dion = pvt.SquareDistance(vtori);
Vinf.NextEdge();
if (Vinf.MoreEdge())
{
const TopoDS_Edge& Edg2 = Vinf.Edge();
// const Draft_EdgeInfo& Einf2 = myEMap(Edg2);
Draft_EdgeInfo& Einf2 = myEMap.ChangeFromKey(Edg2);
// Standard_Real f;
gp_Pnt opvt;
Einf2.Geometry()->D0(Vinf.Parameter(Edg2), opvt);
#ifdef OCCT_DEBUG
if (VertexRecomp != 0)
{
std::cout << " Edg 2 :" << Vinf.Parameter(Vinf.Edge()) << std::endl;
std::cout << "opvt " << opvt.X() << " " << opvt.Y() << " " << opvt.Z() << std::endl;
}
#endif
if (opvt.SquareDistance(vtori) < dion)
{
pvt = opvt;
}
// Vinf.ChangeParameter(Edg2) = Parameter(Einf2.Geometry(), pvt);
Standard_Integer done;
Standard_Real param = Parameter(Einf2.Geometry(), pvt, done);
if (done != 0)
{
Handle(Geom_Surface) S1 = myFMap.FindFromKey(Einf2.FirstFace()).Geometry();
Handle(Geom_Surface) S2 = myFMap.FindFromKey(Einf2.SecondFace()).Geometry();
Vinf.ChangeParameter(Edg2) =
SmartParameter(Einf2, BRep_Tool::Tolerance(Edg2), pvt, done, S1, S2);
}
else
Vinf.ChangeParameter(Edg2) = param;
}
Vinf.ChangeGeometry() = pvt;
// Vinf.ChangeParameter(Edg1) = Parameter(Einf1.Geometry(), pvt);
Standard_Integer done;
Standard_Real param = Parameter(Einf1.Geometry(), pvt, done);
if (done != 0)
{
Handle(Geom_Surface) S1 = myFMap.FindFromKey(Einf1.FirstFace()).Geometry();
Handle(Geom_Surface) S2 = myFMap.FindFromKey(Einf1.SecondFace()).Geometry();
Vinf.ChangeParameter(Edg1) =
SmartParameter(Einf1, BRep_Tool::Tolerance(Edg1), pvt, done, S1, S2);
}
else
Vinf.ChangeParameter(Edg1) = param;
continue;
}
errStat = Draft_VertexRecomputation;
badShape = TVV;
return;
}
IntCurveSurface_HInter myintcs;
myintcs.Perform(HAC, HAS);
if (!myintcs.IsDone())
{
errStat = Draft_VertexRecomputation;
badShape = TVV;
return;
}
gp_Pnt vtori = BRep_Tool::Pnt(TVV);
gp_Pnt pvt;
Standard_Integer nbsol = myintcs.NbPoints();
if (nbsol <= 0)
{
Extrema_ExtCS extr(AC, AS, Precision::PConfusion(), Precision::PConfusion());
if (!extr.IsDone() || extr.NbExt() == 0)
{
errStat = Draft_VertexRecomputation;
badShape = TVV;
return;
}
Standard_Real disref = RealLast();
Standard_Integer iref = 0;
Extrema_POnCurv Pc;
Extrema_POnSurf Ps;
for (Standard_Integer i = 1; i <= extr.NbExt(); i++)
{
extr.Points(i, Pc, Ps);
Standard_Real distemp = Pc.Value().SquareDistance(vtori);
if (distemp < disref)
{
disref = distemp;
iref = i;
}
}
extr.Points(iref, Pc, Ps);
pvt = Pc.Value();
}
else
{
Standard_Real disref = RealLast();
Standard_Integer iref = 0;
for (Standard_Integer i = 1; i <= nbsol; i++)
{
Standard_Real distemp = myintcs.Point(i).Pnt().SquareDistance(vtori);
if (distemp < disref)
{
disref = distemp;
iref = i;
}
}
pvt = myintcs.Point(iref).Pnt();
}
Vinf.ChangeGeometry() = pvt;
for (Vinf.InitEdgeIterator(); Vinf.MoreEdge(); Vinf.NextEdge())
{
const TopoDS_Edge& Edg = Vinf.Edge();
Standard_Real initpar = Vinf.Parameter(Edg);
// const Draft_EdgeInfo& Einf = myEMap(Edg);
Draft_EdgeInfo& Einf = myEMap.ChangeFromKey(Edg);
// Vinf.ChangeParameter(Edg) = Parameter(Einf.Geometry(),pvt);
Standard_Integer done;
Standard_Real param = Parameter(Einf.Geometry(), pvt, done);
if (done != 0)
{
Handle(Geom_Surface) S1 = myFMap.FindFromKey(Einf.FirstFace()).Geometry();
Handle(Geom_Surface) S2 = myFMap.FindFromKey(Einf.SecondFace()).Geometry();
Vinf.ChangeParameter(Edg) =
SmartParameter(Einf, BRep_Tool::Tolerance(Edg), pvt, done, S1, S2);
}
else
{
if (Abs(initpar - param) > Precision::PConfusion())
{
Standard_Real f, l;
TopLoc_Location Loc;
const Handle(Geom_Curve)& aC = BRep_Tool::Curve(Edg, Loc, f, l);
if (aC->DynamicType() == STANDARD_TYPE(Geom_TrimmedCurve))
{
Einf.SetNewGeometry(Standard_True);
}
}
Vinf.ChangeParameter(Edg) = param;
}
}
}
}
// small loop of validation/protection
for (Standard_Integer i = 1; i <= myEMap.Extent(); i++)
{
const TopoDS_Edge& edg = TopoDS::Edge(myEMap.FindKey(i));
TopoDS_Vertex Vf, Vl;
TopExp::Vertices(edg, Vf, Vl);
if (edg.Orientation() == TopAbs_REVERSED)
{
Vf.Reverse();
Vl.Reverse();
}
if (myVMap.Contains(Vf) && myVMap.Contains(Vl))
{
// Here, we compare directions of the source edge (from input shape)
// and corresponding selected part of the intersection edge.
// If these directions are opposite then we reverse intersection edge
// and recompute corresponding vertex-parameters.
Standard_Real aParF = myVMap.ChangeFromKey(Vf).Parameter(edg);
Standard_Real aParL = myVMap.ChangeFromKey(Vl).Parameter(edg);
if (aParL < aParF)
{
Draft_EdgeInfo& aEinf = myEMap.ChangeFromKey(edg);
TopLoc_Location aLoc;
Standard_Real aF = 0.0, aL = 0.0;
const Handle(Geom_Curve) aSCurve = BRep_Tool::Curve(edg, aF, aL);
Handle(Geom_Curve) anIntCurv = aEinf.Geometry();
gp_Pnt aPf, aPl;
gp_Vec aDirNF, aDirNL, aDirOF, aDirOL;
aSCurve->D1(BRep_Tool::Parameter(Vf, edg), aPf, aDirOF);
aSCurve->D1(BRep_Tool::Parameter(Vl, edg), aPl, aDirOL);
anIntCurv->D1(aParF, aPf, aDirNF);
anIntCurv->D1(aParL, aPl, aDirNL);
Standard_Real aSqMagn = aDirNF.SquareMagnitude();
if (aSqMagn > Precision::SquareConfusion())
aDirNF.Divide(sqrt(aSqMagn));
aSqMagn = aDirNL.SquareMagnitude();
if (aSqMagn > Precision::SquareConfusion())
aDirNL.Divide(sqrt(aSqMagn));
aSqMagn = aDirOF.SquareMagnitude();
if (aSqMagn > Precision::SquareConfusion())
aDirOF.Divide(sqrt(aSqMagn));
aSqMagn = aDirOL.SquareMagnitude();
if (aSqMagn > Precision::SquareConfusion())
aDirOL.Divide(sqrt(aSqMagn));
const Standard_Real aCosF = aDirNF.Dot(aDirOF), aCosL = aDirNL.Dot(aDirOL);
const Standard_Real aCosMax = Abs(aCosF) > Abs(aCosL) ? aCosF : aCosL;
if (aCosMax < 0.0)
{
Standard_Integer anErr = 0;
anIntCurv->Reverse();
aEinf.ChangeGeometry() = anIntCurv;
Standard_Real aPar = Parameter(aEinf.Geometry(), aPf, anErr);
if (anErr == 0)
{
myVMap.ChangeFromKey(Vf).ChangeParameter(edg) = aPar;
}
aPar = Parameter(aEinf.Geometry(), aPl, anErr);
if (anErr == 0)
{
myVMap.ChangeFromKey(Vl).ChangeParameter(edg) = aPar;
}
}
}
}
Standard_Real pf, pl, tolerance;
if (!NewParameter(Vf, edg, pf, tolerance))
{
pf = BRep_Tool::Parameter(Vf, edg);
}
if (!NewParameter(Vl, edg, pl, tolerance))
{
pl = BRep_Tool::Parameter(Vl, edg);
}
if (pl <= pf)
{
// const Handle(Geom_Curve) gc=ite.Value().Geometry();
// if (!gc.IsNull()) {
// pl = gc->LastParameter();
// pf = gc->FirstParameter();
// }
Handle(Geom_Curve) theCurve = myEMap.FindFromKey(edg).Geometry();
if (theCurve->IsClosed())
{
// pf >= pl
Standard_Real FirstPar = theCurve->FirstParameter(), LastPar = theCurve->LastParameter();
constexpr Standard_Real pconf = Precision::PConfusion();
if (Abs(pf - LastPar) <= pconf)
pf = FirstPar;
else if (Abs(pl - FirstPar) <= pconf)
pl = LastPar;
if (pl <= pf)
{
pl += (LastPar - FirstPar);
}
}
if (pl <= pf)
{
errStat = Draft_EdgeRecomputation;
badShape = edg;
return;
}
}
if (myVMap.Contains(Vf))
myVMap.ChangeFromKey(Vf).ChangeParameter(edg) = pf;
if (myVMap.Contains(Vl))
myVMap.ChangeFromKey(Vl).ChangeParameter(edg) = pl;
}
}
//=================================================================================================
Handle(Geom_Surface) Draft_Modification::NewSurface(const Handle(Geom_Surface)& S,
const TopAbs_Orientation Oris,
const gp_Dir& Direction,
const Standard_Real Angle,
const gp_Pln& NeutralPlane)
{
Handle(Geom_Surface) NewS;
Handle(Standard_Type) TypeS = S->DynamicType();
if (TypeS == STANDARD_TYPE(Geom_Plane))
{
gp_Pln Pl = Handle(Geom_Plane)::DownCast(S)->Pln();
gp_Ax1 Axe;
Standard_Real Theta;
if (FindRotation(Pl, Oris, Direction, Angle, NeutralPlane, Axe, Theta))
{
if (Abs(Theta) > Precision::Angular())
{
NewS = Handle(Geom_Surface)::DownCast(S->Rotated(Axe, Theta));
}
else
{
NewS = S;
}
}
}
else if (TypeS == STANDARD_TYPE(Geom_CylindricalSurface))
{
Standard_Real testdir = Direction.Dot(NeutralPlane.Axis().Direction());
if (Abs(testdir) <= 1. - Precision::Angular())
{
#ifdef OCCT_DEBUG
std::cout << "NewSurfaceCyl:Draft_Direction_and_Neutral_Perpendicular" << std::endl;
#endif
return NewS;
}
gp_Cylinder Cy = Handle(Geom_CylindricalSurface)::DownCast(S)->Cylinder();
testdir = Direction.Dot(Cy.Axis().Direction());
if (Abs(testdir) <= 1. - Precision::Angular())
{
#ifdef OCCT_DEBUG
std::cout << "NewSurfaceCyl:Draft_Direction_and_Cylinder_Perpendicular" << std::endl;
#endif
return NewS;
}
if (Abs(Angle) > Precision::Angular())
{
IntAna_QuadQuadGeo i2s;
i2s.Perform(NeutralPlane, Cy, Precision::Angular(), Precision::Confusion());
Standard_Boolean isIntDone = i2s.IsDone();
if (i2s.TypeInter() == IntAna_Ellipse)
{
const gp_Elips anEl = i2s.Ellipse(1);
const Standard_Real aMajorR = anEl.MajorRadius();
const Standard_Real aMinorR = anEl.MinorRadius();
isIntDone = (aMajorR < 100000.0 * aMinorR);
}
if (!isIntDone || i2s.TypeInter() != IntAna_Circle)
{
#ifdef OCCT_DEBUG
std::cout << "NewSurfaceCyl:Draft_Intersection_Neutral_Cylinder_NotDone" << std::endl;
#endif
return NewS;
}
gp_Ax3 axcone = Cy.Position();
// Pb : Where is the material???
Standard_Real alpha = Angle;
Standard_Boolean direct(axcone.Direct());
if ((direct && Oris == TopAbs_REVERSED) || (!direct && Oris == TopAbs_FORWARD))
{
alpha = -alpha;
}
gp_Pnt Center = i2s.Circle(1).Location();
if (testdir < 0.)
{
alpha = -alpha;
}
Standard_Real Z = ElCLib::LineParameter(Cy.Axis(), Center);
Standard_Real Rad = Cy.Radius() + Z * Tan(alpha);
if (Rad < 0.)
{
Rad = -Rad;
}
else
{
alpha = -alpha;
}
gp_Cone co(axcone, alpha, Rad);
NewS = new Geom_ConicalSurface(co);
}
else
{
NewS = S;
}
}
else if (TypeS == STANDARD_TYPE(Geom_ConicalSurface))
{
Standard_Real testdir = Direction.Dot(NeutralPlane.Axis().Direction());
if (Abs(testdir) <= 1. - Precision::Angular())
{
#ifdef OCCT_DEBUG
std::cout << "NewSurfaceCone:Draft_Direction_and_Neutral_Perpendicular" << std::endl;
#endif
return NewS;
}
gp_Cone Co1 = Handle(Geom_ConicalSurface)::DownCast(S)->Cone();
testdir = Direction.Dot(Co1.Axis().Direction());
if (Abs(testdir) <= 1. - Precision::Angular())
{
#ifdef OCCT_DEBUG
std::cout << "NewSurfaceCone:Draft_Direction_and_Cone_Perpendicular" << std::endl;
#endif
return NewS;
}
IntAna_QuadQuadGeo i2s;
i2s.Perform(NeutralPlane, Co1, Precision::Angular(), Precision::Confusion());
if (!i2s.IsDone() || i2s.TypeInter() != IntAna_Circle)
{
#ifdef OCCT_DEBUG
std::cout << "NewSurfaceCone:Draft_Intersection_Neutral_Conical_NotDone" << std::endl;
#endif
return NewS;
}
gp_Ax3 axcone = Co1.Position();
// Pb : Where is the material???
Standard_Real alpha = Angle;
Standard_Boolean direct(axcone.Direct());
if ((direct && Oris == TopAbs_REVERSED) || (!direct && Oris == TopAbs_FORWARD))
{
alpha = -alpha;
}
gp_Pnt Center = i2s.Circle(1).Location();
if (Abs(Angle) > Precision::Angular())
{
if (testdir < 0.)
{
alpha = -alpha;
}
Standard_Real Z = ElCLib::LineParameter(Co1.Axis(), Center);
Standard_Real Rad = i2s.Circle(1).Radius() + Z * Tan(alpha);
if (Rad < 0.)
{
Rad = -Rad;
}
else
{
alpha = -alpha;
}
if (Abs(alpha - Co1.SemiAngle()) < Precision::Angular())
{
NewS = S;
}
else
{
gp_Cone co(axcone, alpha, Rad);
NewS = new Geom_ConicalSurface(co);
}
}
else
{
NewS = new Geom_CylindricalSurface(gp_Cylinder(axcone, i2s.Circle(1).Radius()));
}
}
else
{
#ifdef OCCT_DEBUG
std::cout << "NewSurface:Draft_SurfNotYetImplemented" << std::endl;
#endif
}
return NewS;
}
//=================================================================================================
Handle(Geom_Curve) Draft_Modification::NewCurve(const Handle(Geom_Curve)& C,
const Handle(Geom_Surface)& S,
const TopAbs_Orientation Oris,
const gp_Dir& Direction,
const Standard_Real Angle,
const gp_Pln& NeutralPlane,
const Standard_Boolean)
{
Handle(Geom_Curve) NewC;
Handle(Standard_Type) TypeS = S->DynamicType();
if (TypeS == STANDARD_TYPE(Geom_Plane))
{
gp_Pln Pl = Handle(Geom_Plane)::DownCast(S)->Pln();
gp_Ax1 Axe;
Standard_Real Theta;
if (FindRotation(Pl, Oris, Direction, Angle, NeutralPlane, Axe, Theta))
{
if (Abs(Theta) > Precision::Angular())
{
NewC = Handle(Geom_Curve)::DownCast(C->Rotated(Axe, Theta));
}
else
{
NewC = C;
}
}
return NewC;
}
if (C->DynamicType() != STANDARD_TYPE(Geom_Line))
{
return NewC;
}
gp_Lin lin = Handle(Geom_Line)::DownCast(C)->Lin();
// Standard_Real testdir = Direction.Dot(lin.Direction());
// if (Abs(testdir) <= 1.-Precision::Angular()) {
// return NewC;
// }
gp_Dir Norm;
if (TypeS == STANDARD_TYPE(Geom_CylindricalSurface))
{
Standard_Real U, V;
gp_Vec d1u, d1v;
gp_Pnt pbid;
gp_Cylinder Cy = Handle(Geom_CylindricalSurface)::DownCast(S)->Cylinder();
ElSLib::Parameters(Cy, lin.Location(), U, V);
ElSLib::D1(U, V, Cy, pbid, d1u, d1v);
Norm = d1u.Crossed(d1v);
}
else if (TypeS == STANDARD_TYPE(Geom_ConicalSurface))
{
Standard_Real U, V;
gp_Vec d1u, d1v;
gp_Pnt pbid;
gp_Cone Co = Handle(Geom_ConicalSurface)::DownCast(S)->Cone();
ElSLib::Parameters(Co, lin.Location(), U, V);
ElSLib::D1(U, V, Co, pbid, d1u, d1v);
Norm = d1u.Crossed(d1v);
}
IntAna_IntConicQuad ilipl(lin, NeutralPlane, Precision::Angular());
if (ilipl.IsDone() && ilipl.NbPoints() != 0)
{
if (Oris == TopAbs_REVERSED)
{
Norm.Reverse();
}
gp_Ax1 axrot(ilipl.Point(1), Norm.Crossed(Direction));
gp_Lin lires = gp_Lin(gp_Ax1(ilipl.Point(1), Direction)).Rotated(axrot, Angle);
if (lires.Direction().Dot(lin.Direction()) < 0.)
{
lires.Reverse();
}
NewC = new Geom_Line(lires);
}
return NewC;
}
//=================================================================================================
static Standard_Boolean Choose(const Draft_IndexedDataMapOfFaceFaceInfo& theFMap,
Draft_IndexedDataMapOfEdgeEdgeInfo& theEMap,
const TopoDS_Vertex& Vtx,
Draft_VertexInfo& Vinf,
GeomAdaptor_Curve& AC,
GeomAdaptor_Surface& AS)
{
gp_Vec tgref;
Vinf.InitEdgeIterator();
// Find a regular edge with null SecondFace
while (Vinf.MoreEdge())
{
const TopoDS_Edge& E1 = Vinf.Edge();
const Draft_EdgeInfo& Einf1 = theEMap.FindFromKey(E1);
if (Einf1.SecondFace().IsNull())
{
break;
}
else
{
GeomAbs_Shape te = BRep_Tool::Continuity(E1, Einf1.FirstFace(), Einf1.SecondFace());
if (te >= GeomAbs_G1)
{
break;
}
}
Vinf.NextEdge();
}
if (!Vinf.MoreEdge())
{ // take the first edge
Vinf.InitEdgeIterator();
}
const TopoDS_Edge& Eref = Vinf.Edge();
// const Draft_EdgeInfo& Einf = theEMap(Eref);
Draft_EdgeInfo& Einf = theEMap.ChangeFromKey(Eref);
AC.Load(Einf.Geometry());
Standard_Real f, l, prm;
TopLoc_Location Loc;
Handle(Geom_Curve) C = BRep_Tool::Curve(Eref, Loc, f, l);
C = Handle(Geom_Curve)::DownCast(C->Transformed(Loc.Transformation()));
gp_Pnt ptbid;
// prm = Parameter(C,BRep_Tool::Pnt(Vtx));
Standard_Integer done;
Standard_Real param = Parameter(C, BRep_Tool::Pnt(Vtx), done);
if (done != 0)
{
Handle(Geom_Surface) S1 = theFMap.FindFromKey(Einf.FirstFace()).Geometry();
Handle(Geom_Surface) S2 = theFMap.FindFromKey(Einf.SecondFace()).Geometry();
prm = SmartParameter(Einf, BRep_Tool::Tolerance(Eref), BRep_Tool::Pnt(Vtx), done, S1, S2);
}
else
prm = param;
C->D1(prm, ptbid, tgref);
Vinf.InitEdgeIterator();
while (Vinf.MoreEdge())
{
// Find a non tangent edge
const TopoDS_Edge& Edg = Vinf.Edge();
if (!Edg.IsSame(Eref))
{
// const Draft_EdgeInfo& Einfo = theEMap(Edg);
Draft_EdgeInfo& Einfo = theEMap.ChangeFromKey(Edg);
if (!Einfo.SecondFace().IsNull()
&& BRep_Tool::Continuity(Edg, Einfo.FirstFace(), Einfo.SecondFace()) <= GeomAbs_C0)
{
C = BRep_Tool::Curve(Edg, Loc, f, l);
C = Handle(Geom_Curve)::DownCast(C->Transformed(Loc.Transformation()));
// prm = Parameter(C,BRep_Tool::Pnt(Vtx));
Standard_Integer anewdone;
Standard_Real anewparam = Parameter(C, BRep_Tool::Pnt(Vtx), anewdone);
if (anewdone != 0)
{
Handle(Geom_Surface) S1 = theFMap.FindFromKey(Einfo.FirstFace()).Geometry();
Handle(Geom_Surface) S2 = theFMap.FindFromKey(Einfo.SecondFace()).Geometry();
prm =
SmartParameter(Einfo, BRep_Tool::Tolerance(Edg), BRep_Tool::Pnt(Vtx), anewdone, S1, S2);
}
else
prm = anewparam;
gp_Vec tg;
C->D1(prm, ptbid, tg);
if (tg.CrossMagnitude(tgref) > Precision::Confusion())
{
break;
}
}
}
Vinf.NextEdge();
}
if (!Vinf.MoreEdge())
{
return Standard_False;
}
const Draft_EdgeInfo& Einf2 = theEMap.FindFromKey(Vinf.Edge());
if (!Einf.SecondFace().IsNull())
{
if (Einf2.FirstFace().IsSame(Einf.FirstFace()) || Einf2.FirstFace().IsSame(Einf.SecondFace()))
{
AS.Load(theFMap.FindFromKey(Einf2.SecondFace()).Geometry());
}
else
{
AS.Load(theFMap.FindFromKey(Einf2.FirstFace()).Geometry());
}
}
else
{
if (Einf2.FirstFace().IsSame(Einf.FirstFace()))
{
AS.Load(theFMap.FindFromKey(Einf2.SecondFace()).Geometry());
}
else
{
AS.Load(theFMap.FindFromKey(Einf2.FirstFace()).Geometry());
}
}
return Standard_True;
}
//=================================================================================================
static Standard_Real Parameter(const Handle(Geom_Curve)& C, const gp_Pnt& P, Standard_Integer& done)
{
done = 0;
Handle(Geom_Curve) cbase = C;
Handle(Standard_Type) ctyp = C->DynamicType();
if (ctyp == STANDARD_TYPE(Geom_TrimmedCurve))
{
cbase = Handle(Geom_TrimmedCurve)::DownCast(C)->BasisCurve();
ctyp = cbase->DynamicType();
}
Standard_Real param;
if (ctyp == STANDARD_TYPE(Geom_Line))
{
param = ElCLib::Parameter(Handle(Geom_Line)::DownCast(cbase)->Lin(), P);
}
else if (ctyp == STANDARD_TYPE(Geom_Circle))
{
param = ElCLib::Parameter(Handle(Geom_Circle)::DownCast(cbase)->Circ(), P);
if (Abs(2. * M_PI - param) <= Epsilon(2. * M_PI))
{
param = 0.;
}
}
else if (ctyp == STANDARD_TYPE(Geom_Ellipse))
{
param = ElCLib::Parameter(Handle(Geom_Ellipse)::DownCast(cbase)->Elips(), P);
if (Abs(2. * M_PI - param) <= Epsilon(2. * M_PI))
{
param = 0.;
}
}
else if (ctyp == STANDARD_TYPE(Geom_Parabola))
{
param = ElCLib::Parameter(Handle(Geom_Parabola)::DownCast(cbase)->Parab(), P);
}
else if (ctyp == STANDARD_TYPE(Geom_Hyperbola))
{
param = ElCLib::Parameter(Handle(Geom_Hyperbola)::DownCast(cbase)->Hypr(), P);
}
else
{
GeomAdaptor_Curve TheCurve(C);
Extrema_ExtPC myExtPC(P, TheCurve);
if (!myExtPC.IsDone())
{
throw Standard_Failure("Draft_Modification_1::Parameter: ExtremaPC not done.");
}
if (myExtPC.NbExt() >= 1)
{
Standard_Real Dist2, Dist2Min = myExtPC.SquareDistance(1);
Standard_Integer j, jmin = 1;
for (j = 2; j <= myExtPC.NbExt(); j++)
{
Dist2 = myExtPC.SquareDistance(j);
if (Dist2 < Dist2Min)
{
Dist2Min = Dist2;
jmin = j;
}
}
param = myExtPC.Point(jmin).Parameter();
}
else
{
Standard_Real dist1_2, dist2_2;
gp_Pnt p1b, p2b;
myExtPC.TrimmedSquareDistances(dist1_2, dist2_2, p1b, p2b);
if (dist1_2 < dist2_2)
{
done = -1;
param = TheCurve.FirstParameter();
}
else
{
done = 1;
param = TheCurve.LastParameter();
}
}
if (cbase->IsPeriodic())
{
Standard_Real Per = cbase->Period();
Standard_Real Tolp = Precision::Parametric(Precision::Confusion());
if (Abs(Per - param) <= Tolp)
{
param = 0.;
}
}
}
return param;
}
//=================================================================================================
static Standard_Real SmartParameter(Draft_EdgeInfo& Einf,
const Standard_Real EdgeTol,
const gp_Pnt& Pnt,
const Standard_Integer sign,
const Handle(Geom_Surface)& S1,
const Handle(Geom_Surface)& S2)
{
Handle(Geom2d_Curve) NewC2d;
constexpr Standard_Real Tol = Precision::Confusion();
Standard_Real Etol = EdgeTol;
Handle(Geom2d_Curve) pcu1 = Einf.FirstPC();
Handle(Geom2d_Curve) pcu2 = Einf.SecondPC();
if (pcu1.IsNull())
{
Handle(Geom_Curve) theCurve = Einf.Geometry();
pcu1 = GeomProjLib::Curve2d(theCurve,
theCurve->FirstParameter(),
theCurve->LastParameter(),
S1,
Etol);
Einf.ChangeFirstPC() = pcu1;
}
if (pcu2.IsNull())
{
Handle(Geom_Curve) theCurve = Einf.Geometry();
pcu2 = GeomProjLib::Curve2d(theCurve,
theCurve->FirstParameter(),
theCurve->LastParameter(),
S2,
Etol);
Einf.ChangeSecondPC() = pcu2;
}
GeomAPI_ProjectPointOnSurf Projector(Pnt, S1);
Standard_Real U, V;
Projector.LowerDistanceParameters(U, V);
NewC2d = Einf.FirstPC();
if (NewC2d->DynamicType() == STANDARD_TYPE(Geom2d_TrimmedCurve))
NewC2d = (Handle(Geom2d_TrimmedCurve)::DownCast(NewC2d))->BasisCurve();
gp_Pnt2d P2d(U, V);
Geom2dAPI_ProjectPointOnCurve Projector2d(P2d, NewC2d);
if (Projector2d.NbPoints() == 0 || Projector2d.LowerDistance() > Tol)
{
Handle(Geom2d_BSplineCurve) BCurve;
if (NewC2d->DynamicType() != STANDARD_TYPE(Geom2d_BSplineCurve))
BCurve = Geom2dConvert::CurveToBSplineCurve(NewC2d);
else
BCurve = Handle(Geom2d_BSplineCurve)::DownCast(NewC2d);
if (sign == -1)
{
TColgp_Array1OfPnt2d PntArray(1, 2);
PntArray(1) = P2d;
PntArray(2) = BCurve->Pole(1);
Handle(Geom2d_BezierCurve) Patch = new Geom2d_BezierCurve(PntArray);
Geom2dConvert_CompCurveToBSplineCurve Concat(BCurve, Convert_QuasiAngular);
Concat.Add(Patch, Tol, Standard_False);
BCurve = Concat.BSplineCurve();
}
else
{
TColgp_Array1OfPnt2d PntArray(1, 2);
PntArray(1) = BCurve->Pole(BCurve->NbPoles());
PntArray(2) = P2d;
Handle(Geom2d_BezierCurve) Patch = new Geom2d_BezierCurve(PntArray);
Geom2dConvert_CompCurveToBSplineCurve Concat(BCurve, Convert_QuasiAngular);
Concat.Add(Patch, Tol, Standard_True);
BCurve = Concat.BSplineCurve();
}
NewC2d = BCurve;
}
Einf.ChangeFirstPC() = NewC2d;
Handle(Geom2dAdaptor_Curve) hcur = new Geom2dAdaptor_Curve(NewC2d);
Handle(GeomAdaptor_Surface) hsur = new GeomAdaptor_Surface(S1);
Adaptor3d_CurveOnSurface cons(hcur, hsur);
Handle(Adaptor3d_CurveOnSurface) hcons = new Adaptor3d_CurveOnSurface(cons);
Handle(GeomAdaptor_Surface) hsur2 = new GeomAdaptor_Surface(S2);
Handle(ProjLib_HCompProjectedCurve) HProjector =
new ProjLib_HCompProjectedCurve(hsur2, hcons, Tol, Tol);
Standard_Real Udeb, Ufin;
HProjector->Bounds(1, Udeb, Ufin);
Standard_Integer MaxSeg = 20 + HProjector->NbIntervals(GeomAbs_C3);
Approx_CurveOnSurface appr(HProjector, hsur2, Udeb, Ufin, Tol);
appr.Perform(MaxSeg, 10, GeomAbs_C1, Standard_False, Standard_False);
Einf.ChangeSecondPC() = appr.Curve2d();
Einf.ChangeGeometry() = appr.Curve3d();
Einf.SetNewGeometry(Standard_True);
if (sign == -1)
return Einf.Geometry()->FirstParameter();
else
return Einf.Geometry()->LastParameter();
}
//=================================================================================================
static TopAbs_Orientation Orientation(const TopoDS_Shape& S, const TopoDS_Face& F)
{
//
// change porting NT
//
TopExp_Explorer expl;
expl.Init(S, TopAbs_FACE);
while (expl.More())
{
if (TopoDS::Face(expl.Current()).IsSame(F))
{
return expl.Current().Orientation();
}
expl.Next();
}
return TopAbs_FORWARD;
}
//=================================================================================================
static Standard_Boolean FindRotation(const gp_Pln& Pl,
const TopAbs_Orientation Oris,
const gp_Dir& Direction,
const Standard_Real Angle,
const gp_Pln& NeutralPlane,
gp_Ax1& Axe,
Standard_Real& theta)
{
IntAna_QuadQuadGeo i2pl(Pl, NeutralPlane, Precision::Angular(), Precision::Confusion());
if (i2pl.IsDone() && i2pl.TypeInter() == IntAna_Line)
{
gp_Lin li = i2pl.Line(1);
// Try to turn around this line
gp_Dir nx = li.Direction();
gp_Dir ny = Pl.Axis().Direction().Crossed(nx);
Standard_Real a = Direction.Dot(nx);
if (Abs(a) <= 1 - Precision::Angular())
{
Standard_Real b = Direction.Dot(ny);
Standard_Real c = Direction.Dot(Pl.Axis().Direction());
Standard_Boolean direct(Pl.Position().Direct());
if ((direct && Oris == TopAbs_REVERSED) || (!direct && Oris == TopAbs_FORWARD))
{
b = -b;
c = -c;
}
Standard_Real denom = Sqrt(1 - a * a);
Standard_Real Sina = Sin(Angle);
if (denom > Abs(Sina))
{
Standard_Real phi = ATan2(b / denom, c / denom);
Standard_Real theta0 = ACos(Sina / denom);
theta = theta0 - phi;
if (Cos(theta) < 0.)
{
theta = -theta0 - phi;
}
// modified by NIZHNY-EAP Tue Nov 16 15:51:38 1999 ___BEGIN___
while (Abs(theta) > M_PI)
{
theta = theta + M_PI * (theta < 0 ? 1 : -1);
}
// modified by NIZHNY-EAP Tue Nov 16 15:53:32 1999 ___END___
Axe = li.Position();
return Standard_True;
}
}
}
return Standard_False;
}