1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-02 17:46:22 +03:00
occt/src/GeomPlate/GeomPlate_BuildPlateSurface.cxx

2605 lines
85 KiB
C++

// Created on: 1997-05-05
// Created by: Jerome LEMONIER
// Copyright (c) 1996-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 <GeomPlate_BuildPlateSurface.hxx>
#include <Adaptor2d_Curve2d.hxx>
#include <Adaptor3d_Curve.hxx>
#include <Adaptor3d_CurveOnSurface.hxx>
#include <Approx_CurveOnSurface.hxx>
#include <Extrema_ExtPS.hxx>
#include <Extrema_POnSurf.hxx>
#include <GCPnts_AbscissaPoint.hxx>
#include <Geom2d_BezierCurve.hxx>
#include <Geom2d_BSplineCurve.hxx>
#include <Geom2d_Curve.hxx>
#include <Geom2dAdaptor_Curve.hxx>
#include <Geom2dInt_GInter.hxx>
#include <Geom_BSplineSurface.hxx>
#include <Geom_Plane.hxx>
#include <Geom_RectangularTrimmedSurface.hxx>
#include <Geom_Surface.hxx>
#include <GeomAdaptor.hxx>
#include <GeomAdaptor_Surface.hxx>
#include <GeomLProp_SLProps.hxx>
#include <GeomPlate_BuildAveragePlane.hxx>
#include <GeomPlate_CurveConstraint.hxx>
#include <GeomPlate_HArray1OfSequenceOfReal.hxx>
#include <GeomPlate_MakeApprox.hxx>
#include <GeomPlate_PointConstraint.hxx>
#include <GeomPlate_SequenceOfAij.hxx>
#include <GeomPlate_Surface.hxx>
#include <gp_Pnt.hxx>
#include <gp_Pnt2d.hxx>
#include <gp_Vec.hxx>
#include <gp_Vec2d.hxx>
#include <IntRes2d_IntersectionPoint.hxx>
#include <Law_Interpol.hxx>
#include <LocalAnalysis_SurfaceContinuity.hxx>
#include <Plate_D2.hxx>
#include <Plate_FreeGtoCConstraint.hxx>
#include <Plate_GtoCConstraint.hxx>
#include <Plate_PinpointConstraint.hxx>
#include <Plate_Plate.hxx>
#include <Precision.hxx>
#include <ProjLib_HCompProjectedCurve.hxx>
#include <Standard_ConstructionError.hxx>
#include <TColgp_Array1OfPnt2d.hxx>
#include <TColgp_HArray1OfPnt.hxx>
#include <TColgp_SequenceOfVec.hxx>
#include <TColStd_HArray1OfReal.hxx>
#include <TColStd_SequenceOfInteger.hxx>
#include <Message_ProgressScope.hxx>
#include <stdio.h>
#ifdef DRAW
#include <DrawTrSurf.hxx>
#include <Draw_Marker3D.hxx>
#include <Draw_Marker2D.hxx>
#include <Draw.hxx>
// 0 : No display
// 1 : Display of Geometries and intermediary control
// 2 : Display of the number of constraints by curve + Intersection
// 3 : Dump of constraints in Plate
static Standard_Integer NbPlan = 0;
//static Standard_Integer NbCurv2d = 0;
static Standard_Integer NbMark = 0;
static Standard_Integer NbProj = 0;
#endif
#ifdef OCCT_DEBUG
#include <OSD_Chronometer.hxx>
#include <Geom_Surface.hxx>
static Standard_Integer Affich=0;
#endif
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
// =========================================================
// C O N S T R U C T O R S
// =========================================================
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
//---------------------------------------------------------
// Constructor compatible with the old version
//---------------------------------------------------------
GeomPlate_BuildPlateSurface::GeomPlate_BuildPlateSurface (
const Handle(TColStd_HArray1OfInteger)& NPoints,
const Handle(GeomPlate_HArray1OfHCurve)& TabCurve,
const Handle(TColStd_HArray1OfInteger)& Tang,
const Standard_Integer Degree,
const Standard_Integer NbIter,
const Standard_Real Tol2d,
const Standard_Real Tol3d,
const Standard_Real TolAng,
const Standard_Real ,
const Standard_Boolean Anisotropie
) :
myAnisotropie(Anisotropie),
myDegree(Degree),
myNbIter(NbIter),
myProj(),
myTol2d(Tol2d),
myTol3d(Tol3d),
myTolAng(TolAng),
myNbBounds(0)
{ Standard_Integer NTCurve=TabCurve->Length();// Number of linear constraints
myNbPtsOnCur = 0; // Different calculation of the number of points depending on the length
myLinCont = new GeomPlate_HSequenceOfCurveConstraint;
myPntCont = new GeomPlate_HSequenceOfPointConstraint;
if (myNbIter<1)
throw Standard_ConstructionError("GeomPlate : Number of iteration must be >= 1");
if (NTCurve==0)
throw Standard_ConstructionError("GeomPlate : the bounds Array is null");
if (Tang->Length()==0)
throw Standard_ConstructionError("GeomPlate : the constraints Array is null");
Standard_Integer nbp = 0;
Standard_Integer i ;
for ( i=1;i<=NTCurve;i++)
{ nbp+=NPoints->Value(i);
}
if (nbp==0)
throw Standard_ConstructionError("GeomPlate : the resolution is impossible if the number of constraints points is 0");
if (myDegree<2)
throw Standard_ConstructionError("GeomPlate ; the degree resolution must be upper of 2");
// Filling fields passing from the old constructor to the new one
for(i=1;i<=NTCurve;i++)
{ Handle(GeomPlate_CurveConstraint) Cont = new GeomPlate_CurveConstraint
( TabCurve->Value(i),
Tang->Value(i),
NPoints->Value(i));
myLinCont->Append(Cont);
}
mySurfInitIsGive=Standard_False;
myIsLinear = Standard_True;
myFree = Standard_False;
}
//------------------------------------------------------------------
// Constructor with initial surface and degree
//------------------------------------------------------------------
GeomPlate_BuildPlateSurface::GeomPlate_BuildPlateSurface (
const Handle(Geom_Surface)& Surf,
const Standard_Integer Degree,
const Standard_Integer NbPtsOnCur,
const Standard_Integer NbIter,
const Standard_Real Tol2d,
const Standard_Real Tol3d,
const Standard_Real TolAng,
const Standard_Real /*TolCurv*/,
const Standard_Boolean Anisotropie ) :
mySurfInit(Surf),
myAnisotropie(Anisotropie),
myDegree(Degree),
myNbPtsOnCur(NbPtsOnCur),
myNbIter(NbIter),
myProj(),
myTol2d(Tol2d),
myTol3d(Tol3d),
myTolAng(TolAng),
myNbBounds(0)
{ if (myNbIter<1)
throw Standard_ConstructionError("GeomPlate : Number of iteration must be >= 1");
if (myDegree<2)
throw Standard_ConstructionError("GeomPlate : the degree must be above 2");
myLinCont = new GeomPlate_HSequenceOfCurveConstraint;
myPntCont = new GeomPlate_HSequenceOfPointConstraint;
mySurfInitIsGive=Standard_True;
myIsLinear = Standard_True;
myFree = Standard_False;
}
//---------------------------------------------------------
// Constructor with degree
//---------------------------------------------------------
GeomPlate_BuildPlateSurface::GeomPlate_BuildPlateSurface (
const Standard_Integer Degree,
const Standard_Integer NbPtsOnCur,
const Standard_Integer NbIter,
const Standard_Real Tol2d,
const Standard_Real Tol3d,
const Standard_Real TolAng,
const Standard_Real /*TolCurv*/,
const Standard_Boolean Anisotropie ) :
myAnisotropie(Anisotropie),
myDegree(Degree),
myNbPtsOnCur(NbPtsOnCur),
myNbIter(NbIter),
myProj(),
myTol2d(Tol2d),
myTol3d(Tol3d),
myTolAng(TolAng),
myNbBounds(0)
{ if (myNbIter<1)
throw Standard_ConstructionError("GeomPlate : Number of iteration must be >= 1");
if (myDegree<2)
throw Standard_ConstructionError("GeomPlate : the degree resolution must be upper of 2");
myLinCont = new GeomPlate_HSequenceOfCurveConstraint;
myPntCont = new GeomPlate_HSequenceOfPointConstraint;
mySurfInitIsGive=Standard_False;
myIsLinear = Standard_True;
myFree = Standard_False;
}
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
// =========================================================
// P U B L I C M E T H O D S
// =========================================================
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
//-------------------------------------------------------------------------
// Function : TrierTab, internal Function, does not belong to class
//-------------------------------------------------------------------------
// Reorder the table of transformations
// After the call of CourbeJointive the order of curves is modified
// Ex : initial order of curves ==> A B C D E F
// In TabInit we note ==> 1 2 3 4 5 6
// after CourbeJointive ==> A E C B D F
// TabInit ==> 1 5 3 2 4 6
// after TrierTab the Table contains ==> 1 4 3 5 2 6
// It is also possible to access the 2nd curve by taking TabInit[2]
// i.e. the 4th from the table of classified curves
//-------------------------------------------------------------------------
static void TrierTab(Handle(TColStd_HArray1OfInteger)& Tab)
{
// Parse the table of transformations to find the initial order
Standard_Integer Nb=Tab->Length();
TColStd_Array1OfInteger TabTri(1,Nb);
for (Standard_Integer i=1;i<=Nb;i++)
TabTri.SetValue(Tab->Value(i),i);
Tab->ChangeArray1()=TabTri;
}
//---------------------------------------------------------
// Function : ProjectCurve
//---------------------------------------------------------
Handle(Geom2d_Curve) GeomPlate_BuildPlateSurface::ProjectCurve(const Handle(Adaptor3d_Curve)& Curv)
{
// Project a curve on a plane
Handle(Geom2d_Curve) Curve2d ;
Handle(GeomAdaptor_Surface) hsur = new GeomAdaptor_Surface(mySurfInit);
gp_Pnt2d P2d;
Handle(ProjLib_HCompProjectedCurve) HProjector = new ProjLib_HCompProjectedCurve (hsur, Curv, myTol3d/10, myTol3d/10);
Standard_Real UdebCheck, UfinCheck, ProjUdeb, ProjUfin;
UdebCheck = Curv->FirstParameter();
UfinCheck = Curv->LastParameter();
HProjector->Bounds( 1, ProjUdeb, ProjUfin );
if (HProjector->NbCurves() != 1 ||
Abs( UdebCheck -ProjUdeb ) > Precision::PConfusion() ||
Abs( UfinCheck -ProjUfin ) > Precision::PConfusion())
{
if (HProjector->IsSinglePnt(1, P2d))
{
// solution in a point
TColgp_Array1OfPnt2d poles(1, 2);
poles.Init(P2d);
Curve2d = new (Geom2d_BezierCurve) (poles);
}
else
{
Curve2d.Nullify(); // No continuous solution
#ifdef OCCT_DEBUG
std::cout << "BuildPlateSurace :: No continuous projection" << std::endl;
#endif
}
}
else {
GeomAbs_Shape Continuity = GeomAbs_C1;
Standard_Integer MaxDegree = 10, MaxSeg;
Standard_Real Udeb, Ufin;
HProjector->Bounds(1, Udeb, Ufin);
MaxSeg = 20 + HProjector->NbIntervals(GeomAbs_C3);
Approx_CurveOnSurface appr(HProjector, hsur, Udeb, Ufin, myTol3d);
appr.Perform(MaxSeg, MaxDegree, Continuity, Standard_False, Standard_True);
Curve2d = appr.Curve2d();
}
#ifdef DRAW
if (Affich) {
char name[256];
sprintf(name,"proj_%d",++NbProj);
DrawTrSurf::Set(name, Curve2d);
}
#endif
return Curve2d;
}
//---------------------------------------------------------
// Function : ProjectedCurve
//---------------------------------------------------------
Handle(Adaptor2d_Curve2d) GeomPlate_BuildPlateSurface::ProjectedCurve( Handle(Adaptor3d_Curve)& Curv)
{
// Projection of a curve on the initial surface
Handle(GeomAdaptor_Surface) hsur = new GeomAdaptor_Surface(mySurfInit);
Handle(ProjLib_HCompProjectedCurve) HProjector = new ProjLib_HCompProjectedCurve (hsur, Curv, myTolU/10, myTolV/10);
if (HProjector->NbCurves() != 1)
{
HProjector.Nullify(); // No continuous solution
#ifdef OCCT_DEBUG
std::cout << "BuildPlateSurace :: No continuous projection" << std::endl;
#endif
}
else
{
Standard_Real First1,Last1,First2,Last2;
First1=Curv->FirstParameter();
Last1 =Curv->LastParameter();
HProjector->Bounds(1,First2,Last2);
if (Abs(First1-First2) <= Max(myTolU,myTolV) &&
Abs(Last1-Last2) <= Max(myTolU,myTolV))
{
HProjector = Handle(ProjLib_HCompProjectedCurve)::DownCast(HProjector->Trim(First2,Last2,Precision::PConfusion()));
}
else
{
HProjector.Nullify(); // No continuous solution
#ifdef OCCT_DEBUG
std::cout << "BuildPlateSurace :: No complete projection" << std::endl;
#endif
}
}
return HProjector;
}
//---------------------------------------------------------
// Function : ProjectPoint
//---------------------------------------------------------
// Projects a point on the initial surface
//---------------------------------------------------------
gp_Pnt2d GeomPlate_BuildPlateSurface::ProjectPoint(const gp_Pnt &p3d)
{ Extrema_POnSurf P;
myProj.Perform(p3d);
Standard_Integer nearest = 1;
if( myProj.NbExt() > 1)
{
Standard_Real dist2mini = myProj.SquareDistance(1);
for (Standard_Integer i=2; i<=myProj.NbExt();i++)
{
if (myProj.SquareDistance(i) < dist2mini)
{
dist2mini = myProj.SquareDistance(i);
nearest = i;
}
}
}
P=myProj.Point(nearest);
Standard_Real u,v;
P.Parameter(u,v);
gp_Pnt2d p2d;
p2d.SetCoord(u,v);
return p2d;
}
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
// =========================================================
// P U B L I C M E T H O D S
// =========================================================
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
//---------------------------------------------------------
// Function : Init
//---------------------------------------------------------
// Initializes linear and point constraints
//---------------------------------------------------------
void GeomPlate_BuildPlateSurface::Init()
{ myLinCont->Clear();
myPntCont->Clear();
myPntCont = new GeomPlate_HSequenceOfPointConstraint;
myLinCont = new GeomPlate_HSequenceOfCurveConstraint;
}
//---------------------------------------------------------
// Function : LoadInitSurface
//---------------------------------------------------------
// Loads the initial surface
//---------------------------------------------------------
void GeomPlate_BuildPlateSurface::LoadInitSurface(const Handle(Geom_Surface)& Surf)
{ mySurfInit = Surf;
mySurfInitIsGive=Standard_True;
}
//---------------------------------------------------------
// Function : Add
//---------------------------------------------------------
//---------------------------------------------------------
// Adds a linear constraint
//---------------------------------------------------------
void GeomPlate_BuildPlateSurface::
Add(const Handle(GeomPlate_CurveConstraint)& Cont)
{ myLinCont->Append(Cont);
}
void GeomPlate_BuildPlateSurface::SetNbBounds( const Standard_Integer NbBounds )
{
myNbBounds = NbBounds;
}
//---------------------------------------------------------
// Function : Add
//---------------------------------------------------------
//---------------------------------------------------------
// Adds a point constraint
//---------------------------------------------------------
void GeomPlate_BuildPlateSurface::
Add(const Handle(GeomPlate_PointConstraint)& Cont)
{
myPntCont->Append(Cont);
}
//---------------------------------------------------------
// Function : Perform
// Calculates the surface filled with loaded constraints
//---------------------------------------------------------
void GeomPlate_BuildPlateSurface::Perform(const Message_ProgressRange& theProgress)
{
#ifdef OCCT_DEBUG
// Timing
OSD_Chronometer Chrono;
Chrono.Reset();
Chrono.Start();
#endif
if (myNbBounds == 0)
myNbBounds = myLinCont->Length();
myPlate.Init();
//=====================================================================
// Declaration of variables.
//=====================================================================
Standard_Integer NTLinCont = myLinCont->Length(),
NTPntCont = myPntCont->Length(), NbBoucle=0;
Standard_Boolean Fini=Standard_True;
if ((NTLinCont + NTPntCont) == 0)
{
#ifdef OCCT_DEBUG
std::cout << "WARNING : GeomPlate : The number of constraints is null." << std::endl;
#endif
return;
}
//======================================================================
// Initial Surface
//======================================================================
Message_ProgressScope aPS(theProgress, "Calculating the surface filled", 100, Standard_True);
if (!mySurfInitIsGive)
{
ComputeSurfInit (aPS.Next(10));
if (aPS.UserBreak())
return;
}
else {
if (NTLinCont>=2)
{ // Table of transformations to preserve the initial order, see TrierTab
myInitOrder = new TColStd_HArray1OfInteger(1,NTLinCont);
for (Standard_Integer l=1;l<=NTLinCont;l++)
myInitOrder->SetValue(l,l);
if (!CourbeJointive(myTol3d))
{// throw Standard_Failure("Curves are not joined");
#ifdef OCCT_DEBUG
std::cout<<"WARNING : Courbes non jointives a "<<myTol3d<<" pres"<<std::endl;
#endif
}
TrierTab(myInitOrder); // Reorder the table of transformations
}
else if(NTLinCont > 0)//Patch
{
mySense = new TColStd_HArray1OfInteger( 1, NTLinCont, 0 );
myInitOrder = new TColStd_HArray1OfInteger( 1, NTLinCont, 1 );
}
}
if (mySurfInit.IsNull())
{
return;
}
Standard_Real u1,v1,u2,v2;
mySurfInit->Bounds(u1,v1,u2,v2);
GeomAdaptor_Surface aSurfInit(mySurfInit);
myTolU = aSurfInit.UResolution(myTol3d);
myTolV = aSurfInit.VResolution(myTol3d);
myProj.Initialize(aSurfInit,u1,v1,u2,v2,
myTolU,myTolV);
//======================================================================
// Projection of curves
//======================================================================
Standard_Boolean Ok = Standard_True;
for (Standard_Integer i = 1; i <= NTLinCont; i++)
if(myLinCont->Value(i)->Curve2dOnSurf().IsNull())
{
Handle( Geom2d_Curve ) Curve2d = ProjectCurve( myLinCont->Value(i)->Curve3d() );
if (Curve2d.IsNull())
{
Ok = Standard_False;
break;
}
myLinCont->ChangeValue(i)->SetCurve2dOnSurf( Curve2d );
}
if (!Ok)
{
GeomPlate_MakeApprox App(myGeomPlateSurface, myTol3d,
1, 3,
15*myTol3d,
-1, GeomAbs_C0,
1.3);
mySurfInit = App.Surface();
mySurfInit->Bounds(u1,v1,u2,v2);
GeomAdaptor_Surface Surf(mySurfInit);
myTolU = Surf.UResolution(myTol3d);
myTolV = Surf.VResolution(myTol3d);
myProj.Initialize(Surf,u1,v1,u2,v2,
myTolU,myTolV);
Ok = Standard_True;
for (Standard_Integer i = 1; i <= NTLinCont; i++)
{
Handle( Geom2d_Curve ) Curve2d = ProjectCurve( myLinCont->Value(i)->Curve3d() );
if (Curve2d.IsNull())
{
Ok = Standard_False;
break;
}
myLinCont->ChangeValue(i)->SetCurve2dOnSurf( Curve2d );
}
if (!Ok)
{
mySurfInit = myPlanarSurfInit;
mySurfInit->Bounds(u1,v1,u2,v2);
GeomAdaptor_Surface SurfNew(mySurfInit);
myTolU = SurfNew.UResolution(myTol3d);
myTolV = SurfNew.VResolution(myTol3d);
myProj.Initialize(SurfNew,u1,v1,u2,v2,
myTolU,myTolV);
for (Standard_Integer i = 1; i <= NTLinCont; i++)
myLinCont->ChangeValue(i)->
SetCurve2dOnSurf(ProjectCurve( myLinCont->Value(i)->Curve3d() ) );
}
else { // Project the points
for (Standard_Integer i=1; i<=NTPntCont; i++) {
gp_Pnt P;
myPntCont->Value(i)->D0(P);
myPntCont->ChangeValue(i)->SetPnt2dOnSurf(ProjectPoint(P));
}
}
}
//======================================================================
// Projection of points
//======================================================================
for (Standard_Integer i=1;i<=NTPntCont;i++) {
if (! myPntCont->Value(i)->HasPnt2dOnSurf()) {
gp_Pnt P;
myPntCont->Value(i)->D0(P);
myPntCont->ChangeValue(i)->SetPnt2dOnSurf(ProjectPoint(P));
}
}
//======================================================================
// Number of points by curve
//======================================================================
if ((NTLinCont !=0)&&(myNbPtsOnCur!=0))
CalculNbPtsInit();
//======================================================================
// Management of incompatibilites between curves
//======================================================================
Handle(GeomPlate_HArray1OfSequenceOfReal) PntInter;
Handle(GeomPlate_HArray1OfSequenceOfReal) PntG1G1;
if (NTLinCont != 0) {
PntInter = new GeomPlate_HArray1OfSequenceOfReal(1,NTLinCont);
PntG1G1 = new GeomPlate_HArray1OfSequenceOfReal(1,NTLinCont);
Intersect(PntInter, PntG1G1);
}
//======================================================================
// Loop to obtain a better surface
//======================================================================
myFree = !myIsLinear;
do
{
#ifdef OCCT_DEBUG
if (Affich && NbBoucle) {
std::cout<<"Resultats boucle"<< NbBoucle << std::endl;
std::cout<<"DistMax="<<myG0Error<<std::endl;
if (myG1Error!=0)
std::cout<<"AngleMax="<<myG1Error<<std::endl;
if (myG2Error!=0)
std::cout<<"CourbMax="<<myG2Error<<std::endl;
}
#endif
NbBoucle++;
if (NTLinCont!=0)
{ //====================================================================
// Calculate the total number of points and the maximum of points by curve
//====================================================================
Standard_Integer NPointMax=0;
for (Standard_Integer i=1;i<=NTLinCont;i++)
if ((myLinCont->Value(i)->NbPoints())>NPointMax)
NPointMax=(Standard_Integer )( myLinCont->Value(i)->NbPoints());
//====================================================================
// Discretization of curves
//====================================================================
Discretise(PntInter, PntG1G1);
//====================================================================
// Preparation of constraint points for plate
//====================================================================
LoadCurve( NbBoucle );
if ( myPntCont->Length() != 0)
LoadPoint( NbBoucle );
//====================================================================
// Construction of the surface
//====================================================================
myPlate.SolveTI(myDegree, ComputeAnisotropie(), aPS.Next(90));
if (aPS.UserBreak())
{
return;
}
if (!myPlate.IsDone())
{
#ifdef OCCT_DEBUG
std::cout << "WARNING : GeomPlate : calculation of Plate failed" << std::endl;
#endif
return;
}
myGeomPlateSurface = new GeomPlate_Surface(mySurfInit,myPlate);
Standard_Real Umin,Umax,Vmin,Vmax;
myPlate.UVBox(Umin,Umax,Vmin,Vmax);
myGeomPlateSurface->SetBounds(Umin,Umax,Vmin,Vmax);
Fini = VerifSurface(NbBoucle);
if ((NbBoucle >= myNbIter)&&(!Fini))
{
#ifdef OCCT_DEBUG
std::cout<<"Warning: objective was not reached"<<std::endl;
#endif
Fini = Standard_True;
}
if ((NTPntCont != 0)&&(Fini))
{ Standard_Real di,an,cu;
VerifPoints(di,an,cu);
}
}
else
{ LoadPoint( NbBoucle );
//====================================================================
//Construction of the surface
//====================================================================
myPlate.SolveTI(myDegree, ComputeAnisotropie(), aPS.Next(90));
if (aPS.UserBreak())
{
return;
}
if (!myPlate.IsDone())
{
#ifdef OCCT_DEBUG
std::cout << "WARNING : GeomPlate : calculation of Plate failed" << std::endl;
#endif
return;
}
myGeomPlateSurface = new GeomPlate_Surface(mySurfInit,myPlate);
Standard_Real Umin,Umax,Vmin,Vmax;
myPlate.UVBox(Umin,Umax,Vmin,Vmax);
myGeomPlateSurface->SetBounds(Umin,Umax,Vmin,Vmax);
Fini = Standard_True;
Standard_Real di,an,cu;
VerifPoints(di,an,cu);
}
} while (!Fini); // End loop for better surface
#ifdef OCCT_DEBUG
if (NTLinCont != 0)
{ std::cout<<"======== Global results ==========="<<std::endl;
std::cout<<"DistMax="<<myG0Error<<std::endl;
if (myG1Error!=0)
std::cout<<"AngleMax="<<myG1Error<<std::endl;
if (myG2Error!=0)
std::cout<<"CourbMax="<<myG2Error<<std::endl;
}
Chrono.Stop();
Standard_Real Tps;
Chrono.Show(Tps);
std::cout<<"*** END OF GEOMPLATE ***"<<std::endl;
std::cout<<"Time of calculation : "<<Tps<<std::endl;
std::cout<<"Number of loops : "<<NbBoucle<<std::endl;
#endif
}
//---------------------------------------------------------
// Function : EcartContraintesMIL
//---------------------------------------------------------
void GeomPlate_BuildPlateSurface::
EcartContraintesMil ( const Standard_Integer c,
Handle(TColStd_HArray1OfReal)& d,
Handle(TColStd_HArray1OfReal)& an,
Handle(TColStd_HArray1OfReal)& courb)
{
Standard_Integer NbPt=myParCont->Value(c).Length();
Standard_Real U;
if (NbPt<3)
NbPt=4;
else
NbPt=myParCont->Value(c).Length();
gp_Vec v1i, v1f, v2i, v2f, v3i, v3f;
gp_Pnt Pi, Pf;
gp_Pnt2d P2d;Standard_Integer i;
Handle(GeomPlate_CurveConstraint) LinCont = myLinCont->Value(c);
switch (LinCont->Order())
{ case 0 :
for (i=1; i<NbPt; i++)
{ U = ( myParCont->Value(c).Value(i) +
myParCont->Value(c).Value(i+1) )/2;
LinCont->D0(U, Pi);
if (!LinCont->ProjectedCurve().IsNull())
P2d = LinCont->ProjectedCurve()->Value(U);
else
{ if (!LinCont->Curve2dOnSurf().IsNull())
P2d = LinCont->Curve2dOnSurf()->Value(U);
else
P2d = ProjectPoint(Pi);
}
myGeomPlateSurface->D0( P2d.Coord(1), P2d.Coord(2), Pf);
an->Init(0);
courb->Init(0);
d->ChangeValue(i) = Pf.Distance(Pi);
}
break;
case 1 :
for (i=1; i<NbPt; i++)
{ U = ( myParCont->Value(c).Value(i) +
myParCont->Value(c).Value(i+1) )/2;
LinCont->D1(U, Pi, v1i, v2i);
if (!LinCont->ProjectedCurve().IsNull())
P2d = LinCont->ProjectedCurve()->Value(U);
else
{ if (!LinCont->Curve2dOnSurf().IsNull())
P2d = LinCont->Curve2dOnSurf()->Value(U);
else
P2d = ProjectPoint(Pi);
}
myGeomPlateSurface->D1( P2d.Coord(1), P2d.Coord(2), Pf, v1f, v2f);
d->ChangeValue(i) = Pf.Distance(Pi);
v3i = v1i^v2i; v3f=v1f^v2f;
Standard_Real angle=v3f.Angle(v3i);
if (angle>(M_PI/2))
an->ChangeValue(i) = M_PI -angle;
else
an->ChangeValue(i) = angle;
courb->Init(0);
}
break;
case 2 :
Handle(Geom_Surface) Splate (myGeomPlateSurface);
LocalAnalysis_SurfaceContinuity CG2;
for (i=1; i<NbPt; i++)
{ U = ( myParCont->Value(c).Value(i) +
myParCont->Value(c).Value(i+1) )/2;
LinCont->D0(U, Pi);
if (!LinCont->ProjectedCurve().IsNull())
P2d = LinCont->ProjectedCurve()->Value(U);
else
{ if (!LinCont->Curve2dOnSurf().IsNull())
P2d = LinCont->Curve2dOnSurf()->Value(U);
else
P2d = ProjectPoint(Pi);
}
GeomLProp_SLProps Prop (Splate, P2d.Coord(1), P2d.Coord(2),
2, 0.001);
CG2.ComputeAnalysis(Prop, myLinCont->Value(c)->LPropSurf(U),
GeomAbs_G2);
d->ChangeValue(i)=CG2.C0Value();
an->ChangeValue(i)=CG2.G1Angle();
courb->ChangeValue(i)=CG2.G2CurvatureGap();
}
break;
}
}
//---------------------------------------------------------
// Function : Disc2dContour
//---------------------------------------------------------
void GeomPlate_BuildPlateSurface::
Disc2dContour ( const Standard_Integer /*nbp*/,
TColgp_SequenceOfXY& Seq2d)
{
#ifdef OCCT_DEBUG
if (Seq2d.Length()!=4)
std::cout<<"Number of points should be equal to 4 for Disc2dContour"<<std::endl;
#endif
// initialization
Seq2d.Clear();
// sampling in "cosine" + 3 points on each interval
Standard_Integer NTCurve = myLinCont->Length();
Standard_Integer NTPntCont = myPntCont->Length();
gp_Pnt2d P2d;
gp_XY UV;
gp_Pnt PP;
Standard_Real u1,v1,u2,v2;
Standard_Integer i ;
mySurfInit->Bounds(u1,v1,u2,v2);
GeomAdaptor_Surface Surf(mySurfInit);
myProj.Initialize(Surf,u1,v1,u2,v2,
myTolU,myTolV);
for( i=1; i<=NTPntCont; i++)
if (myPntCont->Value(i)->Order()!=-1)
{ P2d = myPntCont->Value(i)->Pnt2dOnSurf();
UV.SetX(P2d.Coord(1));
UV.SetY(P2d.Coord(2));
Seq2d.Append(UV);
}
for(i=1; i<=NTCurve; i++)
{
Handle(GeomPlate_CurveConstraint) LinCont = myLinCont->Value(i);
if (LinCont->Order()!=-1)
{ Standard_Integer NbPt=myParCont->Value(i).Length();
// first point of constraint (j=0)
if (!LinCont->ProjectedCurve().IsNull())
P2d = LinCont->ProjectedCurve()->Value(myParCont->Value(i).Value(1));
else
{ if (!LinCont->Curve2dOnSurf().IsNull())
P2d = LinCont->Curve2dOnSurf()->Value(myParCont->Value(i).Value(1));
else
{
LinCont->D0(myParCont->Value(i).Value(1),PP);
P2d = ProjectPoint(PP);
}
}
UV.SetX(P2d.Coord(1));
UV.SetY(P2d.Coord(2));
Seq2d.Append(UV);
for (Standard_Integer j=2; j<NbPt; j++)
{ Standard_Real Uj=myParCont->Value(i).Value(j),
Ujp1=myParCont->Value(i).Value(j+1);
if (!LinCont->ProjectedCurve().IsNull())
P2d = LinCont->ProjectedCurve()->Value((Ujp1+3*Uj)/4);
else
{ if (!LinCont->Curve2dOnSurf().IsNull())
P2d = LinCont->Curve2dOnSurf()->Value((Ujp1+3*Uj)/4);
else
{
LinCont->D0((Ujp1+3*Uj)/4,PP);
P2d = ProjectPoint(PP);
}
}
UV.SetX(P2d.Coord(1));
UV.SetY(P2d.Coord(2));
Seq2d.Append(UV);
// point 1/2 previous
if (!LinCont->ProjectedCurve().IsNull())
P2d = LinCont->ProjectedCurve()->Value((Ujp1+Uj)/2);
else
{ if (!LinCont->Curve2dOnSurf().IsNull())
P2d = LinCont->Curve2dOnSurf()->Value((Ujp1+Uj)/2);
else
{
LinCont->D0((Ujp1+Uj)/2,PP);
P2d = ProjectPoint(PP);
}
}
UV.SetX(P2d.Coord(1));
UV.SetY(P2d.Coord(2));
Seq2d.Append(UV);
// point 3/4 previous
if (!LinCont->ProjectedCurve().IsNull())
P2d = LinCont->ProjectedCurve()->Value((3*Ujp1+Uj)/4);
else
{ if (!LinCont->Curve2dOnSurf().IsNull())
P2d = LinCont->Curve2dOnSurf()->Value((3*Ujp1+Uj)/4);
else
{
LinCont->D0((3*Ujp1+Uj)/4,PP);
P2d = ProjectPoint(PP);
}
}
UV.SetX(P2d.Coord(1));
UV.SetY(P2d.Coord(2));
Seq2d.Append(UV);
// current constraint point
if (!LinCont->ProjectedCurve().IsNull())
P2d = LinCont->ProjectedCurve()->Value(Ujp1);
else
{ if (!LinCont->Curve2dOnSurf().IsNull())
P2d = LinCont->Curve2dOnSurf()->Value(Ujp1);
else
{
LinCont->D0(Ujp1,PP);
P2d = ProjectPoint(PP);
}
}
UV.SetX(P2d.Coord(1));
UV.SetY(P2d.Coord(2));
Seq2d.Append(UV);
}
}
}
}
//---------------------------------------------------------
// Function : Disc3dContour
//---------------------------------------------------------
void GeomPlate_BuildPlateSurface::
Disc3dContour (const Standard_Integer /*nbp*/,
const Standard_Integer iordre,
TColgp_SequenceOfXYZ& Seq3d)
{
#ifdef OCCT_DEBUG
if (Seq3d.Length()!=4)
std::cout<<"nbp should be equal to 4 for Disc3dContour"<<std::endl;
if (iordre!=0&&iordre!=1)
std::cout<<"incorrect order for Disc3dContour"<<std::endl;
#endif
// initialization
Seq3d.Clear();
// sampling in "cosine" + 3 points on each interval
Standard_Real u1,v1,u2,v2;
mySurfInit->Bounds(u1,v1,u2,v2);
GeomAdaptor_Surface Surf(mySurfInit);
myProj.Initialize(Surf,u1,v1,u2,v2,
Surf.UResolution(myTol3d),
Surf.VResolution(myTol3d));
Standard_Integer NTCurve = myLinCont->Length();
Standard_Integer NTPntCont = myPntCont->Length();
// gp_Pnt2d P2d;
gp_Pnt P3d;
gp_Vec v1h,v2h,v3h;
gp_XYZ Pos;
Standard_Integer i ;
for( i=1; i<=NTPntCont; i++)
if (myPntCont->Value(i)->Order()!=-1)
{ if (iordre==0)
{ myPntCont->Value(i)->D0(P3d);
Pos.SetX(P3d.X());
Pos.SetY(P3d.Y());
Pos.SetZ(P3d.Z());
Seq3d.Append(Pos);
}
else {
myPntCont->Value(i)->D1(P3d,v1h,v2h);
v3h=v1h^v2h;
Pos.SetX(v3h.X());
Pos.SetY(v3h.Y());
Pos.SetZ(v3h.Z());
Seq3d.Append(Pos);
}
}
for(i=1; i<=NTCurve; i++)
if (myLinCont->Value(i)->Order()!=-1)
{ Standard_Integer NbPt=myParCont->Value(i).Length();
// first constraint point (j=0)
// Standard_Integer NbPt=myParCont->Length();
if (iordre==0) {
myLinCont->Value(i)->D0(myParCont->Value(i).Value(1),P3d);
Pos.SetX(P3d.X());
Pos.SetY(P3d.Y());
Pos.SetZ(P3d.Z());
Seq3d.Append(Pos);
}
else {
myLinCont->Value(i)->D1(myParCont->Value(i).Value(1),P3d,v1h,v2h);
v3h=v1h^v2h;
Pos.SetX(v3h.X());
Pos.SetY(v3h.Y());
Pos.SetZ(v3h.Z());
Seq3d.Append(Pos);
}
for (Standard_Integer j=2; j<NbPt; j++)
{ Standard_Real Uj=myParCont->Value(i).Value(j),
Ujp1=myParCont->Value(i).Value(j+1);
if (iordre==0) {
// point 1/4 previous
myLinCont->Value(i)->D0((Ujp1+3*Uj)/4,P3d);
Pos.SetX(P3d.X());
Pos.SetY(P3d.Y());
Pos.SetZ(P3d.Z());
Seq3d.Append(Pos);
// point 1/2 previous
myLinCont->Value(i)->D0((Ujp1+Uj)/2,P3d);
Pos.SetX(P3d.X());
Pos.SetY(P3d.Y());
Pos.SetZ(P3d.Z());
Seq3d.Append(Pos);
// point 3/4 previous
myLinCont->Value(i)->D0((3*Ujp1+Uj)/4,P3d);
Pos.SetX(P3d.X());
Pos.SetY(P3d.Y());
Pos.SetZ(P3d.Z());
Seq3d.Append(Pos);
// current constraint point
myLinCont->Value(i)->D0(Ujp1,P3d);
Pos.SetX(P3d.X());
Pos.SetY(P3d.Y());
Pos.SetZ(P3d.Z());
Seq3d.Append(Pos);
}
else {
// point 1/4 previous
myLinCont->Value(i)->D1((Ujp1+3*Uj)/4,P3d,v1h,v2h);
v3h=v1h^v2h;
Pos.SetX(v3h.X());
Pos.SetY(v3h.Y());
Pos.SetZ(v3h.Z());
Seq3d.Append(Pos);
// point 1/2 previous
myLinCont->Value(i)->D1((Ujp1+Uj)/2,P3d,v1h,v2h);
v3h=v1h^v2h;
Pos.SetX(v3h.X());
Pos.SetY(v3h.Y());
Pos.SetZ(v3h.Z());
Seq3d.Append(Pos);
// point 3/4 previous
myLinCont->Value(i)->D1((3*Ujp1+Uj)/4,P3d,v1h,v2h);
v3h=v1h^v2h;
Pos.SetX(v3h.X());
Pos.SetY(v3h.Y());
Pos.SetZ(v3h.Z());
Seq3d.Append(Pos);
// current constraint point
myLinCont->Value(i)->D1(Ujp1,P3d,v1h,v2h);
v3h=v1h^v2h;
Pos.SetX(v3h.X());
Pos.SetY(v3h.Y());
Pos.SetZ(v3h.Z());
Seq3d.Append(Pos);
}
}
}
}
//---------------------------------------------------------
// Function : IsDone
//---------------------------------------------------------
Standard_Boolean GeomPlate_BuildPlateSurface::IsDone() const
{ return myPlate.IsDone();
}
//---------------------------------------------------------
// Function : Surface
//---------------------------------------------------------
Handle(GeomPlate_Surface) GeomPlate_BuildPlateSurface::Surface() const
{ return myGeomPlateSurface ;
}
//---------------------------------------------------------
// Function : SurfInit
//---------------------------------------------------------
Handle(Geom_Surface) GeomPlate_BuildPlateSurface::SurfInit() const
{ return mySurfInit ;
}
//---------------------------------------------------------
// Function : Sense
//---------------------------------------------------------
Handle(TColStd_HArray1OfInteger) GeomPlate_BuildPlateSurface::Sense() const
{ Standard_Integer NTCurve = myLinCont->Length();
Handle(TColStd_HArray1OfInteger) Sens = new TColStd_HArray1OfInteger(1,
NTCurve);
for (Standard_Integer i=1; i<=NTCurve; i++)
Sens->SetValue(i,mySense->Value(myInitOrder->Value(i)));
return Sens;
}
//---------------------------------------------------------
// Function : Curve2d
//---------------------------------------------------------
Handle(TColGeom2d_HArray1OfCurve) GeomPlate_BuildPlateSurface::Curves2d() const
{ Standard_Integer NTCurve = myLinCont->Length();
Handle(TColGeom2d_HArray1OfCurve) C2dfin =
new TColGeom2d_HArray1OfCurve(1,NTCurve);
for (Standard_Integer i=1; i<=NTCurve; i++)
C2dfin->SetValue(i,myLinCont->Value(myInitOrder->Value(i))->Curve2dOnSurf());
return C2dfin;
}
//---------------------------------------------------------
// Function : Order
//---------------------------------------------------------
Handle(TColStd_HArray1OfInteger) GeomPlate_BuildPlateSurface::Order() const
{ Handle(TColStd_HArray1OfInteger) result=
new TColStd_HArray1OfInteger(1,myLinCont->Length());
for (Standard_Integer i=1;i<=myLinCont->Length();i++)
result->SetValue(myInitOrder->Value(i),i);
return result;
}
//---------------------------------------------------------
// Function : G0Error
//---------------------------------------------------------
Standard_Real GeomPlate_BuildPlateSurface::G0Error() const
{ return myG0Error;
}
//---------------------------------------------------------
// Function : G1Error
//---------------------------------------------------------
Standard_Real GeomPlate_BuildPlateSurface::G1Error() const
{ return myG1Error;
}
//---------------------------------------------------------
// Function : G2Error
//---------------------------------------------------------
Standard_Real GeomPlate_BuildPlateSurface::G2Error() const
{ return myG2Error;
}
//=======================================================================
//function : G0Error
//purpose :
//=======================================================================
Standard_Real GeomPlate_BuildPlateSurface::G0Error( const Standard_Integer Index )
{
Handle( TColStd_HArray1OfReal ) tdistance = new TColStd_HArray1OfReal( 1, myNbPtsOnCur );
Handle( TColStd_HArray1OfReal ) tangle = new TColStd_HArray1OfReal( 1, myNbPtsOnCur );
Handle( TColStd_HArray1OfReal ) tcurvature = new TColStd_HArray1OfReal( 1, myNbPtsOnCur );
EcartContraintesMil( Index, tdistance, tangle, tcurvature );
Standard_Real MaxDistance = 0.;
for (Standard_Integer i = 1; i <= myNbPtsOnCur; i++)
if (tdistance->Value(i) > MaxDistance)
MaxDistance = tdistance->Value(i);
return MaxDistance;
}
//=======================================================================
//function : G1Error
//purpose :
//=======================================================================
Standard_Real GeomPlate_BuildPlateSurface::G1Error( const Standard_Integer Index )
{
Handle( TColStd_HArray1OfReal ) tdistance = new TColStd_HArray1OfReal( 1, myNbPtsOnCur );
Handle( TColStd_HArray1OfReal ) tangle = new TColStd_HArray1OfReal( 1, myNbPtsOnCur );
Handle( TColStd_HArray1OfReal ) tcurvature = new TColStd_HArray1OfReal( 1, myNbPtsOnCur );
EcartContraintesMil( Index, tdistance, tangle, tcurvature );
Standard_Real MaxAngle = 0.;
for (Standard_Integer i = 1; i <= myNbPtsOnCur; i++)
if (tangle->Value(i) > MaxAngle)
MaxAngle = tangle->Value(i);
return MaxAngle;
}
//=======================================================================
//function : G2Error
//purpose :
//=======================================================================
Standard_Real GeomPlate_BuildPlateSurface::G2Error( const Standard_Integer Index )
{
Handle( TColStd_HArray1OfReal ) tdistance = new TColStd_HArray1OfReal( 1, myNbPtsOnCur );
Handle( TColStd_HArray1OfReal ) tangle = new TColStd_HArray1OfReal( 1, myNbPtsOnCur );
Handle( TColStd_HArray1OfReal ) tcurvature = new TColStd_HArray1OfReal( 1, myNbPtsOnCur );
EcartContraintesMil( Index, tdistance, tangle, tcurvature );
Standard_Real MaxCurvature = 0.;
for (Standard_Integer i = 1; i <= myNbPtsOnCur; i++)
if (tcurvature->Value(i) > MaxCurvature)
MaxCurvature = tcurvature->Value(i);
return MaxCurvature;
}
Handle(GeomPlate_CurveConstraint) GeomPlate_BuildPlateSurface::CurveConstraint( const Standard_Integer order) const
{
return myLinCont->Value(order);
}
Handle(GeomPlate_PointConstraint) GeomPlate_BuildPlateSurface::PointConstraint( const Standard_Integer order) const
{
return myPntCont->Value(order);
}
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
// =========================================================
// P R I V A T E M E T H O D S
// =========================================================
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//
//=======================================================================
// Function : CourbeJointive
// Purpose : Create a chain of curves to calculate the
// initial surface with the method of max flow.
// Return true if it is a closed contour.
//=======================================================================
Standard_Boolean GeomPlate_BuildPlateSurface::
CourbeJointive(const Standard_Real tolerance)
{ Standard_Integer nbf = myLinCont->Length();
Standard_Real Ufinal1,Uinit1,Ufinal2,Uinit2;
mySense = new TColStd_HArray1OfInteger(1,nbf,0);
Standard_Boolean result=Standard_True;
Standard_Integer j=1,i;
gp_Pnt P1,P2;
while (j <= (myNbBounds-1))
{
Standard_Integer a=0;
i=j+1;
if (i > myNbBounds)
{ result = Standard_False;
a=2;
}
while (a<1)
{ if (i > myNbBounds)
{ result = Standard_False;
a=2;
}
else
{
Uinit1=myLinCont->Value(j)->FirstParameter();
Ufinal1=myLinCont->Value(j)->LastParameter();
Uinit2=myLinCont->Value(i)->FirstParameter();
Ufinal2=myLinCont->Value(i)->LastParameter();
if (mySense->Value(j)==1)
Ufinal1=Uinit1;
myLinCont->Value(j)->D0(Ufinal1,P1);
myLinCont->Value(i)->D0(Uinit2,P2);
if (P1.Distance(P2)<tolerance)
{ if (i!=j+1) {
Handle(GeomPlate_CurveConstraint) tampon = myLinCont->Value(j+1);
myLinCont->SetValue(j+1,myLinCont->Value(i));
myLinCont->SetValue(i,tampon);
Standard_Integer Tmp=myInitOrder->Value(j+1);
// See function TrierTab for the functioning of myInitOrder
myInitOrder->SetValue(j+1,myInitOrder->Value(i));
myInitOrder->SetValue(i,Tmp);
};
a=2;
mySense->SetValue(j+1,0);
}
else
{ myLinCont->Value(i)->D0(Ufinal2,P2);
if (P1.Distance(P2)<tolerance)
{ if (i!=j+1) {
Handle(GeomPlate_CurveConstraint) tampon =
myLinCont->Value(j+1);
myLinCont->SetValue(j+1,myLinCont->Value(i));
myLinCont->SetValue(i,tampon);
Standard_Integer Tmp=myInitOrder->Value(j+1);
// See function TrierTab for the functioning of myInitOrder
myInitOrder->SetValue(j+1,myInitOrder->Value(i));
myInitOrder->SetValue(i,Tmp);
};
a=2;
mySense->SetValue(j+1,1);
}
}
}
i++;
}
j++;
}
Uinit1=myLinCont->Value( myNbBounds )->FirstParameter();
Ufinal1=myLinCont->Value( myNbBounds )->LastParameter();
Uinit2=myLinCont->Value(1)->FirstParameter();
Ufinal2=myLinCont->Value(1)->LastParameter();
myLinCont->Value( myNbBounds )->D0(Ufinal1,P1);
myLinCont->Value(1)->D0(Uinit2,P2);
if ((mySense->Value( myNbBounds )==0)
&&(P1.Distance(P2)<tolerance))
{
return ((Standard_True)&&(result));
}
myLinCont->Value( myNbBounds )->D0(Uinit1,P1);
if ((mySense->Value( myNbBounds )==1)
&&(P1.Distance(P2)<tolerance))
{
return ((Standard_True)&&(result));
}
else return Standard_False;
}
//-------------------------------------------------------------------------
// Function : ComputeSurfInit
//-------------------------------------------------------------------------
// Calculate the initial surface either by the method of max flow or by
// the method of the plane of inertia if the contour is not closed or if
// there are point constraints.
//-------------------------------------------------------------------------
void GeomPlate_BuildPlateSurface::ComputeSurfInit(const Message_ProgressRange& theProgress)
{
Standard_Integer nopt=2, popt=2, Np=1;
Standard_Boolean isHalfSpace = Standard_True;
Standard_Real LinTol = 0.001, AngTol = 0.001; //AngTol = 0.0001; //LinTol = 0.0001
// Option to calculate the initial plane
Standard_Integer NTLinCont = myLinCont->Length(), NTPntCont = myPntCont->Length();
// Table of transformation to preserve the initial order see TrierTab
if (NTLinCont != 0) {
myInitOrder = new TColStd_HArray1OfInteger(1,NTLinCont);
for (Standard_Integer i = 1; i <= NTLinCont; i++)
myInitOrder->SetValue( i, i );
}
Standard_Boolean CourbeJoint = (NTLinCont != 0) && CourbeJointive (myTol3d);
if (CourbeJoint && IsOrderG1())
{
nopt = 3;
// Table contains the cloud of points for calculation of the plane
Standard_Integer NbPoint = 20, Discr = NbPoint/4, pnum = 0;
Handle( TColgp_HArray1OfPnt ) Pts = new TColgp_HArray1OfPnt( 1, (NbPoint+1)*NTLinCont+NTPntCont );
TColgp_SequenceOfVec Vecs, NewVecs;
GeomPlate_SequenceOfAij Aset;
Standard_Real Uinit, Ufinal, Uif;
gp_Vec LastVec;
Standard_Integer i ;
for ( i = 1; i <= NTLinCont; i++)
{
Standard_Integer Order = myLinCont->Value(i)->Order();
NewVecs.Clear();
Uinit = myLinCont->Value(i)->FirstParameter();
Ufinal = myLinCont->Value(i)->LastParameter();
Uif = Ufinal - Uinit;
if (mySense->Value(i) == 1)
{
Uinit = Ufinal;
Uif = -Uif;
}
gp_Vec Vec1, Vec2, Normal;
Standard_Boolean ToReverse = Standard_False;
if (i > 1 && Order >= GeomAbs_G1)
{
gp_Pnt P;
myLinCont->Value(i)->D1( Uinit, P, Vec1, Vec2 );
Normal = Vec1 ^ Vec2;
if (LastVec.IsOpposite( Normal, AngTol ))
ToReverse = Standard_True;
}
for (Standard_Integer j = 0; j <= NbPoint; j++)
{ // Number of points per curve = 20
// Linear distribution
Standard_Real Inter = j*Uif/(NbPoint);
if (Order < GeomAbs_G1 || j % Discr != 0)
myLinCont->Value(i)->D0( Uinit+Inter, Pts->ChangeValue(++pnum) );
else
{
myLinCont->Value(i)->D1( Uinit+Inter, Pts->ChangeValue(++pnum), Vec1, Vec2 );
Normal = Vec1 ^ Vec2;
Normal.Normalize();
if (ToReverse)
Normal.Reverse();
Standard_Boolean isNew = Standard_True;
Standard_Integer k ;
for ( k = 1; k <= Vecs.Length(); k++)
if (Vecs(k).IsEqual( Normal, LinTol, AngTol ))
{
isNew = Standard_False;
break;
}
if (isNew)
for (k = 1; k <= NewVecs.Length(); k++)
if (NewVecs(k).IsEqual( Normal, LinTol, AngTol ))
{
isNew = Standard_False;
break;
}
if (isNew)
NewVecs.Append( Normal );
}
}
if (Order >= GeomAbs_G1)
{
isHalfSpace = GeomPlate_BuildAveragePlane::HalfSpace( NewVecs, Vecs, Aset, LinTol, AngTol );
if (! isHalfSpace)
break;
LastVec = Normal;
}
} //for (i = 1; i <= NTLinCont; i++)
if (isHalfSpace)
{
for (i = 1; i <= NTPntCont; i++)
{
Standard_Integer Order = myPntCont->Value(i)->Order();
NewVecs.Clear();
gp_Vec Vec1, Vec2, Normal;
if (Order < GeomAbs_G1)
myPntCont->Value(i)->D0( Pts->ChangeValue(++pnum) );
else
{
myPntCont->Value(i)->D1( Pts->ChangeValue(++pnum), Vec1, Vec2 );
Normal = Vec1 ^ Vec2;
Normal.Normalize();
Standard_Boolean isNew = Standard_True;
for (Standard_Integer k = 1; k <= Vecs.Length(); k++)
if (Vecs(k).IsEqual( Normal, LinTol, AngTol ))
{
isNew = Standard_False;
break;
}
if (isNew)
{
NewVecs.Append( Normal );
isHalfSpace = GeomPlate_BuildAveragePlane::HalfSpace( NewVecs, Vecs, Aset, LinTol, AngTol );
if (! isHalfSpace)
{
NewVecs(1).Reverse();
isHalfSpace = GeomPlate_BuildAveragePlane::HalfSpace( NewVecs, Vecs, Aset, LinTol, AngTol );
}
if (! isHalfSpace)
break;
}
}
} //for (i = 1; i <= NTPntCont; i++)
if (isHalfSpace)
{
Standard_Boolean NullExist = Standard_True;
while (NullExist)
{
NullExist = Standard_False;
for (i = 1; i <= Vecs.Length(); i++)
if (Vecs(i).SquareMagnitude() == 0.)
{
NullExist = Standard_True;
Vecs.Remove(i);
break;
}
}
GeomPlate_BuildAveragePlane BAP( Vecs, Pts );
Standard_Real u1,u2,v1,v2;
BAP.MinMaxBox(u1,u2,v1,v2);
// The space is greater for projections
Standard_Real du = u2 - u1;
Standard_Real dv = v2 - v1;
u1 -= du; u2 += du; v1 -= dv; v2 += dv;
mySurfInit = new Geom_RectangularTrimmedSurface( BAP.Plane(), u1,u2,v1,v2 );
}
} //if (isHalfSpace)
if (!isHalfSpace)
{
#ifdef OCCT_DEBUG
std::cout<<std::endl<<"Normals are not in half space"<<std::endl<<std::endl;
#endif
myIsLinear = Standard_False;
nopt = 2;
}
} //if (NTLinCont != 0 && (CourbeJoint = CourbeJointive( myTol3d )) && IsOrderG1())
if (NTLinCont != 0)
TrierTab( myInitOrder ); // Reorder the table of transformations
if (nopt != 3)
{
if ( NTPntCont != 0)
nopt = 1; //Calculate by the method of plane of inertia
else if (!CourbeJoint || NTLinCont != myNbBounds)
{// throw Standard_Failure("Curves are not joined");
#ifdef OCCT_DEBUG
std::cout << "WARNING : Curves are non-adjacent with tolerance " << myTol3d << std::endl;
#endif
nopt = 1;
}
Standard_Real LenT=0;
Standard_Integer Npt=0;
Standard_Integer NTPoint=20*NTLinCont;
Standard_Integer i ;
for ( i=1;i<=NTLinCont;i++)
LenT+=myLinCont->Value(i)->Length();
for (i=1;i<=NTLinCont;i++)
{ Standard_Integer NbPoint= (Standard_Integer )( NTPoint*(myLinCont->Value(i)->Length())/LenT);
if (NbPoint<10)
NbPoint=10;
(void )Npt; // unused but set for debug
Npt += NbPoint;
}
// Table containing a cloud of points for calculation of the plane
Handle(TColgp_HArray1OfPnt) Pts = new TColgp_HArray1OfPnt(1,20*NTLinCont+NTPntCont);
Standard_Integer NbPoint=20;
Standard_Real Uinit,Ufinal, Uif;
for ( i=1;i<=NTLinCont;i++)
{ Uinit=myLinCont->Value(i)->FirstParameter();
Ufinal=myLinCont->Value(i)->LastParameter();
Uif=Ufinal-Uinit;
if (mySense->Value(i) == 1)
{ Uinit = Ufinal;
Uif = -Uif;
}
for (Standard_Integer j=0; j<NbPoint; j++)
{ // Number of points per curve = 20
// Linear distribution
Standard_Real Inter=j*Uif/(NbPoint);
gp_Pnt P;
myLinCont->Value(i)->D0(Uinit+Inter,P);
Pts->SetValue(Np++,P);
}
}
for (i=1;i<=NTPntCont;i++)
{ gp_Pnt P;
myPntCont->Value(i)->D0(P);
Pts->SetValue(Np++,P);
}
if (!CourbeJoint)
myNbBounds = 0;
GeomPlate_BuildAveragePlane BAP( Pts, NbPoint*myNbBounds, myTol3d/1000, popt, nopt );
if (!BAP.IsPlane())
{
#ifdef OCCT_DEBUG
std::cout << "WARNING : GeomPlate : the initial surface is not a plane." << std::endl;
#endif
return;
}
Standard_Real u1,u2,v1,v2;
BAP.MinMaxBox(u1,u2,v1,v2);
// The space is greater for projections
Standard_Real du = u2 - u1;
Standard_Real dv = v2 - v1;
u1 -= du; u2 += du; v1 -= dv; v2 += dv;
mySurfInit = new Geom_RectangularTrimmedSurface(BAP.Plane(),u1,u2,v1,v2);
} //if (nopt != 3)
//Comparing metrics of curves and projected curves
if (NTLinCont != 0 && myIsLinear)
{
Handle( Geom_Surface ) InitPlane =
(Handle( Geom_RectangularTrimmedSurface )::DownCast(mySurfInit))->BasisSurface();
Standard_Real Ratio = 0., R1 = 2., R2 = 0.6; //R1 = 3, R2 = 0.5;//R1 = 1.4, R2 = 0.8; //R1 = 5., R2 = 0.2;
Handle( GeomAdaptor_Surface ) hsur =
new GeomAdaptor_Surface( InitPlane );
Standard_Integer NbPoint = 20;
// gp_Pnt P;
// gp_Vec DerC, DerCproj, DU, DV;
// gp_Pnt2d P2d;
// gp_Vec2d DProj;
for (Standard_Integer i = 1; i <= NTLinCont && myIsLinear; i++)
{
Standard_Real FirstPar = myLinCont->Value(i)->FirstParameter();
Standard_Real LastPar = myLinCont->Value(i)->LastParameter();
Standard_Real Uif = (LastPar - FirstPar)/(NbPoint);
Handle( Adaptor3d_Curve ) Curve = myLinCont->Value(i)->Curve3d();
Handle( ProjLib_HCompProjectedCurve ) ProjCurve = new ProjLib_HCompProjectedCurve (hsur, Curve, myTol3d, myTol3d);
Adaptor3d_CurveOnSurface AProj(ProjCurve, hsur);
gp_Pnt P;
gp_Vec DerC, DerCproj;
for (Standard_Integer j = 1 ; j < NbPoint && myIsLinear; j++)
{
Standard_Real Inter = FirstPar + j*Uif;
Curve->D1(Inter, P, DerC);
AProj.D1(Inter, P, DerCproj);
Standard_Real A1 = DerC.Magnitude();
Standard_Real A2 = DerCproj.Magnitude();
if (A2 <= 1.e-20) {
Ratio = 1.e20;
}
else {
Ratio = A1 / A2;
}
if (Ratio > R1 || Ratio < R2)
{
myIsLinear = Standard_False;
break;
}
}
}
#ifdef OCCT_DEBUG
if (! myIsLinear)
std::cout <<"Metrics are too different :"<< Ratio<<std::endl;
#endif
// myIsLinear = Standard_True; // !!
} //comparing metrics of curves and projected curves
if (! myIsLinear)
{
myPlanarSurfInit = mySurfInit;
#ifdef DRAW
if (Affich) {
char name[256];
sprintf(name,"planinit_%d",NbPlan+1);
DrawTrSurf::Set(name, mySurfInit);
}
#endif
Standard_Real u1,v1,u2,v2;
mySurfInit->Bounds(u1,v1,u2,v2);
GeomAdaptor_Surface Surf(mySurfInit);
myTolU = Surf.UResolution(myTol3d);
myTolV = Surf.VResolution(myTol3d);
myProj.Initialize(Surf,u1,v1,u2,v2,
myTolU,myTolV);
//======================================================================
// Projection of curves
//======================================================================
Standard_Integer i;
for (i = 1; i <= NTLinCont; i++)
if (myLinCont->Value(i)->Curve2dOnSurf().IsNull())
myLinCont->ChangeValue(i)->SetCurve2dOnSurf(ProjectCurve(myLinCont->Value(i)->Curve3d()));
//======================================================================
// Projection of points
//======================================================================
for (i = 1; i<=NTPntCont; i++)
{ gp_Pnt P;
myPntCont->Value(i)->D0(P);
if (!myPntCont->Value(i)->HasPnt2dOnSurf())
myPntCont->ChangeValue(i)->SetPnt2dOnSurf(ProjectPoint(P));
}
//======================================================================
// Number of points by curve
//======================================================================
if ((NTLinCont !=0)&&(myNbPtsOnCur!=0))
CalculNbPtsInit();
//======================================================================
// Management of incompatibilities between curves
//======================================================================
Handle(GeomPlate_HArray1OfSequenceOfReal) PntInter;
Handle(GeomPlate_HArray1OfSequenceOfReal) PntG1G1;
if (NTLinCont != 0)
{
PntInter = new GeomPlate_HArray1OfSequenceOfReal(1,NTLinCont);
PntG1G1 = new GeomPlate_HArray1OfSequenceOfReal(1,NTLinCont);
Intersect(PntInter, PntG1G1);
}
//====================================================================
// Discretization of curves
//====================================================================
Discretise(PntInter, PntG1G1);
//====================================================================
//Preparation of points of constraint for plate
//====================================================================
LoadCurve( 0, 0 );
if (myPntCont->Length() != 0)
LoadPoint( 0, 0 );
//====================================================================
// Construction of the surface
//====================================================================
Message_ProgressScope aPS(theProgress, "ComputeSurfInit", 1);
myPlate.SolveTI(2, ComputeAnisotropie(), aPS.Next());
if (theProgress.UserBreak())
{
return;
}
if (!myPlate.IsDone())
{
#ifdef OCCT_DEBUG
std::cout << "WARNING : GeomPlate : calculation of Plate failed" << std::endl;
#endif
return;
}
myGeomPlateSurface = new GeomPlate_Surface( mySurfInit, myPlate );
GeomPlate_MakeApprox App(myGeomPlateSurface, myTol3d,
1, 3,
15*myTol3d,
-1, GeomAbs_C0);
mySurfInit = App.Surface();
mySurfInitIsGive = Standard_True;
myPlate.Init(); // Reset
for (i=1;i<=NTLinCont;i++)
{
Handle( Geom2d_Curve ) NullCurve;
NullCurve.Nullify();
myLinCont->ChangeValue(i)->SetCurve2dOnSurf( NullCurve);
}
}
#ifdef DRAW
if (Affich) {
char name[256];
sprintf(name,"surfinit_%d",++NbPlan);
DrawTrSurf::Set(name, mySurfInit);
}
#endif
}
//---------------------------------------------------------
// Function : Intersect
//---------------------------------------------------------
// Find intersections between 2d curves
// If the intersection is compatible (in cases G1-G1)
// remove the point on one of two curves
//---------------------------------------------------------
void GeomPlate_BuildPlateSurface::
Intersect(Handle(GeomPlate_HArray1OfSequenceOfReal)& PntInter,
Handle(GeomPlate_HArray1OfSequenceOfReal)& PntG1G1)
{
Standard_Integer NTLinCont = myLinCont->Length();
Geom2dInt_GInter Intersection;
Geom2dAdaptor_Curve Ci, Cj;
IntRes2d_IntersectionPoint int2d;
gp_Pnt P1,P2;
gp_Pnt2d P2d;
gp_Vec2d V2d;
// if (!mySurfInitIsGive)
for (Standard_Integer i=1;i<=NTLinCont;i++)
{
//Standard_Real NbPnt_i=myLinCont->Value(i)->NbPoints();
// Find the intersection with each curve including the curve itself
Ci.Load(myLinCont->Value(i)->Curve2dOnSurf());
for(Standard_Integer j=i; j<=NTLinCont; j++)
{
Cj.Load(myLinCont->Value(j)->Curve2dOnSurf());
if (i==j)
Intersection.Perform(Ci, myTol2d*10, myTol2d*10);
else
Intersection.Perform(Ci, Cj, myTol2d*10, myTol2d*10);
if (!Intersection.IsEmpty())
{ // there is one intersection
Standard_Integer nbpt = Intersection.NbPoints();
// number of points of intersection
for (Standard_Integer k = 1; k <= nbpt; k++)
{ int2d = Intersection.Point(k);
myLinCont->Value(i)->D0(int2d.ParamOnFirst(),P1);
myLinCont->Value(j)->D0(int2d.ParamOnSecond(),P2);
#ifdef OCCT_DEBUG
if (Affich> 1)
{
std::cout << " Intersection "<< k << " entre " << i
<< " &" << j << std::endl;
std::cout <<" Distance = "<< P1.Distance(P2) << std::endl;
}
#endif
if (P1.Distance( P2 ) < myTol3d)
{ // 2D intersection corresponds to close 3D points.
// Note the interval, in which the point needs to be removed
// to avoid duplications, which cause
// error in plate. The point on curve i is removed;
// the point on curve j is preserved;
// the length of interval is a length 2d
// corresponding in 3d to myTol3d
Standard_Real tolint = Ci.Resolution(myTol3d);
Ci.D1(int2d.ParamOnFirst(),P2d, V2d);
Standard_Real aux = V2d.Magnitude();
if (aux > 1.e-7)
{
aux = myTol3d/aux;
if (aux > 100*tolint) tolint*=100;
else tolint = aux;
}
else tolint*=100;
PntInter->ChangeValue(i).Append( int2d.ParamOnFirst() - tolint);
PntInter->ChangeValue(i).Append( int2d.ParamOnFirst() + tolint);
// If G1-G1
if ( (myLinCont->Value(i)->Order()==1)
&&(myLinCont->Value(j)->Order()==1))
{ gp_Vec v11,v12,v13,v14,v15,v16,v21,v22,v23,v24,v25,v26;
myLinCont->Value(i)->D2( int2d.ParamOnFirst(), P1, v11, v12, v13, v14, v15 );
myLinCont->Value(j)->D2( int2d.ParamOnSecond(), P2, v21, v22, v23, v24, v25 );
v16=v11^v12;v26=v21^v22;
Standard_Real ant=v16.Angle(v26);
if (ant>(M_PI/2))
ant= M_PI -ant;
if ((Abs(v16*v15-v16*v25)>(myTol3d/1000))
||(Abs(ant)>myTol3d/1000))
// Non-compatible ==> remove zone in constraint G1
// corresponding to 3D tolerance of 0.01
{ Standard_Real coin;
Standard_Real Tol= 100 * myTol3d;
Standard_Real A1;
gp_Pnt2d P1temp,P2temp;
gp_Vec2d V1,V2;
myLinCont->Value(i)->Curve2dOnSurf()->D1( int2d.ParamOnFirst(), P1temp, V1);
myLinCont->Value(j)->Curve2dOnSurf()->D1( int2d.ParamOnSecond(), P2temp, V2);
A1 = V1.Angle(V2);
if (A1>(M_PI/2))
A1= M_PI - A1;
if (Abs(Abs(A1)-M_PI)<myTolAng) Tol = 100000 * myTol3d;
#ifdef OCCT_DEBUG
if (Affich) std::cout <<"Angle between curves "<<i<<","<<j
<<" "<<Abs(Abs(A1)-M_PI)<<std::endl;
#endif
coin = Ci.Resolution(Tol);
Standard_Real Par1=int2d.ParamOnFirst()-coin,
Par2=int2d.ParamOnFirst()+coin;
// Storage of the interval for curve i
PntG1G1->ChangeValue(i).Append(Par1);
PntG1G1->ChangeValue(i).Append(Par2);
coin = Cj.Resolution(Tol);
Par1=int2d.ParamOnSecond()-coin;
Par2=int2d.ParamOnSecond()+coin;
// Storage of the interval for curve j
PntG1G1->ChangeValue(j).Append(Par1);
PntG1G1->ChangeValue(j).Append(Par2);
}
}
// If G0-G1
if ((myLinCont->Value(i)->Order()==0 && myLinCont->Value(j)->Order()==1) ||
(myLinCont->Value(i)->Order()==1 && myLinCont->Value(j)->Order()==0))
{
gp_Vec vec, vecU, vecV, N;
if (myLinCont->Value(i)->Order() == 0)
{
Handle( Adaptor3d_Curve ) theCurve = myLinCont->Value(i)->Curve3d();
theCurve->D1( int2d.ParamOnFirst(), P1, vec );
myLinCont->Value(j)->D1( int2d.ParamOnSecond(), P2, vecU, vecV );
}
else
{
Handle( Adaptor3d_Curve ) theCurve = myLinCont->Value(j)->Curve3d();
theCurve->D1( int2d.ParamOnSecond(), P2, vec );
myLinCont->Value(i)->D1( int2d.ParamOnFirst(), P1, vecU, vecV );
}
N = vecU ^ vecV;
Standard_Real Angle = vec.Angle( N );
Angle = Abs( M_PI/2-Angle );
if (Angle > myTolAng/10.) //????????? //if (Abs( scal ) > myTol3d/100)
{
// Non-compatible ==> one removes zone in constraint G0 and G1
// corresponding to 3D tolerance of 0.01
Standard_Real coin;
Standard_Real Tol= 100 * myTol3d;
Standard_Real A1;
gp_Pnt2d P1temp,P2temp;
gp_Vec2d V1,V2;
myLinCont->Value(i)->Curve2dOnSurf()->D1( int2d.ParamOnFirst(), P1temp, V1);
myLinCont->Value(j)->Curve2dOnSurf()->D1( int2d.ParamOnSecond(), P2temp, V2);
A1 = V1.Angle( V2 );
if (A1 > M_PI/2)
A1= M_PI - A1;
if (Abs(Abs(A1) - M_PI) < myTolAng) Tol = 100000 * myTol3d;
#ifdef OCCT_DEBUG
if (Affich) std::cout <<"Angle entre Courbe "<<i<<","<<j
<<" "<<Abs(Abs(A1)-M_PI)<<std::endl;
#endif
if (myLinCont->Value(i)->Order() == 1)
{
coin = Ci.Resolution(Tol);
coin *= Angle / myTolAng * 10.;
#ifdef OCCT_DEBUG
std::cout<<std::endl<<"coin = "<<coin<<std::endl;
#endif
Standard_Real Par1 = int2d.ParamOnFirst() - coin;
Standard_Real Par2 = int2d.ParamOnFirst() + coin;
// Storage of the interval for curve i
PntG1G1->ChangeValue(i).Append( Par1 );
PntG1G1->ChangeValue(i).Append( Par2 );
}
else
{
coin = Cj.Resolution(Tol);
coin *= Angle / myTolAng * 10.;
#ifdef OCCT_DEBUG
std::cout<<std::endl<<"coin = "<<coin<<std::endl;
#endif
Standard_Real Par1 = int2d.ParamOnSecond() - coin;
Standard_Real Par2 = int2d.ParamOnSecond() + coin;
// Storage of the interval for curve j
PntG1G1->ChangeValue(j).Append( Par1 );
PntG1G1->ChangeValue(j).Append( Par2 );
}
}
}
} //if (P1.Distance( P2 ) < myTol3d)
else {
// 2D intersection corresponds to extended 3D points.
// Note the interval where it is necessary to remove
// the points to avoid duplications causing
// error in plate. The point on curve i is removed,
// the point on curve j is preserved.
// The length of interval is 2D length
// corresponding to the distance of points in 3D to myTol3d
Standard_Real tolint, Dist;
Dist = P1.Distance(P2);
tolint = Ci.Resolution(Dist);
PntInter->ChangeValue(i).Append( int2d.ParamOnFirst() - tolint);
PntInter->ChangeValue(i).Append( int2d.ParamOnFirst() + tolint);
if (j!=i)
{
tolint = Cj.Resolution(Dist);
PntInter->ChangeValue(j).
Append( int2d.ParamOnSecond() - tolint);
PntInter->ChangeValue(j).
Append( int2d.ParamOnSecond() + tolint);
}
#ifdef OCCT_DEBUG
std::cout << "Attention: Two points 3d have the same projection dist = " << Dist << std::endl;
#endif
#ifdef DRAW
if (Affich > 1)
{
Handle(Draw_Marker3D) mark = new (Draw_Marker3D)(P1, Draw_X, Draw_vert);
char name[256];
sprintf(name,"mark_%d",++NbMark);
Draw::Set(name, mark);
}
#endif
}
}
}
}
}
}
//---------------------------------------------------------
// Function : Discretize
//---------------------------------------------------------
// Discretize curves according to parameters
// the table of sequences Parcont contains all
// parameter of points on curves
// Field myPlateCont contains parameter of points on a plate;
// it excludes duplicate points and incompatible zones.
// The first part corresponds to verification of compatibility
// and to removal of duplicate points.
//---------------------------------------------------------
void GeomPlate_BuildPlateSurface::
Discretise(const Handle(GeomPlate_HArray1OfSequenceOfReal)& PntInter,
const Handle(GeomPlate_HArray1OfSequenceOfReal)& PntG1G1)
{
Standard_Integer NTLinCont = myLinCont->Length();
Standard_Boolean ACR;
Handle(Geom2d_Curve) C2d;
Geom2dAdaptor_Curve AC2d;
// Handle(Adaptor_HCurve2d) HC2d;
Handle(Law_Interpol) acrlaw = new (Law_Interpol) ();
myPlateCont = new GeomPlate_HArray1OfSequenceOfReal(1,NTLinCont);
myParCont = new GeomPlate_HArray1OfSequenceOfReal(1,NTLinCont);
//===========================================================================
// Construction of the table containing parameters of constraint points
//===========================================================================
Standard_Real Uinit, Ufinal, Length2d=0, Inter;
Standard_Real CurLength;
Standard_Integer NbPnt_i, NbPtInter, NbPtG1G1;
Handle(GeomPlate_CurveConstraint) LinCont;
for (Standard_Integer i=1;i<=NTLinCont;i++) {
LinCont = myLinCont->Value(i);
Uinit=LinCont->FirstParameter();
Ufinal=LinCont->LastParameter();
// HC2d=LinCont->ProjectedCurve();
// if(HC2d.IsNull())
// ACR = (!HC2d.IsNull() || !C2d.IsNull());
C2d= LinCont->Curve2dOnSurf();
ACR = (!C2d.IsNull());
if (ACR) {
// Construct a law close to curvilinear abscissa
if(!C2d.IsNull()) AC2d.Load(C2d);
// AC2d.Load(LinCont->Curve2dOnSurf());
Standard_Integer ii, Nbint = 20;
Standard_Real U;
TColgp_Array1OfPnt2d tabP2d(1, Nbint+1);
tabP2d(1).SetY(Uinit);
tabP2d(1).SetX(0.);
tabP2d(Nbint+1).SetY(Ufinal);
/* if (!HC2d.IsNull())
Length2d = GCPnts_AbscissaPoint::Length(HC2d->Curve2d(), Uinit, Ufinal);
else*/
Length2d = GCPnts_AbscissaPoint::Length(AC2d, Uinit, Ufinal);
tabP2d(Nbint+1).SetX(Length2d);
for (ii = 2; ii<= Nbint; ii++) {
U = Uinit + (Ufinal-Uinit)*((1-Cos((ii-1)*M_PI/(Nbint)))/2);
tabP2d(ii).SetY(U);
/* if (!HC2d.IsNull()) {
Standard_Real L = GCPnts_AbscissaPoint::Length(HC2d->Curve2d(), Uinit, U);
tabP2d(ii).SetX(L);
}
else*/
tabP2d(ii).SetX(GCPnts_AbscissaPoint::Length(AC2d, Uinit, U));
}
acrlaw->Set(tabP2d);
}
NbPnt_i = (Standard_Integer )( LinCont->NbPoints());
NbPtInter= PntInter->Value(i).Length();
NbPtG1G1= PntG1G1->Value(i).Length();
#ifdef OCCT_DEBUG
if (Affich > 1) {
std::cout << "Courbe : " << i << std::endl;
std::cout << " NbPnt, NbPtInter, NbPtG1G1 :" << NbPnt_i << ", "
<< NbPtInter << ", " << NbPtG1G1 << std::endl;
}
#endif
for (Standard_Integer j=1; j<=NbPnt_i; j++)
{
// Distribution of points in cosine following ACR 2D
// To avoid points of accumulation in 2D
//Inter=Uinit+(Uif)*((-cos(M_PI*((j-1)/(NbPnt_i-1)))+1)/2);
if (j==NbPnt_i)
Inter=Ufinal;// to avoid bug on Sun
else if (ACR) {
CurLength = Length2d*(1-Cos((j-1)*M_PI/(NbPnt_i-1)))/2;
Inter = acrlaw->Value(CurLength);
}
else {
Inter=Uinit+(Ufinal-Uinit)*((1-Cos((j-1)*M_PI/(NbPnt_i-1)))/2);
}
myParCont->ChangeValue(i).Append(Inter);// add a point
if (NbPtInter!=0)
{
for(Standard_Integer l=1;l<=NbPtInter;l+=2)
{
// check if the point Inter is in the interval
// PntInter[i] PntInter[i+1]
// in which case it is not necessary to store it (problem with duplicates)
if ((Inter>PntInter->Value(i).Value(l))
&&(Inter<PntInter->Value(i).Value(l+1)))
{
l=NbPtInter+2;
// leave the loop without storing the point
}
else
{
if (l+1>=NbPtInter) {
// one has parsed the entire table : the point
// does not belong to a common point interval
if (NbPtG1G1!=0)
{
// if there exists an incompatible interval
for(Standard_Integer k=1;k<=NbPtG1G1;k+=2)
{
if ((Inter>PntG1G1->Value(i).Value(k))
&&(Inter<PntG1G1->Value(i).Value(k+1)))
{
k=NbPtG1G1+2; // to leave the loop
// Add points of constraint G0
gp_Pnt P3d,PP,Pdif;
gp_Pnt2d P2d;
AC2d.D0(Inter, P2d);
LinCont->D0(Inter,P3d);
mySurfInit->D0(P2d.Coord(1),P2d.Coord(2),PP);
Pdif.SetCoord(-PP.Coord(1)+P3d.Coord(1),
-PP.Coord(2)+P3d.Coord(2),
-PP.Coord(3)+P3d.Coord(3));
Plate_PinpointConstraint PC(P2d.XY(),Pdif.XYZ(),0,0);
myPlate.Load(PC);
}
else // the point does not belong to interval G1
{
if (k+1>=NbPtG1G1)
{
myPlateCont->ChangeValue(i).Append(Inter);
// add the point
}
}
}
}
else
{
myPlateCont->ChangeValue(i).Append(Inter);
// add the point
}
}
}
}
}
else
{
if (NbPtG1G1!=0) // there exist an incompatible interval
{
for(Standard_Integer k=1;k<=NbPtG1G1;k+=2)
{
if ((Inter>PntG1G1->Value(i).Value(k))
&&(Inter<PntG1G1->Value(i).Value(k+1)))
{
k=NbPtG1G1+2; // to leave the loop
// Add points of constraint G0
gp_Pnt P3d,PP,Pdif;
gp_Pnt2d P2d;
AC2d.D0(Inter, P2d);
LinCont->D0(Inter,P3d);
mySurfInit->D0(P2d.Coord(1),P2d.Coord(2),PP);
Pdif.SetCoord(-PP.Coord(1)+P3d.Coord(1),
-PP.Coord(2)+P3d.Coord(2),
-PP.Coord(3)+P3d.Coord(3));
Plate_PinpointConstraint PC(P2d.XY(),Pdif.XYZ(),0,0);
myPlate.Load(PC);
}
else // the point does not belong to interval G1
{
if (k+1>=NbPtG1G1)
{
myPlateCont->ChangeValue(i).Append(Inter);
// add the point
}
}
}
}
else
{
if ( ( (!mySurfInitIsGive)
&&(Geom2dAdaptor_Curve(LinCont->Curve2dOnSurf()).GetType()!=GeomAbs_Circle))
|| ( (j>1) &&(j<NbPnt_i))) // exclude extremeties
myPlateCont->ChangeValue(i).Append(Inter);// add the point
}
}
}
}
}
//---------------------------------------------------------
// Function : CalculNbPtsInit
//---------------------------------------------------------
// Calculate the number of points by curve depending on the
// length for the first iteration
//---------------------------------------------------------
void GeomPlate_BuildPlateSurface::CalculNbPtsInit ()
{
Standard_Real LenT=0;
Standard_Integer NTLinCont=myLinCont->Length();
Standard_Integer NTPoint=(Standard_Integer )( myNbPtsOnCur*NTLinCont);
Standard_Integer i ;
for ( i=1;i<=NTLinCont;i++)
LenT+=myLinCont->Value(i)->Length();
for ( i=1;i<=NTLinCont;i++)
{ Standard_Integer Cont=myLinCont->Value(i)->Order();
switch(Cont)
{ case 0 : // Case G0 *1.2
myLinCont->ChangeValue(i)->SetNbPoints(
Standard_Integer(1.2*NTPoint*(myLinCont->Value(i)->Length())/LenT));
break;
case 1 : // Case G1 *1
myLinCont->ChangeValue(i)->SetNbPoints(
Standard_Integer(NTPoint*(myLinCont->Value(i)->Length())/LenT));
break;
case 2 : // Case G2 *0.7
myLinCont->ChangeValue(i)->SetNbPoints(
Standard_Integer(0.7*NTPoint*(myLinCont->Value(i)->Length())/LenT));
break;
}
if (myLinCont->Value(i)->NbPoints()<3)
myLinCont->ChangeValue(i)->SetNbPoints(3);
}
}
//---------------------------------------------------------
// Function : LoadCurve
//---------------------------------------------------------
// Starting from table myParCont load all the points noted in plate
//---------------------------------------------------------
void GeomPlate_BuildPlateSurface::LoadCurve(const Standard_Integer NbBoucle,
const Standard_Integer OrderMax )
{
gp_Pnt P3d,Pdif,PP;
gp_Pnt2d P2d;
Standard_Integer NTLinCont=myLinCont->Length(), i, j;
Standard_Integer Tang, Nt;
for (i=1; i<=NTLinCont; i++){
Handle(GeomPlate_CurveConstraint) CC = myLinCont->Value(i);
if (CC ->Order()!=-1) {
Tang = Min(CC->Order(), OrderMax);
Nt = myPlateCont->Value(i).Length();
if (Tang!=-1)
for (j=1; j<=Nt; j++) {// Loading of points G0 on boundaries
CC ->D0(myPlateCont->Value(i).Value(j),P3d);
if (!CC->ProjectedCurve().IsNull())
P2d = CC->ProjectedCurve()->Value(myPlateCont->Value(i).Value(j));
else {
if (!CC->Curve2dOnSurf().IsNull())
P2d = CC->Curve2dOnSurf()->Value(myPlateCont->Value(i).Value(j));
else
P2d = ProjectPoint(P3d);
}
mySurfInit->D0(P2d.Coord(1),P2d.Coord(2),PP);
Pdif.SetCoord(-PP.Coord(1)+P3d.Coord(1),
-PP.Coord(2)+P3d.Coord(2),
-PP.Coord(3)+P3d.Coord(3));
Plate_PinpointConstraint PC(P2d.XY(),Pdif.XYZ(),0,0);
myPlate.Load(PC);
// Loading of points G1
if (Tang==1) { // ==1
gp_Vec V1,V2,V3,V4;
CC->D1( myPlateCont->Value(i).Value(j), PP, V1, V2 );
mySurfInit->D1( P2d.Coord(1), P2d.Coord(2), PP, V3, V4 );
Plate_D1 D1final(V1.XYZ(),V2.XYZ());
Plate_D1 D1init(V3.XYZ(),V4.XYZ());
if (! myFree)
{
Plate_GtoCConstraint GCC( P2d.XY(), D1init, D1final );
myPlate.Load(GCC);
}
else if (NbBoucle == 1)
{
Plate_FreeGtoCConstraint FreeGCC( P2d.XY(), D1init, D1final );
myPlate.Load( FreeGCC );
}
else {
gp_Vec DU, DV, Normal, DerPlateU, DerPlateV;
Normal = V1^V2;
//Normal.Normalize();
Standard_Real norm = Normal.Magnitude();
if (norm > 1.e-12) Normal /= norm;
DerPlateU = myPrevPlate.EvaluateDerivative( P2d.XY(), 1, 0 );
DerPlateV = myPrevPlate.EvaluateDerivative( P2d.XY(), 0, 1 );
DU.SetLinearForm(-(V3 + DerPlateU).Dot(Normal), Normal, DerPlateU);
DV.SetLinearForm(-(V4 + DerPlateV).Dot(Normal), Normal, DerPlateV);
Plate_PinpointConstraint PinU( P2d.XY(), DU.XYZ(), 1, 0 );
Plate_PinpointConstraint PinV( P2d.XY(), DV.XYZ(), 0, 1 );
myPlate.Load( PinU );
myPlate.Load( PinV );
}
}
// Loading of points G2
if (Tang==2) // ==2
{ gp_Vec V1,V2,V3,V4,V5,V6,V7,V8,V9,V10;
CC->D2(myPlateCont->Value(i).Value(j),
PP,V1,V2,V5,V6,V7);
mySurfInit->D2(P2d.Coord(1),P2d.Coord(2),PP,V3,V4,V8,V9,V10);
Plate_D1 D1final(V1.XYZ(),V2.XYZ());
Plate_D1 D1init(V3.XYZ(),V4.XYZ());
Plate_D2 D2final (V5.XYZ(),V6.XYZ(),V7.XYZ());
Plate_D2 D2init (V8.XYZ(),V9.XYZ(),V10.XYZ());
// if (! myFree)
// {
Plate_GtoCConstraint GCC(P2d.XY(),D1init,D1final,D2init,D2final);
myPlate.Load(GCC);
// }
// else // Good but too expansive
// {
// Plate_FreeGtoCConstraint FreeGCC( P2d.XY(),
// D1init, D1final, D2init, D2final );
// myPlate.Load( FreeGCC );
// }
}
}
}
}
}
//---------------------------------------------------------
// Function : LoadPoint
//---------------------------------------------------------
//void GeomPlate_BuildPlateSurface::LoadPoint(const Standard_Integer NbBoucle,
void GeomPlate_BuildPlateSurface::LoadPoint(const Standard_Integer ,
const Standard_Integer OrderMax)
{
gp_Pnt P3d,Pdif,PP;
gp_Pnt2d P2d;
Standard_Integer NTPntCont=myPntCont->Length();
Standard_Integer Tang, i;
// gp_Vec V1,V2,V3,V4,V5,V6,V7,V8,V9,V10;
// Loading of points of point constraints
for (i=1;i<=NTPntCont;i++) {
myPntCont->Value(i)->D0(P3d);
P2d = myPntCont->Value(i)->Pnt2dOnSurf();
mySurfInit->D0(P2d.Coord(1),P2d.Coord(2),PP);
Pdif.SetCoord(-PP.Coord(1)+P3d.Coord(1),
-PP.Coord(2)+P3d.Coord(2),
-PP.Coord(3)+P3d.Coord(3));
Plate_PinpointConstraint PC(P2d.XY(),Pdif.XYZ(),0,0);
myPlate.Load(PC);
Tang = Min(myPntCont->Value(i)->Order(), OrderMax);
if (Tang==1) {// ==1
gp_Vec V1,V2,V3,V4;
myPntCont->Value(i)->D1(PP,V1,V2);
mySurfInit->D1(P2d.Coord(1),P2d.Coord(2),PP,V3,V4);
Plate_D1 D1final(V1.XYZ(),V2.XYZ());
Plate_D1 D1init(V3.XYZ(),V4.XYZ());
if (! myFree)
{
Plate_GtoCConstraint GCC( P2d.XY(), D1init, D1final );
myPlate.Load( GCC );
}
else
{
Plate_FreeGtoCConstraint FreeGCC( P2d.XY(), D1init, D1final );
myPlate.Load( FreeGCC );
}
}
// Loading of points G2 GeomPlate_PlateG0Criterion
if (Tang==2) // ==2
{ gp_Vec V1,V2,V3,V4,V5,V6,V7,V8,V9,V10;
myPntCont->Value(i)->D2(PP,V1,V2,V5,V6,V7);
// gp_Vec Tv2 = V1^V2;
mySurfInit->D2(P2d.Coord(1),P2d.Coord(2),PP,V3,V4,V8,V9,V10);
Plate_D1 D1final(V1.XYZ(),V2.XYZ());
Plate_D1 D1init(V3.XYZ(),V4.XYZ());
Plate_D2 D2final (V5.XYZ(),V6.XYZ(),V7.XYZ());
Plate_D2 D2init (V8.XYZ(),V9.XYZ(),V10.XYZ());
// if (! myFree)
// {
Plate_GtoCConstraint GCC( P2d.XY(), D1init, D1final, D2init, D2final );
myPlate.Load( GCC );
// }
// else // Good but too expansive
// {
// Plate_FreeGtoCConstraint FreeGCC( P2d.XY(), D1init, D1final, D2init//, D2final );
// myPlate.Load( FreeGCC );
// }
}
}
}
//---------------------------------------------------------
// Function : VerifSurface
//---------------------------------------------------------
Standard_Boolean GeomPlate_BuildPlateSurface::
VerifSurface(const Standard_Integer NbBoucle)
{
//======================================================================
// Calculate errors
//======================================================================
Standard_Integer NTLinCont=myLinCont->Length();
Standard_Boolean Result=Standard_True;
// variable for error calculation
myG0Error=0,myG1Error =0, myG2Error=0;
for (Standard_Integer i=1;i<=NTLinCont;i++) {
Handle(GeomPlate_CurveConstraint) LinCont;
LinCont = myLinCont->Value(i);
if (LinCont->Order()!=-1) {
Standard_Integer NbPts_i = myParCont->Value(i).Length();
if (NbPts_i<3)
NbPts_i=4;
Handle(TColStd_HArray1OfReal) tdist =
new TColStd_HArray1OfReal(1,NbPts_i-1);
Handle(TColStd_HArray1OfReal) tang =
new TColStd_HArray1OfReal(1,NbPts_i-1);
Handle(TColStd_HArray1OfReal) tcourb =
new TColStd_HArray1OfReal(1,NbPts_i-1);
EcartContraintesMil (i,tdist,tang,tcourb);
Standard_Real diffDistMax=0, diffAngMax=0;
//Standard_Real SdiffDist=0, SdiffAng=0;
Standard_Integer NdiffDist=0,NdiffAng=0;
for (Standard_Integer j=1;j<NbPts_i;j++)
{ if (tdist->Value(j)>myG0Error)
myG0Error=tdist->Value(j);
if (tang->Value(j)>myG1Error)
myG1Error=tang->Value(j);
if (tcourb->Value(j)>myG2Error)
myG2Error=tcourb->Value(j);
Standard_Real U;
if (myParCont->Value(i).Length()>3)
U=(myParCont->Value(i).Value(j)+myParCont->Value(i).Value(j+1))/2;
else
U=LinCont->FirstParameter()+
( LinCont->LastParameter()-LinCont->FirstParameter())*(j-1)/(NbPts_i-2);
Standard_Real diffDist=tdist->Value(j)-LinCont->G0Criterion(U),diffAng;
if (LinCont->Order()>0)
diffAng=tang->Value(j)-LinCont->G1Criterion(U);
else diffAng=0;
// find the maximum variation of error and calculate the average
if (diffDist>0) {
diffDist = diffDist/LinCont->G0Criterion(U);
if (diffDist>diffDistMax)
diffDistMax = diffDist;
//SdiffDist+=diffDist;
NdiffDist++;
#ifdef DRAW
if ((Affich) && (NbBoucle == myNbIter)) {
gp_Pnt P;
gp_Pnt2d P2d;
LinCont->D0(U,P);
Handle(Draw_Marker3D) mark =
new (Draw_Marker3D)(P, Draw_X, Draw_orange);
char name[256];
sprintf(name,"mark_%d",++NbMark);
Draw::Set(name, mark);
if (!LinCont->ProjectedCurve().IsNull())
P2d = LinCont->ProjectedCurve()->Value(U);
else
{ if (!LinCont->Curve2dOnSurf().IsNull())
P2d = LinCont->Curve2dOnSurf()->Value(U);
else
P2d = ProjectPoint(P);
}
sprintf(name,"mark2d_%d",++NbMark);
Handle(Draw_Marker2D) mark2d =
new (Draw_Marker2D)(P2d, Draw_X, Draw_orange);
Draw::Set(name, mark2d);
}
#endif
}
else
if ((diffAng>0)&&(LinCont->Order()==1)) {
diffAng=diffAng/myLinCont->Value(i)->G1Criterion(U);
if (diffAng>diffAngMax)
diffAngMax = diffAng;
//SdiffAng+=diffAng;
NdiffAng++;
#ifdef DRAW
if ((Affich) && (NbBoucle == myNbIter)) {
gp_Pnt P;
LinCont->D0(U,P);
Handle(Draw_Marker3D) mark =
new Draw_Marker3D(P, Draw_X, Draw_or);
char name[256];
sprintf(name,"mark_%d",++NbMark);
Draw::Set(name, mark);
}
#endif
}
}
if (NdiffDist>0) {// at least one point is not acceptable in G0
Standard_Real Coef;
if(LinCont->Order()== 0)
Coef = 0.6*Log(diffDistMax+7.4);
//7.4 corresponds to the calculation of min. coefficient = 1.2 is e^1.2/0.6
else
Coef = Log(diffDistMax+3.3);
//3.3 corresponds to calculation of min. coefficient = 1.2 donc e^1.2
if (Coef>3)
Coef=3;
//experimentally after the coefficient becomes bad for L cases
if ((NbBoucle>1)&&(diffDistMax>2))
{ Coef=1.6;
}
if (LinCont->NbPoints()>=Floor(LinCont->NbPoints()*Coef))
Coef=2;// to provide increase of the number of points
LinCont->SetNbPoints(Standard_Integer(LinCont->NbPoints() * Coef));
Result=Standard_False;
}
else
if (NdiffAng>0) // at least 1 point is not acceptable in G1
{ Standard_Real Coef=1.5;
if ((LinCont->NbPoints()+1)>=Floor(LinCont->NbPoints()*Coef))
Coef=2;
LinCont->SetNbPoints(Standard_Integer(LinCont->NbPoints()*Coef )) ;
Result=Standard_False;
}
}
}
if (!Result)
{
if (myFree && NbBoucle == 1)
myPrevPlate = myPlate;
myPlate.Init();
}
return Result;
}
//---------------------------------------------------------
// Function : VerifPoint
//---------------------------------------------------------
void GeomPlate_BuildPlateSurface::
VerifPoints (Standard_Real& Dist,
Standard_Real& Ang,
Standard_Real& Curv) const
{ Standard_Integer NTPntCont=myPntCont->Length();
gp_Pnt Pi, Pf;
gp_Pnt2d P2d;
gp_Vec v1i, v1f, v2i, v2f, v3i, v3f;
Ang=0;Dist=0,Curv=0;
Handle(GeomPlate_PointConstraint) PntCont;
for (Standard_Integer i=1;i<=NTPntCont;i++) {
PntCont = myPntCont->Value(i);
switch (PntCont->Order())
{ case 0 :
P2d = PntCont->Pnt2dOnSurf();
PntCont->D0(Pi);
myGeomPlateSurface->D0( P2d.Coord(1), P2d.Coord(2), Pf);
Dist = Pf.Distance(Pi);
break;
case 1 :
PntCont->D1(Pi, v1i, v2i);
P2d = PntCont->Pnt2dOnSurf();
myGeomPlateSurface->D1( P2d.Coord(1), P2d.Coord(2), Pf, v1f, v2f);
Dist = Pf.Distance(Pi);
v3i = v1i^v2i; v3f=v1f^v2f;
Ang=v3f.Angle(v3i);
if (Ang>(M_PI/2))
Ang = M_PI -Ang;
break;
case 2 :
Handle(Geom_Surface) Splate (myGeomPlateSurface);
LocalAnalysis_SurfaceContinuity CG2;
P2d = PntCont->Pnt2dOnSurf();
GeomLProp_SLProps Prop (Splate, P2d.Coord(1), P2d.Coord(2),
2, 0.001);
CG2.ComputeAnalysis(Prop, PntCont->LPropSurf(),GeomAbs_G2);
Dist=CG2.C0Value();
Ang=CG2.G1Angle();
Curv=CG2.G2CurvatureGap();
break;
}
}
}
Standard_Real GeomPlate_BuildPlateSurface::ComputeAnisotropie() const
{
if (myAnisotropie)
{
//Temporary
return 1.0;
}
else return 1.0;
}
Standard_Boolean GeomPlate_BuildPlateSurface::IsOrderG1() const
{
Standard_Boolean result = Standard_True;
for (Standard_Integer i = 1; i <= myLinCont->Length(); i++)
if (myLinCont->Value(i)->Order() < 1)
{
result = Standard_False;
break;
}
return result;
}