#include <BRepTools.hxx>
#include <BRepTopAdaptor_FClass2d.hxx>
#include <Extrema_ExtPC2d.hxx>
-#include <GCPnts_AbscissaPoint.hxx>
#include <Geom2d_Curve.hxx>
#include <Geom2d_Line.hxx>
#include <Geom2dAdaptor_Curve.hxx>
#include <Geom2dInt_GInter.hxx>
#include <Geom_Curve.hxx>
#include <Geom_ElementarySurface.hxx>
-#include <GeomAdaptor_Curve.hxx>
#include <GeomAdaptor_Surface.hxx>
#include <gp_Dir2d.hxx>
#include <gp_Lin2d.hxx>
#define ITP_ENDSEG 32 // stop of tangential segment
#define ITP_TANG 64 // tangential point
-enum ShapeFix_MakeCut
-{
- ShapeFix_NoCut,
- ShapeFix_CutHead,
- ShapeFix_CutTail
-};
-
//=======================================================================
//function : PointLineDeviation
//purpose : auxilary
ShapeFix_WireSegment ShapeFix_ComposeShell::SplitWire (ShapeFix_WireSegment &wire,
TColStd_SequenceOfInteger& indexes,
const TColStd_SequenceOfReal& values,
- const TopTools_MapOfShape& theVerts,
TopTools_SequenceOfShape& vertices,
const TColStd_SequenceOfInteger &SegmentCodes,
const Standard_Boolean isCutByU,
ShapeAnalysis_Edge sae;
Standard_Integer start = 1;
TopAbs_Orientation anWireOrient = wire.Orientation();
- Standard_Integer aLastSplitted = 0;
gp_Trsf T;
if ( ! myLoc.IsIdentity() ) T = myLoc.Inverted().Transformation();
std::cout << "Error: ShapeFix_ComposeShell::SplitWire: edge dismissed" << std::endl;
#endif
i--;
- aLastSplitted = 0;
continue;
}
}
result.AddEdge ( 0, edge, iumin, iumax, ivmin, ivmax );
if(code!=0 || wire.Orientation()!=TopAbs_EXTERNAL) // pdn 0 code handling for extertnal wires
DefinePatch ( result, code, isCutByU, cutIndex );
- aLastSplitted = 0;
continue;
}
//find non-manifold vertices on edge
// Collect data on edge
Standard_Real tolEdge = BRep_Tool::Tolerance(edge);
- Standard_Real tol = LimitTolerance( tolEdge );
TopoDS_Vertex prevV = sae.FirstVertex(edge);
TopoDS_Vertex lastV = sae.LastVertex(edge);
Standard_Real prevVTol = LimitTolerance( BRep_Tool::Tolerance(prevV) );
Standard_Integer NbEdgesStart = result.NbEdges();
Standard_Boolean splitted = Standard_False;
Standard_Real currPar=lastPar; //SK
- Standard_Integer aCurSplitted = 0;
for ( Standard_Integer j = start; j <= stop; prevPar = currPar, j++ ) {
if ( ! splitted && j >= stop ) {// no splitting at all
// code = SegmentCodes ( j >1 ? j-1 : SegmentCodes.Length() ); // classification code
break;
}
- ShapeFix_MakeCut aCutPart = ShapeFix_NoCut;
- Standard_Boolean isCutChecked = Standard_False;
currPar = ( j < stop ? values.Value(j) : lastPar );
//fix for case when pcurve is periodic and first parameter of edge is more than 2P
//method ShapeBuild_Edge::CopyRanges shift pcurve to range 0-2P and parameters of cutting
currPnt2d = C2d->Value(currPar);
currPnt = myGrid->Value ( currPnt2d );
if ( currPnt.Distance ( lastVPnt ) <= lastVTol &&
- lastPnt.Distance ( currPnt ) <= tol &&
// Tolerance is increased to prevent degenerated cuts in cases where all vertex
// tolerance is covered by distance of the edge curve from vertex point.
// Doubled to prevent edge being fully covered by its vertices tolerance (invalid edge).
CheckByCurve3d ( lastVPnt, c3d, f3d+(currPar-firstPar)*(l3d-f3d)/span2d,
T, lastVTol + 2 * Precision::Confusion() ) &&
- lastPnt.Distance ( myGrid->Value ( C2d->Value(0.5*(currPar+lastPar)) ) ) <= tol )
- {
- if (theVerts.Contains(lastV))
- {
- GeomAdaptor_Curve AC(c3d, currPar, (edge.Orientation() == TopAbs_REVERSED) ? firstPar : lastPar);
- Standard_Real L = GCPnts_AbscissaPoint::Length(AC, Precision::Confusion());
- if (L < BRep_Tool::Tolerance(lastV))
- aCutPart = ShapeFix_CutTail;
- isCutChecked = Standard_True;
+ lastPnt.Distance (myGrid->Value (C2d->Value(0.5*(currPar+lastPar)))) <= lastVTol) {
+ V = lastV;
+ Standard_Real uRes = myUResolution;
+ Standard_Real vRes = myVResolution;
+ if(isCutByU) {
+ Standard_Real gridRes = GetGridResolution(myGrid->UJointValues(), cutIndex) / lastVTol;
+ uRes = Min(myUResolution,gridRes);
}
- if (aCutPart == ShapeFix_NoCut)
- {
- V = lastV;
- Standard_Real uRes = myUResolution;
- Standard_Real vRes = myVResolution;
- if (isCutByU) {
- Standard_Real gridRes = GetGridResolution(myGrid->UJointValues(), cutIndex) / tol;
- uRes = Min(myUResolution, gridRes);
- }
- else {
- Standard_Real gridRes = GetGridResolution(myGrid->VJointValues(), cutIndex) / tol;
- vRes = Min(myVResolution, gridRes);
- }
- if (IsCoincided(lastPnt2d, currPnt2d, uRes, vRes, tol) &&
- IsCoincided(lastPnt2d, C2d->Value(0.5*(currPar + lastPar)), uRes, vRes, tol))
- {
- doCut = Standard_False;
- }
+ else {
+ Standard_Real gridRes = GetGridResolution(myGrid->VJointValues(), cutIndex) / lastVTol;
+ vRes = Min(myVResolution,gridRes);
}
+ if (IsCoincided(lastPnt2d, currPnt2d, uRes, vRes, lastVTol) &&
+ IsCoincided(lastPnt2d, C2d->Value(0.5*(currPar + lastPar)), uRes, vRes, lastVTol))
+ doCut = Standard_False;
}
else if ( currPnt.Distance ( prevVPnt ) <= prevVTol &&
- prevPnt.Distance ( currPnt ) <= tol &&
// Tolerance is increased to prevent degenerated cuts in cases where all vertex
// tolerance is covered by distance of the edge curve from vertex point.
// Doubled to prevent edge being fully covered by its vertices tolerance (invalid edge).
- CheckByCurve3d ( prevVPnt, c3d, f3d + (currPar - firstPar)*(l3d - f3d) / span2d,
+ CheckByCurve3d ( prevVPnt, c3d, f3d+(currPar-firstPar)*(l3d-f3d)/span2d,
T, prevVTol + 2 * Precision::Confusion()) &&
- prevPnt.Distance ( myGrid->Value ( C2d->Value(0.5*(currPar + prevPar)) ) ) <= tol )
- {
- if (theVerts.Contains(prevV))
- {
- GeomAdaptor_Curve AC(c3d, (edge.Orientation() == TopAbs_REVERSED) ? lastPar : firstPar, currPar);
- Standard_Real L = GCPnts_AbscissaPoint::Length(AC, Precision::Confusion());
- if (L < BRep_Tool::Tolerance(prevV))
- aCutPart = ShapeFix_CutHead;
- isCutChecked = Standard_True;
+ prevPnt.Distance (myGrid->Value (C2d->Value(0.5*(currPar+prevPar)))) <= prevVTol) {
+ V = prevV;
+ Standard_Real uRes = myUResolution;
+ Standard_Real vRes = myVResolution;
+ if(isCutByU) {
+ Standard_Real gridRes = GetGridResolution(myGrid->UJointValues(), cutIndex) / prevVTol;
+ uRes = Min(myUResolution,gridRes);
}
- if (aCutPart == ShapeFix_NoCut)
- {
- V = prevV;
- Standard_Real uRes = myUResolution;
- Standard_Real vRes = myVResolution;
- if (isCutByU) {
- Standard_Real gridRes = GetGridResolution(myGrid->UJointValues(), cutIndex) / tol;
- uRes = Min(myUResolution, gridRes);
- }
- else {
- Standard_Real gridRes = GetGridResolution(myGrid->VJointValues(), cutIndex) / tol;
- vRes = Min(myVResolution, gridRes);
- }
- if (IsCoincided(prevPnt2d, currPnt2d, uRes, vRes, tol) &&
- IsCoincided(prevPnt2d, C2d->Value(0.5*(currPar + prevPar)), uRes, vRes, tol)) {
- vertices.Append(prevV);
- code = SegmentCodes(j); // classification code - update for next segment
- continue; // no splitting at this point, go to next one
- }
+ else {
+ Standard_Real gridRes = GetGridResolution(myGrid->VJointValues(), cutIndex) / prevVTol;
+ vRes = Min(myVResolution,gridRes);
+ }
+ if (IsCoincided(prevPnt2d, currPnt2d, uRes, vRes, prevVTol) &&
+ IsCoincided(prevPnt2d, C2d->Value(0.5*(currPar + prevPar)), uRes, vRes, prevVTol)) {
+
+ vertices.Append ( prevV );
+ code = SegmentCodes ( j ); // classification code - update for next segment
+ continue; // no splitting at this point, go to next one
}
}
//:abv 28.05.02: OCC320 Sample_2: if maxtol = 1e-7, the vertex tolerance
// is actually ignored - protect against new vertex on degenerated edge
- else if (BRep_Tool::Degenerated(edge) && prevV.IsSame(lastV)) {
+ else if ( BRep_Tool::Degenerated(edge) && prevV.IsSame(lastV) ) {
V = prevV;
}
}
if ( V.IsNull() ) {
B.MakeVertex ( V, currPnt.Transformed(myLoc.Transformation()), tolEdge );
vertices.Append ( V );
- if (!isCutChecked)
- {
- Standard_Real aVTol;
- if (theVerts.Contains(prevV))
- {
- aVTol = BRep_Tool::Tolerance(prevV);
- if (currPnt.SquareDistance(prevVPnt) < aVTol * aVTol)
- {
- GeomAdaptor_Curve AC(c3d, (edge.Orientation() == TopAbs_REVERSED) ? lastPar : firstPar, currPar);
- Standard_Real L = GCPnts_AbscissaPoint::Length(AC, Precision::Confusion());
- if (L < aVTol)
- aCutPart = ShapeFix_CutHead;
- }
- }
- else if (theVerts.Contains(lastV))
- {
- aVTol = BRep_Tool::Tolerance(lastV);
- if (currPnt.SquareDistance(lastVPnt) < aVTol * aVTol)
- {
- GeomAdaptor_Curve AC(c3d, currPar, (edge.Orientation() == TopAbs_REVERSED) ? firstPar : lastPar);
- Standard_Real L = GCPnts_AbscissaPoint::Length(AC, Precision::Confusion());
- if (L < aVTol)
- aCutPart = ShapeFix_CutTail;
- }
- }
- }
}
// else adjusted to end, fill all resting vertices
else if ( ! doCut ) {
- for (; j < stop; j++)
- {
- vertices.Append(lastV);
- aCurSplitted++;
- }
+ for ( ; j < stop; j++ ) vertices.Append ( lastV );
if ( ! splitted ) break; // no splitting at all
currPar = lastPar;
}
code = ( ( isCutByU == (j == 1) ) ? 1 : 2 );
}
- if (aCutPart == ShapeFix_CutHead)
- {
- V.Orientation(TopAbs_FORWARD);
- Context()->Replace(prevV, V);
- // also replce this vertice in the sequence
- for (Standard_Integer iV = 1; aLastSplitted > 0; aLastSplitted--, iV++)
- {
- vertices.ChangeValue(vertices.Length() - iV) = V;
- }
- }
- else
- {
- result.AddEdge(0, newEdge, iumin, iumax, ivmin, ivmax);
- DefinePatch(result, code, isCutByU, cutIndex);
- }
+ result.AddEdge ( 0, newEdge, iumin, iumax, ivmin, ivmax );
+ DefinePatch ( result, code, isCutByU, cutIndex );
// Changing prev parameters
prevV = V;
prevVPnt = BRep_Tool::Pnt ( V );
prevPnt = currPnt;
prevPnt2d = currPnt2d;
-
- if (aCutPart == ShapeFix_CutTail)
- {
- Context()->Replace(lastV, V);
- for (; j + 1 < stop; j++) vertices.Append(lastV);
- break;
- }
}
start = stop;
- aLastSplitted = aCurSplitted;
if ( splitted ) {
// record replacement in context
TColStd_SequenceOfReal IntEdgePar; // parameter of intersection point on edge
TColStd_SequenceOfReal IntLinePar; // parameter of intersection point on line
- TopTools_MapOfShape exactVertices; // vertices that line passes through
-
Standard_Boolean isnonmanifold = (wire.Orientation() == TopAbs_INTERNAL);
//gka correction for non-manifold vertices SAMTECH
if(wire.IsVertex()) {
Standard_Real f, l;
Handle(Geom2d_Curve) c2d;
if ( ! sae.PCurve ( E, myFace, c2d, f, l, Standard_False ) ) continue;
+ Handle(Geom2d_Curve) c2d_sav = c2d;
// get end points
gp_Pnt2d posf = c2d->Value(f), posl = c2d->Value(l);
pppf.SetX ( pppf.X() + shift );
pppl.SetX ( pppl.X() + shift );
}
- shiftNext.SetX ( -myUPeriod );
- nbIter = (Standard_Integer)( 1 + Abs ( umax + shift - x ) / myUPeriod );
+ Standard_Real dUmax = umax + shift - x;
+ shiftNext.SetX (dUmax > 0 ? -myUPeriod : myUPeriod);
+ nbIter = (Standard_Integer)(1 + Abs (dUmax) / myUPeriod);
shift = ShapeAnalysis::AdjustByPeriod ( posf.X(), x, myUPeriod );
posf.SetX ( posf.X() + shift );
shift = ShapeAnalysis::AdjustByPeriod ( posl.X(), x, myUPeriod );
pppf.SetY ( pppf.Y() + shift );
pppl.SetY ( pppl.Y() + shift );
}
- shiftNext.SetY ( -myVPeriod );
- nbIter = (Standard_Integer)( 1 + Abs ( umax + shift - y ) / myVPeriod );
+ Standard_Real dVmax = vmax + shift - y;
+ shiftNext.SetY (dVmax > 0 ? -myVPeriod : myVPeriod);
+ nbIter = (Standard_Integer)(1 + Abs (dVmax) / myVPeriod);
shift = ShapeAnalysis::AdjustByPeriod ( posf.Y(), y, myVPeriod );
posf.SetY ( posf.Y() + shift );
shift = ShapeAnalysis::AdjustByPeriod ( posl.Y(), y, myVPeriod );
IntLinePar.Append ( ParamPointsOnLine ( pos, prevPos, line ) ); // !! - maybe compute exactly ?
IntEdgePar.Append ( isreversed ? l : f );
IntEdgeInd.Append ( iedge );
- exactVertices.Add (sae.FirstVertex(E));
}
}
Standard_Integer i;
for ( i = 1; i <= Inter.NbPoints(); i++ ) {
IntRes2d_IntersectionPoint IP = Inter.Point (i);
- IntLinePar.Append ( IP.ParamOnFirst() );
- IntEdgePar.Append ( IP.ParamOnSecond() );
+ if (IP.TransitionOfSecond().PositionOnCurve() == IntRes2d_Middle || (code != IOR_UNDEF && prevCode != IOR_UNDEF) )
+ {
+ IntLinePar.Append (IP.ParamOnFirst());
+ IntEdgePar.Append (IP.ParamOnSecond());
+ }
}
for ( i = 1; i <= Inter.NbSegments(); i++ ) {
IntRes2d_IntersectionSegment IS = Inter.Segment (i);
IntLinePar.Append ( ParamPointsOnLine ( pos, firstPos, line ) );
IntEdgePar.Append ( isreversed ? f : l );
IntEdgeInd.Append ( iedge );
- exactVertices.Add (sae.LastVertex(E));
}
}
}
//=======================================
// Split edges in the wire by intersection points and fill vertices array
TopTools_SequenceOfShape IntVertices;
- wire = SplitWire ( wire, IntEdgeInd, IntEdgePar, exactVertices, IntVertices,
+ wire = SplitWire ( wire, IntEdgeInd, IntEdgePar, IntVertices,
aNewSegCodes, isCutByU, cutIndex );
// add all data to input arrays
// merge null-length tangential segments into one-point tangencies or intersections
for ( i = 1; i < SplitLinePar.Length(); i++ ) {
- Standard_Boolean isSameVertex = SplitLineVertex(i).IsSame(SplitLineVertex(i + 1));
- if ( Abs ( SplitLinePar(i+1) - SplitLinePar(i) ) > ::Precision::PConfusion() && !isSameVertex) continue;
+ if ( Abs ( SplitLinePar(i+1) - SplitLinePar(i) ) > ::Precision::PConfusion() && !SplitLineVertex(i).IsSame(SplitLineVertex(i+1)) ) continue;
if ( ( SplitLineCode(i) & ITP_ENDSEG &&
SplitLineCode(i+1) & ITP_BEGSEG ) ||
( SplitLineCode(i) & ITP_BEGSEG &&
SplitLineCode.Remove(i+1);
SplitLineVertex.Remove(i+1);
}
- else if (isSameVertex &&
- ((SplitLineCode (i) & ITP_TANG &&
- SplitLineCode (i + 1) & ITP_INTER) ||
- (SplitLineCode (i) & ITP_INTER &&
- SplitLineCode (i + 1) & ITP_TANG)))
- {
- SplitLineCode.SetValue(i, IOR_BOTH | ITP_INTER );
- SplitLinePar.Remove(i + 1);
- SplitLineCode.Remove(i + 1);
- SplitLineVertex.Remove(i + 1);
- }
}
// go along line, split it by intersection points and create edges
TopoDS_Shape tmpV2 = Context()->Apply ( SplitLineVertex(i) );
TopoDS_Vertex V1 = TopoDS::Vertex ( tmpV1 );
TopoDS_Vertex V2 = TopoDS::Vertex ( tmpV2 );
- // protection against creating null-length edges
- if ( SplitLinePar(i) - SplitLinePar(i-1) < ::Precision::PConfusion() ) {
+ // protection against creating null-length edges or edges lying inside tolerance of vertices
+ //first and last vertices for split line can not be merged to each other
+ Standard_Boolean canbeMerged = ( /*myClosedMode &&*/ (i -1 > 1 || i < SplitLinePar.Length()));
+ Standard_Real aMaxTol = MaxTolerance();
+ //case when max tolerance is not defined tolerance of vertices will be used as is
+ if( aMaxTol <= 2. *Precision::Confusion() )
+ aMaxTol = Precision::Infinite();
+ Standard_Real aTol1 = Min(BRep_Tool::Tolerance(V1), aMaxTol);
+ Standard_Real aTol2 = Min(BRep_Tool::Tolerance(V2), aMaxTol);
+ gp_Pnt aP1 = BRep_Tool::Pnt(V1);
+ gp_Pnt aP2 = BRep_Tool::Pnt(V2);
+ Standard_Real aD = aP1.SquareDistance(aP2);
+ if (SplitLinePar(i) - SplitLinePar(i-1) < ::Precision::PConfusion() || ( canbeMerged && ( aD <= (aTol1 * aTol1) || aD <= (aTol2 * aTol2)))) {// BRepTools::Compare(V1, V2)) ) {
#ifdef OCCT_DEBUG
std::cout << "Info: ShapeFix_ComposeShell::SplitByLine: Short segment ignored" << std::endl;
// for coincidence (instead of vertex tolerance) in order
// this check to be in agreement with check for position of wire segments
// thus avoiding bad effects on overlapping edges
- Standard_Real ctol = Max ( edgeTol, BRep_Tool::Tolerance(lastEdge) );
+ Standard_Real ctol = Max (edgeTol, BRep_Tool::Tolerance(endV/*lastEdge*/));
Standard_Boolean conn = IsCoincided ( endPnt, lPnt, myUResolution, myVResolution, ctol );
Standard_Real dist = endPnt.SquareDistance ( lPnt );