mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-09-03 14:10:33 +03:00
Get rid of strange code: preliminary check of self-intersections is made on a polygonal representation of a curve, it is able to find possible intersections, but after that it filter out segments neighbor to the pair of non-intersected segments. Test case de step_4 I1 has been marked BAD, because the self-intersection is treated correctly, but the projection algorithm generates such crooked 2D curve. Reference data in test cases heal split_angle_advanced ZA5 and ZA6 has been updated, because those shapes have self-intersected edges, which are being detected now.
1358 lines
51 KiB
Plaintext
1358 lines
51 KiB
Plaintext
// Created on: 1992-10-13
|
|
// Created by: Laurent BUCHARD
|
|
// Copyright (c) 1992-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.
|
|
|
|
// Modified by skv - Tue Mar 1 14:22:09 2005 OCC8169
|
|
|
|
|
|
#ifndef OCCT_DEBUG
|
|
#define No_Standard_RangeError
|
|
#define No_Standard_OutOfRange
|
|
#endif
|
|
|
|
|
|
#include <Standard_ConstructionError.hxx>
|
|
|
|
#include <IntRes2d_Domain.hxx>
|
|
#include <IntRes2d_Position.hxx>
|
|
#include <IntRes2d_Transition.hxx>
|
|
#include <IntRes2d_IntersectionPoint.hxx>
|
|
#include <IntRes2d_IntersectionSegment.hxx>
|
|
|
|
|
|
#include <IntImpParGen.hxx>
|
|
|
|
#include <Intf_SectionPoint.hxx>
|
|
#include <Intf_SectionLine.hxx>
|
|
#include <Intf_TangentZone.hxx>
|
|
#include <Intf_InterferencePolygon2d.hxx>
|
|
|
|
#include <gp_Vec2d.hxx>
|
|
|
|
#include <math_Vector.hxx>
|
|
#include <math_FunctionSetRoot.hxx>
|
|
#include <math_NewtonFunctionSetRoot.hxx>
|
|
#include <NCollection_Handle.hxx>
|
|
#include <Bnd_Box2d.hxx>
|
|
#include <Precision.hxx>
|
|
|
|
//======================================================================
|
|
|
|
#define NBITER_MAX_POLYGON 10
|
|
#define TOL_CONF_MINI 0.0000000001
|
|
#define TOL_MINI 0.0000000001
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
|
void GetIntersection(const TheCurve& theC1, const Standard_Real theT1f, const Standard_Real theT1l,
|
|
const TheCurve& theC2, const Standard_Real theT2f, const Standard_Real theT2l,
|
|
const Standard_Real theTolConf,
|
|
const Standard_Integer theMaxCount,
|
|
IntRes2d_IntersectionPoint& thePInt, Standard_Real& theDist,
|
|
Standard_Integer& theCount);
|
|
|
|
|
|
Standard_Boolean HeadOrEndPoint( const IntRes2d_Domain& D1
|
|
,const TheCurve& C1
|
|
,const Standard_Real u
|
|
,const IntRes2d_Domain& D2
|
|
,const TheCurve& C2
|
|
,const Standard_Real v
|
|
,const Standard_Real TolConf
|
|
,IntRes2d_IntersectionPoint& IntPt
|
|
,Standard_Boolean& HeadOn1
|
|
,Standard_Boolean& HeadOn2
|
|
,Standard_Boolean& EndOn1
|
|
,Standard_Boolean& EndOn2
|
|
,Standard_Integer PosSegment);
|
|
|
|
|
|
//======================================================================
|
|
IntCurve_IntPolyPolyGen::IntCurve_IntPolyPolyGen()
|
|
{
|
|
const Standard_Integer aMinPntNb = 20; // Minimum number of samples.
|
|
myMinPntNb = aMinPntNb;
|
|
done = Standard_False;
|
|
}
|
|
//======================================================================
|
|
void IntCurve_IntPolyPolyGen::Perform( const TheCurve& C1
|
|
,const IntRes2d_Domain& D1
|
|
,const TheCurve& C2
|
|
,const IntRes2d_Domain& D2
|
|
,const Standard_Real TheTolConf
|
|
,const Standard_Real TheTol)
|
|
{
|
|
this->ResetFields();
|
|
DomainOnCurve1=D1;
|
|
DomainOnCurve2=D2;
|
|
Standard_Real DU = D1.LastParameter()-D1.FirstParameter();
|
|
Standard_Real DV = D2.LastParameter()-D2.FirstParameter();
|
|
Standard_Real Tl=(TheTol < TOL_MINI)? TOL_MINI : TheTol;
|
|
Standard_Real TlConf=(TheTolConf < TOL_CONF_MINI)? TOL_CONF_MINI : TheTolConf;
|
|
Perform(C1,D1,C2,D2,TlConf,Tl,0,DU,DV);
|
|
//----------------------------------------------------------------------
|
|
//-- Processing of end points
|
|
//----------------------------------------------------------------------
|
|
Standard_Boolean HeadOn1 = Standard_False;
|
|
Standard_Boolean HeadOn2 = Standard_False;
|
|
Standard_Boolean EndOn1 = Standard_False;
|
|
Standard_Boolean EndOn2 = Standard_False;
|
|
Standard_Integer i;
|
|
Standard_Integer n=this->NbPoints();
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
//-- The points Head Head ... End End are not rejected if
|
|
//-- they are already present at the end of segment
|
|
//-- ( It is not possible to test the equities on the parameters)
|
|
//-- ( these points are not found at EpsX precision )
|
|
//-- PosSegment = 1 if Head Head
|
|
//-- 2 if Head End
|
|
//-- 4 if End Head
|
|
//-- 8 if End End
|
|
//--------------------------------------------------------------------
|
|
Standard_Integer PosSegment = 0;
|
|
|
|
for(i=1;i<=n;i++) {
|
|
IntRes2d_Position Pos1 = this->Point(i).TransitionOfFirst().PositionOnCurve();
|
|
if(Pos1 == IntRes2d_Head) HeadOn1 = Standard_True;
|
|
else if(Pos1 == IntRes2d_End) EndOn1 = Standard_True;
|
|
|
|
IntRes2d_Position Pos2 = this->Point(i).TransitionOfSecond().PositionOnCurve();
|
|
if(Pos2 == IntRes2d_Head) HeadOn2 = Standard_True;
|
|
else if(Pos2 == IntRes2d_End) EndOn2 = Standard_True;
|
|
|
|
if(Pos1 == IntRes2d_Head) {
|
|
if(Pos2 == IntRes2d_Head) PosSegment|=1;
|
|
else if(Pos2 == IntRes2d_End) PosSegment|=2;
|
|
}
|
|
else if(Pos1 == IntRes2d_End) {
|
|
if(Pos2 == IntRes2d_Head) PosSegment|=4;
|
|
else if(Pos2 == IntRes2d_End) PosSegment|=8;
|
|
}
|
|
}
|
|
|
|
n=this->NbSegments();
|
|
for(i=1;i<=n;i++) {
|
|
IntRes2d_Position Pos1 = this->Segment(i).FirstPoint().TransitionOfFirst().PositionOnCurve();
|
|
if(Pos1 == IntRes2d_Head) HeadOn1 = Standard_True;
|
|
else if(Pos1 == IntRes2d_End) EndOn1 = Standard_True;
|
|
|
|
IntRes2d_Position Pos2 = this->Segment(i).FirstPoint().TransitionOfSecond().PositionOnCurve();
|
|
if(Pos2 == IntRes2d_Head) HeadOn2 = Standard_True;
|
|
else if(Pos2 == IntRes2d_End) EndOn2 = Standard_True;
|
|
|
|
if(Pos1 == IntRes2d_Head) {
|
|
if(Pos2 == IntRes2d_Head) PosSegment|=1;
|
|
else if(Pos2 == IntRes2d_End) PosSegment|=2;
|
|
}
|
|
else if(Pos1 == IntRes2d_End) {
|
|
if(Pos2 == IntRes2d_Head) PosSegment|=4;
|
|
else if(Pos2 == IntRes2d_End) PosSegment|=8;
|
|
}
|
|
|
|
Pos1 = this->Segment(i).LastPoint().TransitionOfFirst().PositionOnCurve();
|
|
if(Pos1 == IntRes2d_Head) HeadOn1 = Standard_True;
|
|
else if(Pos1 == IntRes2d_End) EndOn1 = Standard_True;
|
|
|
|
Pos2 = this->Segment(i).LastPoint().TransitionOfSecond().PositionOnCurve();
|
|
if(Pos2 == IntRes2d_Head) HeadOn2 = Standard_True;
|
|
else if(Pos2 == IntRes2d_End) EndOn2 = Standard_True;
|
|
|
|
if(Pos1 == IntRes2d_Head) {
|
|
if(Pos2 == IntRes2d_Head) PosSegment|=1;
|
|
else if(Pos2 == IntRes2d_End) PosSegment|=2;
|
|
}
|
|
else if(Pos1 == IntRes2d_End) {
|
|
if(Pos2 == IntRes2d_Head) PosSegment|=4;
|
|
else if(Pos2 == IntRes2d_End) PosSegment|=8;
|
|
}
|
|
}
|
|
|
|
Standard_Real U0 = D1.FirstParameter();
|
|
Standard_Real U1 = D1.LastParameter();
|
|
Standard_Real V0 = D2.FirstParameter();
|
|
Standard_Real V1 = D2.LastParameter();
|
|
IntRes2d_IntersectionPoint IntPt;
|
|
|
|
if(D1.FirstTolerance() || D2.FirstTolerance()) {
|
|
if(HeadOrEndPoint(D1,C1,U0,D2,C2,V0,TheTolConf,IntPt,HeadOn1,HeadOn2,EndOn1,EndOn2,PosSegment))
|
|
this->Insert(IntPt);
|
|
}
|
|
if(D1.FirstTolerance() || D2.LastTolerance()) {
|
|
if(HeadOrEndPoint(D1,C1,U0,D2,C2,V1,TheTolConf,IntPt,HeadOn1,HeadOn2,EndOn1,EndOn2,PosSegment))
|
|
this->Insert(IntPt);
|
|
}
|
|
if(D1.LastTolerance() || D2.FirstTolerance()) {
|
|
if(HeadOrEndPoint(D1,C1,U1,D2,C2,V0,TheTolConf,IntPt,HeadOn1,HeadOn2,EndOn1,EndOn2,PosSegment))
|
|
this->Insert(IntPt);
|
|
}
|
|
if(D1.LastTolerance() || D2.LastTolerance()) {
|
|
if(HeadOrEndPoint(D1,C1,U1,D2,C2,V1,TheTolConf,IntPt,HeadOn1,HeadOn2,EndOn1,EndOn2,PosSegment))
|
|
this->Insert(IntPt);
|
|
}
|
|
}
|
|
|
|
|
|
//======================================================================
|
|
//== A u t o I n t e r s e c t i o n
|
|
//======================================================================
|
|
void IntCurve_IntPolyPolyGen::Perform( const TheCurve& C1
|
|
,const IntRes2d_Domain& D1
|
|
,const Standard_Real TheTolConf
|
|
,const Standard_Real TheTol)
|
|
{
|
|
|
|
this->ResetFields();
|
|
DomainOnCurve1=D1;
|
|
DomainOnCurve2=D1;
|
|
Standard_Real DU = D1.LastParameter()-D1.FirstParameter();
|
|
Standard_Real Tl=(TheTol < TOL_MINI)? TOL_MINI : TheTol;
|
|
Standard_Real TlConf=(TheTolConf < TOL_CONF_MINI)? TOL_CONF_MINI : TheTolConf;
|
|
Perform(C1,D1,TlConf,Tl,0,DU,DU);
|
|
Standard_Integer i;
|
|
Standard_Integer n=this->NbPoints();
|
|
|
|
//--------------------------------------------------------------------
|
|
//-- The points Head Head ... End End are not rejected if
|
|
//-- they are already present at the end of segment
|
|
//-- ( It is not possible to test the equities on the parameters)
|
|
//-- ( these points are not found at EpsX precision )
|
|
//-- PosSegment = 1 if Head Head
|
|
//-- 2 if Head End
|
|
//-- 4 if End Head
|
|
//-- 8 if End End
|
|
//--------------------------------------------------------------------
|
|
Standard_Integer PosSegment = 0;
|
|
|
|
for(i=1;i<=n;i++) {
|
|
IntRes2d_Position Pos1 = this->Point(i).TransitionOfFirst().PositionOnCurve();
|
|
IntRes2d_Position Pos2 = this->Point(i).TransitionOfSecond().PositionOnCurve();
|
|
|
|
if(Pos1 == IntRes2d_Head) {
|
|
if(Pos2 == IntRes2d_Head) PosSegment|=1;
|
|
else if(Pos2 == IntRes2d_End) PosSegment|=2;
|
|
}
|
|
else if(Pos1 == IntRes2d_End) {
|
|
if(Pos2 == IntRes2d_Head) PosSegment|=4;
|
|
else if(Pos2 == IntRes2d_End) PosSegment|=8;
|
|
}
|
|
}
|
|
|
|
n=this->NbSegments();
|
|
for(i=1;i<=n;i++) {
|
|
IntRes2d_Position Pos1 = this->Segment(i).FirstPoint().TransitionOfFirst().PositionOnCurve();
|
|
IntRes2d_Position Pos2 = this->Segment(i).FirstPoint().TransitionOfSecond().PositionOnCurve();
|
|
|
|
if(Pos1 == IntRes2d_Head) {
|
|
if(Pos2 == IntRes2d_Head) PosSegment|=1;
|
|
else if(Pos2 == IntRes2d_End) PosSegment|=2;
|
|
}
|
|
else if(Pos1 == IntRes2d_End) {
|
|
if(Pos2 == IntRes2d_Head) PosSegment|=4;
|
|
else if(Pos2 == IntRes2d_End) PosSegment|=8;
|
|
}
|
|
|
|
Pos1 = this->Segment(i).LastPoint().TransitionOfFirst().PositionOnCurve();
|
|
Pos2 = this->Segment(i).LastPoint().TransitionOfSecond().PositionOnCurve();
|
|
|
|
if(Pos1 == IntRes2d_Head) {
|
|
if(Pos2 == IntRes2d_Head) PosSegment|=1;
|
|
else if(Pos2 == IntRes2d_End) PosSegment|=2;
|
|
}
|
|
else if(Pos1 == IntRes2d_End) {
|
|
if(Pos2 == IntRes2d_Head) PosSegment|=4;
|
|
else if(Pos2 == IntRes2d_End) PosSegment|=8;
|
|
}
|
|
}
|
|
(void )PosSegment;
|
|
}
|
|
//======================================================================
|
|
|
|
void IntCurve_IntPolyPolyGen::Perform( const TheCurve& C1
|
|
,const IntRes2d_Domain& D1
|
|
,const Standard_Real TolConf
|
|
,const Standard_Real Tol
|
|
,const Standard_Integer NbIter
|
|
,const Standard_Real /*DeltaU*/
|
|
,const Standard_Real) {
|
|
|
|
gp_Vec2d Tan1,Tan2,Norm1,Norm2;
|
|
gp_Pnt2d P1,P2;
|
|
Standard_Integer nbsamples;
|
|
done = Standard_False;
|
|
|
|
nbsamples = TheCurveTool::NbSamples(C1,D1.FirstParameter(),D1.LastParameter());
|
|
|
|
if(NbIter>3 || (NbIter>2 && nbsamples>100)) return;
|
|
|
|
nbsamples*=2; //--- We take systematically two times more points
|
|
//-- than on a normal curve.
|
|
//-- Auto-intersecting curves often produce
|
|
//-- polygons rather far from the curve with parameter ct.
|
|
|
|
if(NbIter>0) {
|
|
nbsamples=(3*(nbsamples*NbIter))/2;
|
|
}
|
|
IntCurve_ThePolygon2d Poly1(C1,nbsamples,D1,Tol);
|
|
if(!Poly1.AutoIntersectionIsPossible()) {
|
|
done = Standard_True;
|
|
return;
|
|
}
|
|
//-- Poly1.Dump();
|
|
//----------------------------------------------------------------------
|
|
//-- If the deflection is less than the Tolerance of Confusion
|
|
//-- then the deflection of the polygon is set in TolConf
|
|
//-- (Detection of Tangency Zones)
|
|
//----------------------------------------------------------------------
|
|
if(Poly1.DeflectionOverEstimation() < TolConf) {
|
|
Poly1.SetDeflectionOverEstimation(TolConf);
|
|
}
|
|
|
|
Intf_InterferencePolygon2d InterPP(Poly1);
|
|
IntCurve_ExactIntersectionPoint EIP(C1,C1,TolConf);
|
|
Standard_Real U,V;
|
|
|
|
//----------------------------------------------------------------------
|
|
//-- Processing of SectionPoint
|
|
//----------------------------------------------------------------------
|
|
Standard_Integer Nbsp = InterPP.NbSectionPoints();
|
|
if(Nbsp>=1) {
|
|
|
|
//-- ---------------------------------------------------------------------
|
|
//-- filtering, filtering, filtering ...
|
|
//--
|
|
Standard_Integer* TriIndex = new Standard_Integer [Nbsp+1];
|
|
Standard_Integer* PtrSegIndex1 = new Standard_Integer [Nbsp+1];
|
|
Standard_Integer* PtrSegIndex2 = new Standard_Integer [Nbsp+1];
|
|
Standard_Boolean Triok;
|
|
Standard_Integer SegIndex1,SegIndex2,SegIndex_1,SegIndex_2;
|
|
// Standard_Real ParamOn1,ParamOn2,ParamOn_1,ParamOn_2;
|
|
Standard_Real ParamOn1,ParamOn2;
|
|
Intf_PIType Type;
|
|
Standard_Integer i ;
|
|
for( i=1;i<=Nbsp;i++) {
|
|
TriIndex[i]=i;
|
|
const Intf_SectionPoint& SPnt1 = InterPP.PntValue(i);
|
|
SPnt1.InfoFirst(Type,PtrSegIndex1[i],ParamOn1);
|
|
SPnt1.InfoSecond(Type,PtrSegIndex2[i],ParamOn2);
|
|
}
|
|
|
|
|
|
do {
|
|
Triok=Standard_True;
|
|
|
|
for(Standard_Integer tr=1;tr<Nbsp;tr++) {
|
|
SegIndex1=PtrSegIndex1[TriIndex[tr]];
|
|
SegIndex_1=PtrSegIndex1[TriIndex[tr+1]];
|
|
|
|
SegIndex2=PtrSegIndex2[TriIndex[tr]];
|
|
SegIndex_2=PtrSegIndex2[TriIndex[tr+1]];
|
|
|
|
if(SegIndex1 > SegIndex_1) {
|
|
Standard_Integer q=TriIndex[tr];
|
|
TriIndex[tr]=TriIndex[tr+1];
|
|
TriIndex[tr+1]=q;
|
|
Triok=Standard_False;
|
|
}
|
|
else if(SegIndex1 == SegIndex_1) {
|
|
if(SegIndex2 > SegIndex_2) {
|
|
Standard_Integer q=TriIndex[tr];
|
|
TriIndex[tr]=TriIndex[tr+1];
|
|
TriIndex[tr+1]=q;
|
|
Triok=Standard_False;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
while(Triok==Standard_False);
|
|
|
|
//-- supression des doublons Si Si !
|
|
for(i=1; i<Nbsp;i++) {
|
|
if( (PtrSegIndex1[TriIndex[i]] == PtrSegIndex1[TriIndex[i+1]])
|
|
&& (PtrSegIndex2[TriIndex[i]] == PtrSegIndex2[TriIndex[i+1]])) {
|
|
TriIndex[i]=-i;
|
|
}
|
|
}
|
|
|
|
for(Standard_Integer sp=1; sp <= Nbsp; sp++) {
|
|
if(TriIndex[sp]>0) {
|
|
const Intf_SectionPoint& SPnt = InterPP.PntValue(TriIndex[sp]);
|
|
|
|
SPnt.InfoFirst(Type,SegIndex1,ParamOn1);
|
|
SPnt.InfoSecond(Type,SegIndex2,ParamOn2);
|
|
|
|
if(Abs(SegIndex1-SegIndex2)>1) {
|
|
|
|
EIP.Perform(Poly1,Poly1,SegIndex1,SegIndex2,ParamOn1,ParamOn2);
|
|
if(EIP.NbRoots()>=1) {
|
|
//--------------------------------------------------------------------
|
|
//-- It is checked if the found point is a root
|
|
//--------------------------------------------------------------------
|
|
EIP.Roots(U,V);
|
|
|
|
TheCurveTool::D1(C1,U,P1,Tan1);
|
|
TheCurveTool::D1(C1,V,P2,Tan2);
|
|
Standard_Real Dist = P1.Distance(P2);
|
|
Standard_Real EpsX1 = 10.0*TheCurveTool::EpsX(C1);
|
|
|
|
if(Abs(U-V)<=EpsX1) {
|
|
//-----------------------------------------
|
|
//-- Solution not valid
|
|
//-- The maths should have converged in a
|
|
//-- trivial solution ( point U = V )
|
|
//-----------------------------------------
|
|
Dist = TolConf+1.0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------
|
|
//-- It is checked if the point (u,v) already exists
|
|
//--
|
|
done = Standard_True;
|
|
Standard_Integer nbp=NbPoints();
|
|
|
|
for(Standard_Integer p=1; p<=nbp; p++) {
|
|
const IntRes2d_IntersectionPoint& P=Point(p);
|
|
if(Abs(U-P.ParamOnFirst()) <= EpsX1) {
|
|
if(Abs(V-P.ParamOnSecond()) <= EpsX1) {
|
|
Dist = TolConf+1.0; p+=nbp;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(Dist <= TolConf) { //-- Or the point is already present
|
|
IntRes2d_Position Pos1 = IntRes2d_Middle;
|
|
IntRes2d_Position Pos2 = IntRes2d_Middle;
|
|
IntRes2d_Transition Trans1,Trans2;
|
|
//-----------------------------------------------------------------
|
|
//-- Calculate Positions of Points on the curve
|
|
//--
|
|
if(P1.Distance(DomainOnCurve1.FirstPoint())<=DomainOnCurve1.FirstTolerance())
|
|
Pos1 = IntRes2d_Head;
|
|
else if(P1.Distance(DomainOnCurve1.LastPoint())<=DomainOnCurve1.LastTolerance())
|
|
Pos1 = IntRes2d_End;
|
|
|
|
if(P2.Distance(DomainOnCurve2.FirstPoint())<=DomainOnCurve2.FirstTolerance())
|
|
Pos2 = IntRes2d_Head;
|
|
else if(P2.Distance(DomainOnCurve2.LastPoint())<=DomainOnCurve2.LastTolerance())
|
|
Pos2 = IntRes2d_End;
|
|
//-----------------------------------------------------------------
|
|
if(IntImpParGen::DetermineTransition( Pos1,Tan1,Trans1
|
|
,Pos2,Tan2,Trans2
|
|
,TolConf) == Standard_False)
|
|
{
|
|
TheCurveTool::D2(C1,U,P1,Tan1,Norm1);
|
|
TheCurveTool::D2(C1,V,P2,Tan2,Norm2);
|
|
IntImpParGen::DetermineTransition( Pos1,Tan1,Norm1,Trans1
|
|
,Pos2,Tan2,Norm2,Trans2
|
|
,TolConf);
|
|
}
|
|
IntRes2d_IntersectionPoint IP(P1,U,V,Trans1,Trans2,Standard_False);
|
|
Insert(IP);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
delete [] TriIndex;
|
|
delete [] PtrSegIndex1;
|
|
delete [] PtrSegIndex2;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
//-- Processing of TangentZone
|
|
//----------------------------------------------------------------------
|
|
Standard_Integer Nbtz = InterPP.NbTangentZones();
|
|
for(Standard_Integer tz=1; tz <= Nbtz; tz++) {
|
|
Standard_Integer NbPnts = InterPP.ZoneValue(tz).NumberOfPoints();
|
|
//====================================================================
|
|
//== Find the first and the last point in the tangency zone.
|
|
//====================================================================
|
|
Standard_Real ParamSupOnCurve2,ParamInfOnCurve2;
|
|
Standard_Real ParamSupOnCurve1,ParamInfOnCurve1;
|
|
// Standard_Integer SegIndex,SegIndex1onP1,SegIndex1onP2,SegIndex2onP1,SegIndex2onP2;
|
|
Standard_Integer SegIndex1onP1,SegIndex1onP2;
|
|
Intf_PIType Type;
|
|
Standard_Real ParamOnLine;
|
|
Standard_Real PolyUInf,PolyUSup,PolyVInf,PolyVSup;
|
|
ParamSupOnCurve2=ParamSupOnCurve1=PolyUSup=PolyVSup=-RealLast();
|
|
ParamInfOnCurve2=ParamInfOnCurve1=PolyUInf=PolyVInf= RealLast();
|
|
for(Standard_Integer qq=1;qq<=NbPnts;qq++) {
|
|
const Intf_SectionPoint& SPnt1 = InterPP.ZoneValue(tz).GetPoint(qq);
|
|
//====================================================================
|
|
//== The zones of tangency are discretized
|
|
//== Test of stop : Check if
|
|
//== (Deflection < Tolerance)
|
|
//== Or (Sample < EpsX) (normally the first condition is
|
|
//== more strict)
|
|
//====================================================================
|
|
// Standard_Real _PolyUInf,_PolyUSup,_PolyVInf,_PolyVSup;
|
|
Standard_Real _PolyUInf,_PolyVInf;
|
|
|
|
SPnt1.InfoFirst(Type,SegIndex1onP1,ParamOnLine);
|
|
if(SegIndex1onP1 > Poly1.NbSegments()) { SegIndex1onP1--; ParamOnLine = 1.0; }
|
|
if(SegIndex1onP1 <= 0) { SegIndex1onP1=1; ParamOnLine = 0.0; }
|
|
_PolyUInf = Poly1.ApproxParamOnCurve(SegIndex1onP1,ParamOnLine);
|
|
|
|
SPnt1.InfoSecond(Type,SegIndex1onP2,ParamOnLine);
|
|
if(SegIndex1onP2 > Poly1.NbSegments()) { SegIndex1onP2--; ParamOnLine = 1.0; }
|
|
if(SegIndex1onP2 <= 0) { SegIndex1onP2=1; ParamOnLine = 0.0; }
|
|
_PolyVInf = Poly1.ApproxParamOnCurve(SegIndex1onP2,ParamOnLine);
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
if(ParamInfOnCurve1 > _PolyUInf) ParamInfOnCurve1=_PolyUInf;
|
|
if(ParamInfOnCurve2 > _PolyVInf) ParamInfOnCurve2=_PolyVInf;
|
|
|
|
if(ParamSupOnCurve1 < _PolyUInf) ParamSupOnCurve1=_PolyUInf;
|
|
if(ParamSupOnCurve2 < _PolyVInf) ParamSupOnCurve2=_PolyVInf;
|
|
}
|
|
|
|
PolyUInf= ParamInfOnCurve1;
|
|
PolyUSup= ParamSupOnCurve1;
|
|
PolyVInf= ParamInfOnCurve2;
|
|
PolyVSup= ParamSupOnCurve2;
|
|
|
|
TheCurveTool::D0(C1,PolyUInf,P1);
|
|
TheCurveTool::D0(C1,PolyVInf,P2);
|
|
Standard_Real distmemesens = P1.SquareDistance(P2);
|
|
TheCurveTool::D0(C1,PolyVSup,P2);
|
|
Standard_Real distdiffsens = P1.SquareDistance(P2);
|
|
if(distmemesens > distdiffsens) {
|
|
Standard_Real qwerty=PolyVInf; PolyVInf=PolyVSup; PolyVSup=qwerty;
|
|
}
|
|
|
|
//-----------------------------------------------------------------
|
|
//-- Calculate Positions of Points on the curve and
|
|
//-- Transitions on each limit of the segment
|
|
|
|
IntRes2d_Position Pos1 = IntRes2d_Middle;
|
|
IntRes2d_Position Pos2 = IntRes2d_Middle;
|
|
IntRes2d_Transition Trans1,Trans2;
|
|
|
|
TheCurveTool::D1(C1,PolyUInf,P1,Tan1);
|
|
TheCurveTool::D1(C1,PolyVInf,P2,Tan2);
|
|
|
|
if(P1.Distance(DomainOnCurve1.FirstPoint())<=DomainOnCurve1.FirstTolerance()) {
|
|
Pos1 = IntRes2d_Head;
|
|
}
|
|
else if(P1.Distance(DomainOnCurve1.LastPoint())<=DomainOnCurve1.LastTolerance()) {
|
|
Pos1 = IntRes2d_End;
|
|
}
|
|
if(P2.Distance(DomainOnCurve2.FirstPoint())<=DomainOnCurve2.FirstTolerance()) {
|
|
Pos2 = IntRes2d_Head;
|
|
}
|
|
else if(P2.Distance(DomainOnCurve2.LastPoint())<=DomainOnCurve2.LastTolerance()) {
|
|
Pos2 = IntRes2d_End;
|
|
}
|
|
|
|
if(Pos1==IntRes2d_Middle && Pos2!=IntRes2d_Middle) {
|
|
PolyUInf=TheProjPCur::FindParameter( C1,P2,D1.FirstParameter(),D1.LastParameter(),TheCurveTool::EpsX(C1));
|
|
}
|
|
else if(Pos1!=IntRes2d_Middle && Pos2==IntRes2d_Middle) {
|
|
PolyVInf=TheProjPCur::FindParameter( C1,P1,D1.FirstParameter(),D1.LastParameter(),TheCurveTool::EpsX(C1));
|
|
}
|
|
else if(Abs(ParamInfOnCurve1-ParamSupOnCurve1) > Abs(ParamInfOnCurve2-ParamSupOnCurve2)) {
|
|
PolyVInf=TheProjPCur::FindParameter( C1,P1,D1.FirstParameter(),D1.LastParameter(),TheCurveTool::EpsX(C1));
|
|
}
|
|
else {
|
|
PolyUInf=TheProjPCur::FindParameter( C1,P2,D1.FirstParameter(),D1.LastParameter(),TheCurveTool::EpsX(C1));
|
|
}
|
|
|
|
|
|
|
|
if(IntImpParGen::DetermineTransition( Pos1,Tan1,Trans1,Pos2,Tan2,Trans2,TolConf)
|
|
== Standard_False)
|
|
{
|
|
TheCurveTool::D2(C1,PolyUInf,P1,Tan1,Norm1);
|
|
TheCurveTool::D2(C1,PolyVInf,P2,Tan2,Norm2);
|
|
IntImpParGen::DetermineTransition(Pos1,Tan1,Norm1,Trans1,
|
|
Pos2,Tan2,Norm2,Trans2,TolConf);
|
|
}
|
|
IntRes2d_IntersectionPoint PtSeg1(P1,PolyUInf,PolyVInf
|
|
,Trans1,Trans2,Standard_False);
|
|
//----------------------------------------------------------------------
|
|
|
|
if((Abs(PolyUInf-PolyUSup) <= TheCurveTool::EpsX(C1)) ||
|
|
(Abs(PolyVInf-PolyVSup) <= TheCurveTool::EpsX(C1)))
|
|
{
|
|
//bad segment
|
|
}
|
|
else
|
|
{
|
|
TheCurveTool::D1(C1,PolyUSup,P1,Tan1);
|
|
TheCurveTool::D1(C1,PolyVSup,P2,Tan2);
|
|
Pos1 = IntRes2d_Middle; Pos2 = IntRes2d_Middle;
|
|
|
|
if(P1.Distance(DomainOnCurve1.FirstPoint())<=DomainOnCurve1.FirstTolerance()) {
|
|
Pos1 = IntRes2d_Head;
|
|
}
|
|
else if(P1.Distance(DomainOnCurve1.LastPoint())<=DomainOnCurve1.LastTolerance()) {
|
|
Pos1 = IntRes2d_End;
|
|
}
|
|
if(P2.Distance(DomainOnCurve2.FirstPoint())<=DomainOnCurve2.FirstTolerance()) {
|
|
Pos2 = IntRes2d_Head;
|
|
}
|
|
else if(P2.Distance(DomainOnCurve2.LastPoint())<=DomainOnCurve2.LastTolerance()) {
|
|
Pos2 = IntRes2d_End;
|
|
}
|
|
|
|
|
|
if(Pos1==IntRes2d_Middle && Pos2!=IntRes2d_Middle) {
|
|
PolyUSup=TheProjPCur::FindParameter( C1,P2,D1.FirstParameter(),D1.LastParameter(),TheCurveTool::EpsX(C1));
|
|
}
|
|
else if(Pos1!=IntRes2d_Middle && Pos2==IntRes2d_Middle) {
|
|
PolyVSup=TheProjPCur::FindParameter( C1,P1,D1.FirstParameter(),D1.LastParameter(),TheCurveTool::EpsX(C1));
|
|
}
|
|
else if(Abs(ParamInfOnCurve1-ParamSupOnCurve1) > Abs(ParamInfOnCurve2-ParamSupOnCurve2)) {
|
|
PolyVSup=TheProjPCur::FindParameter( C1,P1,D1.FirstParameter(),D1.LastParameter(),TheCurveTool::EpsX(C1));
|
|
}
|
|
else {
|
|
PolyUSup=TheProjPCur::FindParameter( C1,P2,D1.FirstParameter(),D1.LastParameter(),TheCurveTool::EpsX(C1));
|
|
}
|
|
|
|
if(IntImpParGen::DetermineTransition( Pos1,Tan1,Trans1,Pos2,Tan2,Trans2,TolConf)
|
|
==Standard_False) {
|
|
TheCurveTool::D2(C1,PolyUSup,P1,Tan1,Norm1);
|
|
TheCurveTool::D2(C1,PolyVSup,P2,Tan2,Norm2);
|
|
IntImpParGen::DetermineTransition(Pos1,Tan1,Norm1,Trans1,
|
|
Pos2,Tan2,Norm2,Trans2,TolConf);
|
|
}
|
|
IntRes2d_IntersectionPoint PtSeg2(P1,PolyUSup,PolyVSup
|
|
,Trans1,Trans2,Standard_False);
|
|
|
|
Standard_Boolean Oppos = (Tan1.Dot(Tan2) > 0.0)? Standard_False : Standard_True;
|
|
if(ParamInfOnCurve1 > ParamSupOnCurve1) {
|
|
IntRes2d_IntersectionSegment Seg(PtSeg2,PtSeg1,Oppos,Standard_False);
|
|
Append(Seg);
|
|
}
|
|
else {
|
|
IntRes2d_IntersectionSegment Seg(PtSeg1,PtSeg2,Oppos,Standard_False);
|
|
Append(Seg);
|
|
}
|
|
}
|
|
} //end of processing of TangentZone
|
|
|
|
done = Standard_True;
|
|
}
|
|
|
|
|
|
Standard_Boolean HeadOrEndPoint( const IntRes2d_Domain& D1
|
|
,const TheCurve& C1
|
|
,const Standard_Real tu
|
|
,const IntRes2d_Domain& D2
|
|
,const TheCurve& C2
|
|
,const Standard_Real tv
|
|
,const Standard_Real TolConf
|
|
,IntRes2d_IntersectionPoint& IntPt
|
|
,Standard_Boolean& HeadOn1
|
|
,Standard_Boolean& HeadOn2
|
|
,Standard_Boolean& EndOn1
|
|
,Standard_Boolean& EndOn2
|
|
,Standard_Integer PosSegment) {
|
|
|
|
gp_Pnt2d P1,P2,SP1,SP2;
|
|
gp_Vec2d T1,T2,N1,N2;
|
|
Standard_Real u=tu;
|
|
Standard_Real v=tv;
|
|
Standard_Real svu = u;
|
|
Standard_Real svv = v;
|
|
|
|
TheCurveTool::D1(C1,u,P1,T1);
|
|
TheCurveTool::D1(C2,v,P2,T2);
|
|
|
|
IntRes2d_Position Pos1 = IntRes2d_Middle;
|
|
IntRes2d_Position Pos2 = IntRes2d_Middle;
|
|
IntRes2d_Transition Trans1,Trans2;
|
|
|
|
//----------------------------------------------------------------------
|
|
//-- Head On 1 : Head1 <-> P2
|
|
if(P2.Distance(D1.FirstPoint())<=D1.FirstTolerance()) {
|
|
Pos1 = IntRes2d_Head;
|
|
HeadOn1 = Standard_True;
|
|
SP1 = D1.FirstPoint();
|
|
u = D1.FirstParameter();
|
|
}
|
|
//----------------------------------------------------------------------
|
|
//-- End On 1 : End1 <-> P2
|
|
else if(P2.Distance(D1.LastPoint())<=D1.LastTolerance()) {
|
|
Pos1 = IntRes2d_End;
|
|
EndOn1 = Standard_True;
|
|
SP1 = D1.LastPoint();
|
|
u = D1.LastParameter();
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
//-- Head On 2 : Head2 <-> P1
|
|
else if(P1.Distance(D2.FirstPoint())<=D2.FirstTolerance()) {
|
|
Pos2 = IntRes2d_Head;
|
|
HeadOn2 = Standard_True;
|
|
SP2 = D2.FirstPoint();
|
|
v = D2.FirstParameter();
|
|
}
|
|
//----------------------------------------------------------------------
|
|
//-- End On 2 : End2 <-> P1
|
|
else if(P1.Distance(D2.LastPoint())<=D2.LastTolerance()) {
|
|
Pos2 = IntRes2d_End;
|
|
EndOn2 = Standard_True;
|
|
SP2 = D2.LastPoint();
|
|
v = D2.LastParameter();
|
|
}
|
|
|
|
Standard_Real EpsX1 = TheCurveTool::EpsX(C1);
|
|
Standard_Real EpsX2 = TheCurveTool::EpsX(C2);
|
|
|
|
if((Pos1 != IntRes2d_Middle)||(Pos2 != IntRes2d_Middle)) {
|
|
if(Pos1 == IntRes2d_Middle) {
|
|
if(Abs(u-D1.FirstParameter()) <= EpsX1) {
|
|
Pos1 = IntRes2d_Head;
|
|
P1 = D1.FirstPoint();
|
|
HeadOn1 = Standard_True;
|
|
}
|
|
else if(Abs(u-D1.LastParameter()) <= EpsX1) {
|
|
Pos1 = IntRes2d_End;
|
|
P1 = D1.LastPoint();
|
|
EndOn1 = Standard_True;
|
|
}
|
|
}
|
|
else if(u!=tu) {
|
|
P1 = SP1;
|
|
}
|
|
|
|
|
|
if(Pos2 == IntRes2d_Middle) {
|
|
if(Abs(v-D2.FirstParameter()) <= EpsX2) {
|
|
Pos2 = IntRes2d_Head;
|
|
HeadOn2 = Standard_True;
|
|
P2 = D2.FirstPoint();
|
|
if(Pos1 != IntRes2d_Middle) {
|
|
P1.SetCoord(0.5*(P1.X()+P2.X()),0.5*(P1.Y()+P2.Y()));
|
|
}
|
|
else {
|
|
P2 = P1;
|
|
}
|
|
}
|
|
else if(Abs(v-D2.LastParameter()) <= EpsX2) {
|
|
Pos2 = IntRes2d_End;
|
|
EndOn2 = Standard_True;
|
|
P2 = D2.LastPoint();
|
|
if(Pos1 != IntRes2d_Middle) {
|
|
P1.SetCoord(0.5*(P1.X()+P2.X()),0.5*(P1.Y()+P2.Y()));
|
|
}
|
|
else {
|
|
P2 = P1;
|
|
}
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
//-- It is tested if a point at the end of segment already has its transitions
|
|
//-- If Yes, the new point is not created
|
|
//--
|
|
//-- PosSegment = 1 if Head Head
|
|
//-- 2 if Head End
|
|
//-- 4 if End Head
|
|
//-- 8 if End End
|
|
//--------------------------------------------------------------------
|
|
if(Pos1 == IntRes2d_Head) {
|
|
if((Pos2 == IntRes2d_Head)&&(PosSegment & 1)) return(Standard_False);
|
|
if((Pos2 == IntRes2d_End )&&(PosSegment & 2)) return(Standard_False);
|
|
}
|
|
else if(Pos1 == IntRes2d_End) {
|
|
if((Pos2 == IntRes2d_Head)&&(PosSegment & 4)) return(Standard_False);
|
|
if((Pos2 == IntRes2d_End )&&(PosSegment & 8)) return(Standard_False);
|
|
}
|
|
|
|
|
|
if(IntImpParGen::DetermineTransition( Pos1,T1,Trans1,Pos2,T2,Trans2,TolConf)
|
|
== Standard_False) {
|
|
TheCurveTool::D2(C1,svu,P1,T1,N1);
|
|
TheCurveTool::D2(C2,svv,P2,T2,N2);
|
|
IntImpParGen::DetermineTransition(Pos1,T1,N1,Trans1,
|
|
Pos2,T2,N2,Trans2,TolConf);
|
|
}
|
|
IntPt.SetValues(P1,u,v,Trans1,Trans2,Standard_False);
|
|
return(Standard_True);
|
|
}
|
|
else
|
|
return(Standard_False);
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : Perform
|
|
//purpose : Base method to perform polyline / polyline intersection for
|
|
// pair of curves.
|
|
//=======================================================================
|
|
void IntCurve_IntPolyPolyGen::Perform(const TheCurve& C1,
|
|
const IntRes2d_Domain& D1,
|
|
const TheCurve& C2,
|
|
const IntRes2d_Domain& D2,
|
|
const Standard_Real TolConf,
|
|
const Standard_Real Tol,
|
|
const Standard_Integer NbIter,
|
|
const Standard_Real DeltaU,
|
|
const Standard_Real DeltaV)
|
|
{
|
|
Standard_Integer nbsamplesOnC1,nbsamplesOnC2;
|
|
done = Standard_False;
|
|
|
|
if(NbIter>NBITER_MAX_POLYGON) return;
|
|
|
|
// Number of samples running.
|
|
nbsamplesOnC1 = TheCurveTool::NbSamples(C1,D1.FirstParameter(),D1.LastParameter());
|
|
nbsamplesOnC2 = TheCurveTool::NbSamples(C2,D2.FirstParameter(),D2.LastParameter());
|
|
|
|
if (NbIter == 0)
|
|
{
|
|
// Minimal number of points.
|
|
nbsamplesOnC1 = Max(nbsamplesOnC1, myMinPntNb);
|
|
nbsamplesOnC2 = Max(nbsamplesOnC2, myMinPntNb);
|
|
}
|
|
else
|
|
{
|
|
// Increase number of samples in second and next iterations.
|
|
nbsamplesOnC1=(5 * (nbsamplesOnC1 * NbIter)) / 4;
|
|
nbsamplesOnC2=(5 * (nbsamplesOnC2 * NbIter)) / 4;
|
|
}
|
|
|
|
NCollection_Handle<IntCurve_ThePolygon2d>
|
|
aPoly1 = new IntCurve_ThePolygon2d(C1,nbsamplesOnC1,D1,Tol),
|
|
aPoly2 = new IntCurve_ThePolygon2d(C2,nbsamplesOnC2,D2,Tol);
|
|
|
|
if( (aPoly1->DeflectionOverEstimation() > TolConf) &&
|
|
(aPoly2->DeflectionOverEstimation() > TolConf))
|
|
{
|
|
const Standard_Real aDeflectionSum =
|
|
Max(aPoly1->DeflectionOverEstimation(), TolConf) +
|
|
Max(aPoly2->DeflectionOverEstimation(), TolConf);
|
|
|
|
if (nbsamplesOnC2 > nbsamplesOnC1)
|
|
{
|
|
aPoly2->ComputeWithBox(C2, aPoly1->Bounding());
|
|
aPoly1->SetDeflectionOverEstimation(aDeflectionSum);
|
|
aPoly1->ComputeWithBox(C1, aPoly2->Bounding());
|
|
}
|
|
else
|
|
{
|
|
aPoly1->ComputeWithBox(C1, aPoly2->Bounding());
|
|
aPoly2->SetDeflectionOverEstimation(aDeflectionSum);
|
|
aPoly2->ComputeWithBox(C2, aPoly1->Bounding());
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
//-- if the deflection less then the Tolerance of Confusion
|
|
//-- Then the deflection of the polygon is set in TolConf
|
|
//-- (Detection of Tangency Zones)
|
|
//----------------------------------------------------------------------
|
|
|
|
if(aPoly1->DeflectionOverEstimation() < TolConf) {
|
|
aPoly1->SetDeflectionOverEstimation(TolConf);
|
|
}
|
|
if(aPoly2->DeflectionOverEstimation() < TolConf) {
|
|
aPoly2->SetDeflectionOverEstimation(TolConf);
|
|
}
|
|
// for case when a few polygon points were replaced by line
|
|
// if exact solution was not found
|
|
// then search of precise solution will be repeated
|
|
// for polygon contains all initial points
|
|
// secondary search will be performed only for case when initial points
|
|
// were dropped
|
|
Standard_Boolean isFullRepresentation = ( aPoly1->NbSegments() == nbsamplesOnC1 &&
|
|
aPoly2->NbSegments() == nbsamplesOnC2 );
|
|
|
|
if( !findIntersect( C1, D1, C2, D2, TolConf, Tol, NbIter,
|
|
DeltaU, DeltaV, *aPoly1, *aPoly2, isFullRepresentation ) && !isFullRepresentation )
|
|
{
|
|
if(aPoly1->NbSegments() < nbsamplesOnC1)
|
|
{
|
|
aPoly1 = new IntCurve_ThePolygon2d(C1,nbsamplesOnC1,D1,Tol);
|
|
}
|
|
if(aPoly2->NbSegments() < nbsamplesOnC2)
|
|
{
|
|
aPoly2 = new IntCurve_ThePolygon2d(C2,nbsamplesOnC2,D2,Tol);
|
|
}
|
|
|
|
findIntersect( C1, D1, C2, D2, TolConf, Tol, NbIter,
|
|
DeltaU, DeltaV, *aPoly1, *aPoly2,
|
|
Standard_True);
|
|
|
|
}
|
|
|
|
done = Standard_True;
|
|
}
|
|
|
|
//======================================================================
|
|
// Purpose : findIntersect
|
|
//======================================================================
|
|
|
|
Standard_Boolean IntCurve_IntPolyPolyGen::findIntersect(
|
|
const TheCurve& C1,
|
|
const IntRes2d_Domain& D1,
|
|
const TheCurve& C2,
|
|
const IntRes2d_Domain& D2,
|
|
const Standard_Real TolConf,
|
|
const Standard_Real Tol,
|
|
const Standard_Integer NbIter,
|
|
const Standard_Real DeltaU,
|
|
const Standard_Real DeltaV,
|
|
const IntCurve_ThePolygon2d& thePoly1,
|
|
const IntCurve_ThePolygon2d& thePoly2,
|
|
Standard_Boolean isFullPolygon )
|
|
{
|
|
|
|
gp_Vec2d Tan1,Tan2,Norm1,Norm2;
|
|
gp_Pnt2d P1,P2;
|
|
Intf_InterferencePolygon2d InterPP(thePoly1,thePoly2);
|
|
IntCurve_ExactIntersectionPoint EIP(C1,C2,TolConf);
|
|
Standard_Real U = 0., V = 0.;
|
|
Standard_Boolean AnErrorOccurred = Standard_False;
|
|
done = Standard_True; // To prevent exception in nbp=NbPoints();
|
|
//----------------------------------------------------------------------
|
|
//-- Processing of SectionPoint
|
|
//----------------------------------------------------------------------
|
|
Standard_Integer Nbsp = InterPP.NbSectionPoints();
|
|
for(Standard_Integer sp=1; sp <= Nbsp; sp++) {
|
|
const Intf_SectionPoint& SPnt = InterPP.PntValue(sp);
|
|
Standard_Integer SegIndex1,SegIndex2;
|
|
Standard_Real ParamOn1,ParamOn2;
|
|
Intf_PIType Type;
|
|
|
|
SPnt.InfoFirst(Type,SegIndex1,ParamOn1);
|
|
SPnt.InfoSecond(Type,SegIndex2,ParamOn2);
|
|
EIP.Perform(thePoly1,thePoly2,SegIndex1,SegIndex2,ParamOn1,ParamOn2);
|
|
AnErrorOccurred = EIP.AnErrorOccurred();
|
|
|
|
if( !EIP.NbRoots() && !isFullPolygon)
|
|
return Standard_False;
|
|
|
|
if(AnErrorOccurred)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
//-- It is checked if the found point is really a root
|
|
//--------------------------------------------------------------------
|
|
|
|
EIP.Roots(U,V);
|
|
TheCurveTool::D1(C1,U,P1,Tan1);
|
|
TheCurveTool::D1(C2,V,P2,Tan2);
|
|
Standard_Real Dist = P1.Distance(P2);
|
|
if(EIP.NbRoots() == 0 && Dist > TolConf)
|
|
{
|
|
IntRes2d_Transition aTrans;
|
|
IntRes2d_IntersectionPoint aPInt(P1, U, V, aTrans, aTrans, Standard_False);
|
|
Standard_Real aT1f, aT1l, aT2f, aT2l;
|
|
aT1f= thePoly1.ApproxParamOnCurve(SegIndex1, 0.0);
|
|
aT1l= thePoly1.ApproxParamOnCurve(SegIndex1, 1.0);
|
|
aT2f= thePoly2.ApproxParamOnCurve(SegIndex2, 0.0);
|
|
aT2l= thePoly2.ApproxParamOnCurve(SegIndex2, 1.0);
|
|
//
|
|
Standard_Integer aMaxCount = 16, aCount = 0;
|
|
GetIntersection(C1, aT1f, aT1l, C2, aT2f, aT2l, TolConf, aMaxCount,
|
|
aPInt, Dist, aCount);
|
|
U = aPInt.ParamOnFirst();
|
|
V = aPInt.ParamOnSecond();
|
|
TheCurveTool::D1(C1,U,P1,Tan1);
|
|
TheCurveTool::D1(C2,V,P2,Tan2);
|
|
Dist = P1.Distance(P2);
|
|
}
|
|
//-----------------------------------------------------------------
|
|
//-- It is checked if the point (u,v) does not exist already
|
|
//--
|
|
Standard_Integer nbp=NbPoints();
|
|
Standard_Real EpsX1 = 10.0*TheCurveTool::EpsX(C1);
|
|
Standard_Real EpsX2 = 10.0*TheCurveTool::EpsX(C2);
|
|
for(Standard_Integer p=1; p<=nbp; p++) {
|
|
const IntRes2d_IntersectionPoint& P=Point(p);
|
|
if(Abs(U-P.ParamOnFirst()) <= EpsX1) {
|
|
if(Abs(V-P.ParamOnSecond()) <= EpsX2) {
|
|
Dist = TolConf+1.0; p+=nbp;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(Dist <= TolConf) { //-- Or the point is already present
|
|
IntRes2d_Position Pos1 = IntRes2d_Middle;
|
|
IntRes2d_Position Pos2 = IntRes2d_Middle;
|
|
IntRes2d_Transition Trans1,Trans2;
|
|
//-----------------------------------------------------------------
|
|
//-- Calculate the Positions of Points on the curve
|
|
//--
|
|
if(P1.Distance(DomainOnCurve1.FirstPoint())<=DomainOnCurve1.FirstTolerance())
|
|
Pos1 = IntRes2d_Head;
|
|
else if(P1.Distance(DomainOnCurve1.LastPoint())<=DomainOnCurve1.LastTolerance())
|
|
Pos1 = IntRes2d_End;
|
|
|
|
if(P2.Distance(DomainOnCurve2.FirstPoint())<=DomainOnCurve2.FirstTolerance())
|
|
Pos2 = IntRes2d_Head;
|
|
else if(P2.Distance(DomainOnCurve2.LastPoint())<=DomainOnCurve2.LastTolerance())
|
|
Pos2 = IntRes2d_End;
|
|
//-----------------------------------------------------------------
|
|
//-- Calculate the Transitions (see IntImpParGen.cxx)
|
|
//--
|
|
if(IntImpParGen::DetermineTransition (Pos1, Tan1, Trans1, Pos2, Tan2, Trans2, TolConf) == Standard_False) {
|
|
TheCurveTool::D2(C1,U,P1,Tan1,Norm1);
|
|
TheCurveTool::D2(C2,V,P2,Tan2,Norm2);
|
|
IntImpParGen::DetermineTransition (Pos1, Tan1, Norm1, Trans1, Pos2, Tan2, Norm2, Trans2, TolConf);
|
|
}
|
|
IntRes2d_IntersectionPoint IP(P1,U,V,Trans1,Trans2,Standard_False);
|
|
Insert(IP);
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
//-- Processing of TangentZone
|
|
//----------------------------------------------------------------------
|
|
Standard_Integer Nbtz = InterPP.NbTangentZones();
|
|
for(Standard_Integer tz=1; tz <= Nbtz; tz++) {
|
|
Standard_Integer NbPnts = InterPP.ZoneValue(tz).NumberOfPoints();
|
|
//====================================================================
|
|
//== Find the first and the last point in the tangency zone.
|
|
//====================================================================
|
|
Standard_Real ParamSupOnCurve2,ParamInfOnCurve2;
|
|
Standard_Real ParamSupOnCurve1,ParamInfOnCurve1;
|
|
// Standard_Integer SegIndex,SegIndex1onP1,SegIndex1onP2,SegIndex2onP1,SegIndex2onP2;
|
|
Standard_Integer SegIndex1onP1,SegIndex1onP2;
|
|
Intf_PIType Type;
|
|
Standard_Real ParamOnLine;
|
|
Standard_Real PolyUInf,PolyUSup,PolyVInf,PolyVSup;
|
|
ParamSupOnCurve2=ParamSupOnCurve1=PolyUSup=PolyVSup=-RealLast();
|
|
ParamInfOnCurve2=ParamInfOnCurve1=PolyUInf=PolyVInf= RealLast();
|
|
for(Standard_Integer qq=1;qq<=NbPnts;qq++) {
|
|
const Intf_SectionPoint& SPnt1 = InterPP.ZoneValue(tz).GetPoint(qq);
|
|
//====================================================================
|
|
//== The zones of tangency are discretized
|
|
//== Test of stop : Check if
|
|
//== (Deflection < Tolerance)
|
|
//== Or (Sample < EpsX) (normally the first condition is
|
|
//== more strict)
|
|
//====================================================================
|
|
// Standard_Real _PolyUInf,_PolyUSup,_PolyVInf,_PolyVSup;
|
|
Standard_Real _PolyUInf,_PolyVInf;
|
|
|
|
SPnt1.InfoFirst(Type,SegIndex1onP1,ParamOnLine);
|
|
if(SegIndex1onP1 > thePoly1.NbSegments()) { SegIndex1onP1--; ParamOnLine = 1.0; }
|
|
if(SegIndex1onP1 <= 0) { SegIndex1onP1=1; ParamOnLine = 0.0; }
|
|
_PolyUInf = thePoly1.ApproxParamOnCurve(SegIndex1onP1,ParamOnLine);
|
|
|
|
SPnt1.InfoSecond(Type,SegIndex1onP2,ParamOnLine);
|
|
if(SegIndex1onP2 > thePoly2.NbSegments()) { SegIndex1onP2--; ParamOnLine = 1.0; }
|
|
if(SegIndex1onP2 <= 0) { SegIndex1onP2=1; ParamOnLine = 0.0; }
|
|
_PolyVInf = thePoly2.ApproxParamOnCurve(SegIndex1onP2,ParamOnLine);
|
|
|
|
//----------------------------------------------------------------------
|
|
|
|
if(ParamInfOnCurve1 > _PolyUInf) ParamInfOnCurve1=_PolyUInf;
|
|
if(ParamInfOnCurve2 > _PolyVInf) ParamInfOnCurve2=_PolyVInf;
|
|
|
|
if(ParamSupOnCurve1 < _PolyUInf) ParamSupOnCurve1=_PolyUInf;
|
|
if(ParamSupOnCurve2 < _PolyVInf) ParamSupOnCurve2=_PolyVInf;
|
|
}
|
|
|
|
PolyUInf= ParamInfOnCurve1;
|
|
PolyUSup= ParamSupOnCurve1;
|
|
PolyVInf= ParamInfOnCurve2;
|
|
PolyVSup= ParamSupOnCurve2;
|
|
|
|
TheCurveTool::D0(C1,PolyUInf,P1);
|
|
TheCurveTool::D0(C2,PolyVInf,P2);
|
|
Standard_Real distmemesens = P1.SquareDistance(P2);
|
|
TheCurveTool::D0(C2,PolyVSup,P2);
|
|
Standard_Real distdiffsens = P1.SquareDistance(P2);
|
|
if(distmemesens > distdiffsens) {
|
|
Standard_Real qwerty=PolyVInf; PolyVInf=PolyVSup; PolyVSup=qwerty;
|
|
}
|
|
|
|
if( ( (thePoly1.DeflectionOverEstimation() > TolConf)
|
|
||(thePoly2.DeflectionOverEstimation() > TolConf))
|
|
&&(NbIter<NBITER_MAX_POLYGON)) {
|
|
|
|
IntRes2d_Domain RecursD1( TheCurveTool::Value(C1,ParamInfOnCurve1)
|
|
,ParamInfOnCurve1,TolConf
|
|
,TheCurveTool::Value(C1,ParamSupOnCurve1)
|
|
,ParamSupOnCurve1,TolConf);
|
|
IntRes2d_Domain RecursD2( TheCurveTool::Value(C2,ParamInfOnCurve2)
|
|
,ParamInfOnCurve2,TolConf
|
|
,TheCurveTool::Value(C2,ParamSupOnCurve2)
|
|
,ParamSupOnCurve2,TolConf);
|
|
//-- thePoly1(2) are not deleted,
|
|
//-- finally they are destroyed.
|
|
//-- !! No untimely return !!
|
|
Perform(C1,RecursD1,C2,RecursD2,Tol,TolConf,NbIter+1,DeltaU,DeltaV);
|
|
}
|
|
else {
|
|
//-----------------------------------------------------------------
|
|
//-- Calculate Positions of Points on the curve and
|
|
//-- Transitions on each limit of the segment
|
|
|
|
IntRes2d_Position Pos1 = IntRes2d_Middle;
|
|
IntRes2d_Position Pos2 = IntRes2d_Middle;
|
|
IntRes2d_Transition Trans1,Trans2;
|
|
|
|
TheCurveTool::D1(C1,PolyUInf,P1,Tan1);
|
|
TheCurveTool::D1(C2,PolyVInf,P2,Tan2);
|
|
|
|
if(P1.Distance(DomainOnCurve1.FirstPoint())<=DomainOnCurve1.FirstTolerance()) {
|
|
Pos1 = IntRes2d_Head;
|
|
}
|
|
else if(P1.Distance(DomainOnCurve1.LastPoint())<=DomainOnCurve1.LastTolerance()) {
|
|
Pos1 = IntRes2d_End;
|
|
}
|
|
if(P2.Distance(DomainOnCurve2.FirstPoint())<=DomainOnCurve2.FirstTolerance()) {
|
|
Pos2 = IntRes2d_Head;
|
|
}
|
|
else if(P2.Distance(DomainOnCurve2.LastPoint())<=DomainOnCurve2.LastTolerance()) {
|
|
Pos2 = IntRes2d_End;
|
|
}
|
|
|
|
if(Pos1==IntRes2d_Middle && Pos2!=IntRes2d_Middle) {
|
|
PolyUInf=TheProjPCur::FindParameter( C1,P2,D1.FirstParameter(),D1.LastParameter(),TheCurveTool::EpsX(C1));
|
|
}
|
|
else if(Pos1!=IntRes2d_Middle && Pos2==IntRes2d_Middle) {
|
|
PolyVInf=TheProjPCur::FindParameter( C2,P1,D2.FirstParameter(),D2.LastParameter(),TheCurveTool::EpsX(C2));
|
|
}
|
|
else if(Abs(ParamInfOnCurve1-ParamSupOnCurve1) > Abs(ParamInfOnCurve2-ParamSupOnCurve2)) {
|
|
PolyVInf=TheProjPCur::FindParameter( C2,P1,D2.FirstParameter(),D2.LastParameter(),TheCurveTool::EpsX(C2));
|
|
}
|
|
else {
|
|
PolyUInf=TheProjPCur::FindParameter( C1,P2,D1.FirstParameter(),D1.LastParameter(),TheCurveTool::EpsX(C1));
|
|
}
|
|
|
|
|
|
|
|
if(IntImpParGen::DetermineTransition( Pos1,Tan1,Trans1,Pos2,Tan2,Trans2,TolConf)
|
|
== Standard_False)
|
|
{
|
|
TheCurveTool::D2(C1,PolyUInf,P1,Tan1,Norm1);
|
|
TheCurveTool::D2(C2,PolyVInf,P2,Tan2,Norm2);
|
|
IntImpParGen::DetermineTransition(Pos1,Tan1,Norm1,Trans1,
|
|
Pos2,Tan2,Norm2,Trans2,TolConf);
|
|
}
|
|
IntRes2d_IntersectionPoint PtSeg1(P1,PolyUInf,PolyVInf
|
|
,Trans1,Trans2,Standard_False);
|
|
//----------------------------------------------------------------------
|
|
|
|
if((Abs(PolyUInf-PolyUSup) <= TheCurveTool::EpsX(C1))
|
|
|| (Abs(PolyVInf-PolyVSup) <= TheCurveTool::EpsX(C2)))
|
|
{
|
|
Insert(PtSeg1);
|
|
}
|
|
else
|
|
{
|
|
TheCurveTool::D1(C1,PolyUSup,P1,Tan1);
|
|
TheCurveTool::D1(C2,PolyVSup,P2,Tan2);
|
|
Pos1 = IntRes2d_Middle; Pos2 = IntRes2d_Middle;
|
|
|
|
if(P1.Distance(DomainOnCurve1.FirstPoint())<=DomainOnCurve1.FirstTolerance()) {
|
|
Pos1 = IntRes2d_Head;
|
|
}
|
|
else if(P1.Distance(DomainOnCurve1.LastPoint())<=DomainOnCurve1.LastTolerance()) {
|
|
Pos1 = IntRes2d_End;
|
|
}
|
|
if(P2.Distance(DomainOnCurve2.FirstPoint())<=DomainOnCurve2.FirstTolerance()) {
|
|
Pos2 = IntRes2d_Head;
|
|
}
|
|
else if(P2.Distance(DomainOnCurve2.LastPoint())<=DomainOnCurve2.LastTolerance()) {
|
|
Pos2 = IntRes2d_End;
|
|
}
|
|
|
|
|
|
if(Pos1==IntRes2d_Middle && Pos2!=IntRes2d_Middle) {
|
|
PolyUSup=TheProjPCur::FindParameter( C1,P2,D1.FirstParameter(),D1.LastParameter(),TheCurveTool::EpsX(C1));
|
|
}
|
|
else if(Pos1!=IntRes2d_Middle && Pos2==IntRes2d_Middle) {
|
|
PolyVSup=TheProjPCur::FindParameter( C2,P1,D2.FirstParameter(),D2.LastParameter(),TheCurveTool::EpsX(C2));
|
|
}
|
|
else if(Abs(ParamInfOnCurve1-ParamSupOnCurve1) > Abs(ParamInfOnCurve2-ParamSupOnCurve2)) {
|
|
PolyVSup=TheProjPCur::FindParameter( C2,P1,D2.FirstParameter(),D2.LastParameter(),TheCurveTool::EpsX(C2));
|
|
}
|
|
else {
|
|
PolyUSup=TheProjPCur::FindParameter( C1,P2,D1.FirstParameter(),D1.LastParameter(),TheCurveTool::EpsX(C1));
|
|
}
|
|
|
|
if(IntImpParGen::DetermineTransition( Pos1,Tan1,Trans1,Pos2,Tan2,Trans2,TolConf)
|
|
==Standard_False) {
|
|
TheCurveTool::D2(C1,PolyUSup,P1,Tan1,Norm1);
|
|
TheCurveTool::D2(C2,PolyVSup,P2,Tan2,Norm2);
|
|
IntImpParGen::DetermineTransition(Pos1,Tan1,Norm1,Trans1,
|
|
Pos2,Tan2,Norm2,Trans2,TolConf);
|
|
}
|
|
IntRes2d_IntersectionPoint PtSeg2(P1,PolyUSup,PolyVSup
|
|
,Trans1,Trans2,Standard_False);
|
|
|
|
Standard_Boolean Oppos = (Tan1.Dot(Tan2) > 0.0)? Standard_False : Standard_True;
|
|
if(ParamInfOnCurve1 > ParamSupOnCurve1) {
|
|
IntRes2d_IntersectionSegment Seg(PtSeg2,PtSeg1,Oppos,Standard_False);
|
|
Append(Seg);
|
|
}
|
|
else {
|
|
IntRes2d_IntersectionSegment Seg(PtSeg1,PtSeg2,Oppos,Standard_False);
|
|
Append(Seg);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return Standard_True;
|
|
}
|
|
|
|
//======================================================================
|
|
// GetIntersection
|
|
//======================================================================
|
|
|
|
void GetIntersection(const TheCurve& theC1, const Standard_Real theT1f, const Standard_Real theT1l,
|
|
const TheCurve& theC2, const Standard_Real theT2f, const Standard_Real theT2l,
|
|
const Standard_Real theTolConf,
|
|
const Standard_Integer theMaxCount,
|
|
IntRes2d_IntersectionPoint& thePInt, Standard_Real& theDist,
|
|
Standard_Integer& theCount)
|
|
{
|
|
theCount++;
|
|
//
|
|
Standard_Real aTol2 = theTolConf*theTolConf;
|
|
Standard_Real aPTol1 = Max(100.*Epsilon(Max(Abs(theT1f), Abs(theT1l))), Precision::PConfusion());
|
|
Standard_Real aPTol2 = Max(100.*Epsilon(Max(Abs(theT2f), Abs(theT2l))), Precision::PConfusion());
|
|
gp_Pnt2d aP1f, aP1l, aP2f, aP2l;
|
|
Bnd_Box2d aB1, aB2;
|
|
//
|
|
TheCurveTool::D0(theC1, theT1f, aP1f);
|
|
TheCurveTool::D0(theC1, theT1l, aP1l);
|
|
aB1.Add(aP1f);
|
|
aB1.Add(aP1l);
|
|
aB1.Enlarge(theTolConf);
|
|
//
|
|
TheCurveTool::D0(theC2, theT2f, aP2f);
|
|
TheCurveTool::D0(theC2, theT2l, aP2l);
|
|
aB2.Add(aP2f);
|
|
aB2.Add(aP2l);
|
|
aB2.Enlarge(theTolConf);
|
|
//
|
|
if(aB1.IsOut(aB2))
|
|
{
|
|
theCount--;
|
|
return;
|
|
}
|
|
//
|
|
Standard_Boolean isSmall1 = (theT1l - theT1f) <= aPTol1 || aP1f.SquareDistance(aP1l) / 4. <= aTol2;
|
|
Standard_Boolean isSmall2 = (theT2l - theT2f) <= aPTol2 || aP2f.SquareDistance(aP2l) / 4. <= aTol2;
|
|
|
|
if((isSmall1 && isSmall2) || (theCount > theMaxCount))
|
|
{
|
|
//Seems to be intersection
|
|
//Simple treatment of segment intersection
|
|
gp_XY aPnts1[3] = {aP1f.XY(), (aP1f.XY() + aP1l.XY()) / 2., aP1l.XY()};
|
|
gp_XY aPnts2[3] = {aP2f.XY(), (aP2f.XY() + aP2l.XY()) / 2., aP2l.XY()};
|
|
Standard_Integer i, j, imin = -1, jmin = -1;
|
|
Standard_Real dmin = RealLast(), d;
|
|
for(i = 0; i < 3; i++)
|
|
{
|
|
for(j = 0; j < 3; j++)
|
|
{
|
|
d = (aPnts1[i] - aPnts2[j]).SquareModulus();
|
|
if(d < dmin)
|
|
{
|
|
dmin=d;
|
|
imin = i;
|
|
jmin = j;
|
|
}
|
|
}
|
|
}
|
|
//
|
|
dmin = Sqrt(dmin);
|
|
if(theDist > dmin)
|
|
{
|
|
theDist = dmin;
|
|
//
|
|
Standard_Real t1;
|
|
if(imin == 0)
|
|
{
|
|
t1 = theT1f;
|
|
}
|
|
else if(imin == 1)
|
|
{
|
|
t1 = (theT1f + theT1l) / 2.;
|
|
}
|
|
else
|
|
{
|
|
t1 = theT1l;
|
|
}
|
|
//
|
|
Standard_Real t2;
|
|
if(jmin == 0)
|
|
{
|
|
t2 = theT2f;
|
|
}
|
|
else if(jmin == 1)
|
|
{
|
|
t2 = (theT2f + theT2l) / 2.;
|
|
}
|
|
else
|
|
{
|
|
t2 = theT2l;
|
|
}
|
|
//
|
|
gp_Pnt2d aPint((aPnts1[imin] + aPnts2[jmin])/2.);
|
|
//
|
|
IntRes2d_Transition aTrans1, aTrans2;
|
|
thePInt.SetValues(aPint, t1, t2, aTrans1, aTrans2, Standard_False);
|
|
}
|
|
theCount--;
|
|
return;
|
|
}
|
|
|
|
if(isSmall1)
|
|
{
|
|
Standard_Real aT2m = (theT2l + theT2f) / 2.;
|
|
GetIntersection(theC1, theT1f, theT1l, theC2, theT2f, aT2m, theTolConf, theMaxCount, thePInt, theDist, theCount);
|
|
GetIntersection(theC1, theT1f, theT1l, theC2, aT2m, theT2l, theTolConf, theMaxCount, thePInt, theDist, theCount);
|
|
}
|
|
else if(isSmall2)
|
|
{
|
|
Standard_Real aT1m = (theT1l + theT1f) / 2.;
|
|
GetIntersection(theC1, theT1f, aT1m, theC2, theT2f, theT2l, theTolConf, theMaxCount, thePInt, theDist, theCount);
|
|
GetIntersection(theC1, aT1m, theT1l, theC2, theT2f, theT2l, theTolConf, theMaxCount, thePInt, theDist, theCount);
|
|
}
|
|
else
|
|
{
|
|
Standard_Real aT1m = (theT1l + theT1f) / 2.;
|
|
Standard_Real aT2m = (theT2l + theT2f) / 2.;
|
|
GetIntersection(theC1, theT1f, aT1m, theC2, theT2f, aT2m, theTolConf, theMaxCount, thePInt, theDist, theCount);
|
|
GetIntersection(theC1, theT1f, aT1m, theC2, aT2m, theT2l, theTolConf, theMaxCount, thePInt, theDist, theCount);
|
|
GetIntersection(theC1, aT1m, theT1l, theC2, theT2f, aT2m, theTolConf, theMaxCount, thePInt, theDist, theCount);
|
|
GetIntersection(theC1, aT1m, theT1l, theC2, aT2m, theT2l, theTolConf, theMaxCount, thePInt, theDist, theCount);
|
|
}
|
|
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : GetMinNbPoints
|
|
//purpose :
|
|
//=======================================================================
|
|
Standard_Integer IntCurve_IntPolyPolyGen::GetMinNbSamples() const
|
|
{
|
|
return myMinPntNb;
|
|
}
|
|
|
|
//=======================================================================
|
|
//function : SetMinNbPoints
|
|
//purpose :
|
|
//=======================================================================
|
|
void IntCurve_IntPolyPolyGen::SetMinNbSamples(const Standard_Integer theMinNbSamples)
|
|
{
|
|
myMinPntNb = theMinNbSamples;
|
|
}
|