1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-03 17:56:21 +03:00

0032995: Modeling algorithms - Interface for checking canonical geometry

GeomConvert_CurveToAnaCurve, GeomConvert_SurfToAnaSurf - geometrical algorithms
for converting geometrical curve and surfaces in canonical geometry with given tolerance.

ShapeAnalysis_CanonicalRecognition - interface for checking canonical geometry.
This commit is contained in:
ifv 2022-05-15 08:04:58 +03:00 committed by smoskvin
parent 7a52478f16
commit b47b075ac5
42 changed files with 4652 additions and 8 deletions

View File

@ -339,6 +339,7 @@ The <i>GeomConvert</i> package also provides the following:
* global functions to construct BSpline surfaces created by this splitting algorithm, or by other types of BSpline surface segmentation,
* an algorithm, which converts a BSpline surface into a series of adjacent Bezier surfaces,
* an algorithm, which converts a grid of adjacent Bezier surfaces into a BSpline surface.
* algorithms that converts NURBS, Bezier and other general parametrized curves and surface into anaytical curves and surfaces.
@subsection occt_modat_1_4 Points on Curves

View File

@ -1007,6 +1007,25 @@ Standard_Integer aNbOffsetSurfaces = aCheckContents.NbOffsetSurf();
Handle(TopTools_HSequenceOfShape) aSeqFaces = aCheckContents.OffsetSurfaceSec();
~~~~
@subsubsection occt_shg_3_2_4 Analysis of shape underlined geometry
Class *ShapeAnalysis_CanonicalRecognition* provides tools that analyze geometry of shape and explore the possibility of converting geometry into a canonical form.
Canonical forms for curves are lines, circles and ellipses.
Canonical forms for surfaces are planar, cylindrical, conical and spherical surfaces.
Recognition and converting into canonical form is performed according to maximal deviation criterium: maximal distance between initial and canonical geometrical objects must be less, than given value.
Analysis of curves is allowed for following shapes:
* edge - algorithm checks 3d curve of edge
* wire - algorithm checks 3d curves of all edges in order to convert them in the same analytical curve
Analysis of surfaces is allowed for following shapes:
* face - algorithm checks surface of face
* shell - algorithm checks surfaces of all faces in order to convert them in the same analytical surface
* edge - algorithm checks all surfaces that are shared by given edge in order convert one of them in analytical surface, which most close to the input sample surface.
* wire - the same as for edge, but algorithm checks all edges of wire in order to find analytical surface, which most close to the input sample surface.
@section occt_shg_4 Upgrading
Upgrading tools are intended for adaptation of shapes for better use by Open CASCADE Technology or for customization to particular needs, i.e. for export to another system.

View File

@ -20,3 +20,8 @@ GeomConvert_CompCurveToBSplineCurve.cxx
GeomConvert_CompCurveToBSplineCurve.hxx
GeomConvert_Units.cxx
GeomConvert_Units.hxx
GeomConvert_CurveToAnaCurve.cxx
GeomConvert_CurveToAnaCurve.hxx
GeomConvert_SurfToAnaSurf.cxx
GeomConvert_SurfToAnaSurf.hxx
GeomConvert_ConvType.hxx

View File

@ -0,0 +1,23 @@
// Copyright (c) 2022 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.
#ifndef _GeomConvert_ConvType_HeaderFile
#define _GeomConvert_ConvType_HeaderFile
enum GeomConvert_ConvType
{
GeomConvert_Target,
GeomConvert_Simplest,
GeomConvert_MinGap
};
#endif // _GeomConvert_ConvType_HeaderFile

View File

@ -0,0 +1,768 @@
// Created: 2001-05-21
//
// Copyright (c) 2001-2013 OPEN CASCADE SAS
//
// This file is part of commercial software by OPEN CASCADE SAS,
// furnished in accordance with the terms and conditions of the contract
// and with the inclusion of this copyright notice.
// This file or any part thereof may not be provided or otherwise
// made available to any third party.
//
// No ownership title to the software is transferred hereby.
//
// OPEN CASCADE SAS makes no representation or warranties with respect to the
// performance of this software, and specifically disclaims any responsibility
// for any damages, special or consequential, connected with its use.
#include <ElCLib.hxx>
#include <gce_MakeCirc.hxx>
#include <Geom_BezierCurve.hxx>
#include <Geom_BSplineCurve.hxx>
#include <Geom_Circle.hxx>
#include <Geom_Curve.hxx>
#include <Geom_Ellipse.hxx>
#include <Geom_Line.hxx>
#include <Geom_TrimmedCurve.hxx>
#include <gp_Ax2.hxx>
#include <gp_Ax3.hxx>
#include <gp_Circ.hxx>
#include <gp_Lin.hxx>
#include <gp_Pnt.hxx>
#include <gp_Vec.hxx>
#include <Precision.hxx>
#include <GeomConvert_CurveToAnaCurve.hxx>
#include <TColgp_Array1OfPnt.hxx>
#include <TColgp_HArray1OfPnt.hxx>
#include <TColStd_Array1OfReal.hxx>
#include <TColStd_Array2OfReal.hxx>
#include <GeomAbs_CurveType.hxx>
#include <math_Vector.hxx>
#include <math_Matrix.hxx>
#include <math_Gauss.hxx>
GeomConvert_CurveToAnaCurve::GeomConvert_CurveToAnaCurve():
myGap(Precision::Infinite()),
myConvType(GeomConvert_MinGap),
myTarget(GeomAbs_Line)
{
}
GeomConvert_CurveToAnaCurve::GeomConvert_CurveToAnaCurve(const Handle(Geom_Curve)& C) :
myGap(Precision::Infinite()),
myConvType(GeomConvert_MinGap),
myTarget(GeomAbs_Line)
{
myCurve = C;
}
void GeomConvert_CurveToAnaCurve::Init(const Handle(Geom_Curve)& C)
{
myCurve = C;
myGap = Precision::Infinite();
}
//=======================================================================
//function : ConvertToAnalytical
//purpose :
//=======================================================================
Standard_Boolean GeomConvert_CurveToAnaCurve::ConvertToAnalytical(const Standard_Real tol,
Handle(Geom_Curve)& theResultCurve,
const Standard_Real F, const Standard_Real L,
Standard_Real& NewF, Standard_Real& NewL)
{
if(myCurve.IsNull())
return Standard_False;
Handle(Geom_Curve) aCurve = myCurve;
while (aCurve->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) {
Handle(Geom_TrimmedCurve) aTrimmed = Handle(Geom_TrimmedCurve)::
DownCast(aCurve);
aCurve = aTrimmed->BasisCurve();
}
Handle(Geom_Curve) C = ComputeCurve(aCurve,tol,F, L, NewF, NewL, myGap, myConvType, myTarget);
if(C.IsNull()) return Standard_False;
theResultCurve = C;
return Standard_True;
}
//=======================================================================
//function : IsLinear
//purpose :
//=======================================================================
Standard_Boolean GeomConvert_CurveToAnaCurve::IsLinear(const TColgp_Array1OfPnt& aPoles,
const Standard_Real tolerance,
Standard_Real& Deviation)
{
Standard_Integer nbPoles = aPoles.Length();
if(nbPoles < 2)
return Standard_False;
Standard_Real dMax = 0;
Standard_Integer iMax1=0,iMax2=0;
Standard_Integer i;
for(i = 1; i < nbPoles; i++)
for(Standard_Integer j = i+1; j <= nbPoles; j++) {
Standard_Real dist = aPoles(i).SquareDistance(aPoles(j));
if(dist > dMax) {
dMax = dist;
iMax1 = i;
iMax2 = j;
}
}
if (dMax < Precision::SquareConfusion())
return Standard_False;
Standard_Real tol2 = tolerance*tolerance;
gp_Vec avec (aPoles(iMax1),aPoles(iMax2)); gp_Dir adir (avec); gp_Lin alin (aPoles(iMax1),adir);
Standard_Real aMax = 0.;
for(i = 1; i <= nbPoles; i++) {
Standard_Real dist = alin.SquareDistance(aPoles(i));
if(dist > tol2)
return Standard_False;
if(dist > aMax)
aMax = dist;
}
Deviation = sqrt(aMax);
return Standard_True;
}
//=======================================================================
//function : GetLine
//purpose :
//=======================================================================
gp_Lin GeomConvert_CurveToAnaCurve::GetLine(const gp_Pnt& P1, const gp_Pnt& P2,
Standard_Real& cf, Standard_Real& cl)
{
gp_Vec avec(P1, P2); gp_Dir adir(avec); gp_Lin alin(P1, adir);
cf = ElCLib::Parameter(alin, P1);
cl = ElCLib::Parameter(alin, P2);
return alin;
}
//=======================================================================
//function : ComputeLine
//purpose :
//=======================================================================
Handle(Geom_Line) GeomConvert_CurveToAnaCurve::ComputeLine (const Handle(Geom_Curve)& curve,
const Standard_Real tolerance,
const Standard_Real c1, const Standard_Real c2,
Standard_Real& cf, Standard_Real& cl,
Standard_Real& Deviation)
{
Handle(Geom_Line) line;
if (curve.IsNull()) return line;
line = Handle(Geom_Line)::DownCast(curve); // qui sait
if (!line.IsNull()) {
cf = c1;
cl = c2;
Deviation = 0.;
return line;
}
gp_Pnt P1 = curve->Value (c1);
gp_Pnt P2 = curve->Value (c2);
if(P1.SquareDistance(P2) < Precision::SquareConfusion())
return line;
cf = c1; cl = c2;
Handle(TColgp_HArray1OfPnt) Poles;
Standard_Integer nbPoles;
Handle(Geom_BSplineCurve) bsc = Handle(Geom_BSplineCurve)::DownCast(curve);
if (!bsc.IsNull()) {
nbPoles = bsc->NbPoles();
Poles = new TColgp_HArray1OfPnt(1, nbPoles);
bsc->Poles(Poles->ChangeArray1());
}
else
{
Handle(Geom_BezierCurve) bzc = Handle(Geom_BezierCurve)::DownCast(curve);
if (!bzc.IsNull()) {
nbPoles = bzc->NbPoles();
Poles = new TColgp_HArray1OfPnt(1, nbPoles);
bzc->Poles(Poles->ChangeArray1());
}
else
{
nbPoles = 23;
Poles = new TColgp_HArray1OfPnt(1, nbPoles);
Standard_Real dt = (c2 - c1) / (nbPoles - 1);
Poles->SetValue(1, P1);
Poles->SetValue(nbPoles, P2);
Standard_Integer i;
for (i = 2; i < nbPoles; ++i)
{
Poles->SetValue(i, curve->Value(c1 + (i - 1) * dt));
}
}
}
if(!IsLinear(Poles->Array1(),tolerance,Deviation)) return line; // non
gp_Lin alin = GetLine (P1, P2, cf, cl);
line = new Geom_Line (alin);
return line;
}
//=======================================================================
//function : GetCircle
//purpose :
//=======================================================================
Standard_Boolean GeomConvert_CurveToAnaCurve::GetCircle (gp_Circ& crc,
const gp_Pnt& P0,const gp_Pnt& P1, const gp_Pnt& P2)
{
// Control if points are not aligned (should be done by MakeCirc
Standard_Real aMaxCoord = Sqrt(Precision::Infinite());
if (Abs(P0.X()) > aMaxCoord || Abs(P0.Y()) > aMaxCoord || Abs(P0.Z()) > aMaxCoord)
return Standard_False;
if (Abs(P1.X()) > aMaxCoord || Abs(P1.Y()) > aMaxCoord || Abs(P1.Z()) > aMaxCoord)
return Standard_False;
if (Abs(P2.X()) > aMaxCoord || Abs(P2.Y()) > aMaxCoord || Abs(P2.Z()) > aMaxCoord)
return Standard_False;
// Building the circle
gce_MakeCirc mkc (P0,P1,P2);
if (!mkc.IsDone()) return Standard_False;
crc = mkc.Value();
if (crc.Radius() < gp::Resolution()) return Standard_False;
// Recalage sur P0
gp_Pnt PC = crc.Location();
gp_Ax2 axe = crc.Position();
gp_Vec VX (PC,P0);
axe.SetXDirection (VX);
crc.SetPosition (axe);
return Standard_True;
}
//=======================================================================
//function : ComputeCircle
//purpose :
//=======================================================================
Handle(Geom_Curve) GeomConvert_CurveToAnaCurve::ComputeCircle (const Handle(Geom_Curve)& c3d,
const Standard_Real tol,
const Standard_Real c1, const Standard_Real c2,
Standard_Real& cf, Standard_Real& cl,
Standard_Real& Deviation)
{
if (c3d->IsKind (STANDARD_TYPE(Geom_Circle))) {
cf = c1;
cl = c2;
Deviation = 0.;
Handle(Geom_Circle) aCirc = Handle(Geom_Circle)::DownCast(c3d);
return aCirc;
}
Handle(Geom_Circle) circ;
gp_Pnt P0,P1,P2;
Standard_Real ca = (c1+c1+c2) / 3; Standard_Real cb = (c1+c2+c2) / 3;
P0 = c3d->Value(c1);
P1 = c3d->Value(ca);
P2 = c3d->Value(cb);
gp_Circ crc;
if (!GetCircle (crc,P0,P1,P2)) return circ;
// Reste a controler que c est bien un cercle : prendre 20 points
Standard_Real du = (c2-c1)/20;
Standard_Integer i;
Standard_Real aMax = 0.;
for (i = 0; i <= 20; i ++) {
Standard_Real u = c1+(du*i);
gp_Pnt PP = c3d->Value(u);
Standard_Real dist = crc.Distance(PP);
if (dist > tol) return circ; // not done
if (dist > aMax)
aMax = dist;
}
Deviation = aMax;
// defining the parameters
Standard_Real PI2 = 2 * M_PI;
cf = ElCLib::Parameter (crc,c3d->Value (c1));
cf = ElCLib::InPeriod(cf, 0., PI2);
//first parameter should be closed to zero
if(Abs(cf) < Precision::PConfusion() || Abs(PI2-cf) < Precision::PConfusion())
cf = 0.;
Standard_Real cm = ElCLib::Parameter (crc,c3d->Value ((c1+c2)/2.));
cm = ElCLib::InPeriod(cm, cf, cf + PI2);
cl = ElCLib::Parameter (crc,c3d->Value (c2));
cl = ElCLib::InPeriod(cl, cm, cm + PI2);
circ = new Geom_Circle (crc);
return circ;
}
//=======================================================================
// Compute Ellipse
//=======================================================================
//=======================================================================
//function : IsArrayPntPlanar
//purpose :
//=======================================================================
static Standard_Boolean IsArrayPntPlanar(const Handle(TColgp_HArray1OfPnt)& HAP,
gp_Dir& Norm, const Standard_Real prec)
{
Standard_Integer size = HAP->Length();
if(size<3)
return Standard_False;
gp_Pnt P1 = HAP->Value(1);
gp_Pnt P2 = HAP->Value(2);
gp_Pnt P3 = HAP->Value(3);
Standard_Real dist1 = P1.Distance(P2);
Standard_Real dist2 = P1.Distance(P3);
if( dist1<prec || dist2<prec )
return Standard_False;
gp_Vec V1(P1,P2);
gp_Vec V2(P1,P3);
if(V1.IsParallel(V2,prec))
return Standard_False;
gp_Vec NV = V1.Crossed(V2);
Standard_Integer i;
for (i = 1; i <= 3; ++i)
{
if (Precision::IsInfinite(NV.Coord(i)))
return Standard_False;
}
if(NV.Magnitude() < gp::Resolution())
return Standard_False;
if(size>3) {
for(i=4; i<=size; i++) {
gp_Pnt PN = HAP->Value(i);
dist1 = P1.Distance(PN);
if (dist1 < prec || Precision::IsInfinite(dist1))
{
return Standard_False;
}
gp_Vec VN(P1,PN);
if(!NV.IsNormal(VN,prec))
return Standard_False;
}
}
Norm = NV;
return Standard_True;
}
//=======================================================================
//function : ConicdDefinition
//purpose :
//=======================================================================
static Standard_Boolean ConicDefinition
( const Standard_Real a, const Standard_Real b1, const Standard_Real c,
const Standard_Real d1, const Standard_Real e1, const Standard_Real f,
const Standard_Boolean IsParab, const Standard_Boolean IsEllip,
gp_Pnt& Center, gp_Dir& MainAxis, Standard_Real& Rmin, Standard_Real& Rmax )
{
Standard_Real Xcen = 0.,Ycen = 0., Xax = 0.,Yax = 0.;
Standard_Real b,d,e;
// conic : a*x2 + 2*b*x*y + c*y2 + 2*d*x + 2*e*y + f = 0.
//Equation (a,b,c,d,e,f);
b = b1/2.; d = d1/2.; e = e1/2.; // chgt de variable
Standard_Real eps = 1.E-08; // ?? comme ComputedForm
if (IsParab) {
}
else {
// -> Conique a centre, cas general
// On utilise les Determinants des matrices :
// | a b d |
// gdet (3x3) = | b c e | et pdet (2X2) = | a b |
// | d e f | | b c |
Standard_Real gdet = a*c*f + 2*b*d*e - c*d*d - a*e*e - b*b*f;
Standard_Real pdet = a*c - b*b;
Xcen = (b*e - c*d) / pdet;
Ycen = (b*d - a*e) / pdet;
Standard_Real term1 = a-c;
Standard_Real term2 = 2*b;
Standard_Real cos2t;
Standard_Real auxil;
if (Abs(term2) <= eps && Abs(term1) <= eps) {
cos2t = 1.;
auxil = 0.;
}
else {
if (Abs(term1) < eps)
{
return Standard_False;
}
Standard_Real t2d = term2/term1; //skl 21.11.2001
cos2t = 1./sqrt(1+t2d*t2d);
auxil = sqrt (term1*term1 + term2*term2);
}
Standard_Real cost = sqrt ( (1+cos2t)/2. );
Standard_Real sint = sqrt ( (1-cos2t)/2. );
Standard_Real aprim = (a+c+auxil)/2.;
Standard_Real cprim = (a+c-auxil)/2.;
if (Abs(aprim) < gp::Resolution() || Abs(cprim) < gp::Resolution())
return Standard_False;
term1 = -gdet/(aprim*pdet);
term2 = -gdet/(cprim*pdet);
if (IsEllip) {
Xax = cost;
Yax = sint;
Rmin = sqrt ( term1);
Rmax = sqrt ( term2);
if(Rmax<Rmin){
Rmax = sqrt ( term1);
Rmin = sqrt ( term2);
}
}
else if (term1 <= eps){
Xax = -sint;
Yax = cost;
Rmin = sqrt (-term1);
Rmax = sqrt (term2);
}
else {
Xax = cost;
Yax = sint;
Rmin = sqrt (-term2);
Rmax = sqrt (term1);
}
}
Center.SetCoord (Xcen,Ycen,0.);
MainAxis.SetCoord (Xax,Yax,0.);
return Standard_True;
}
//=======================================================================
//function : ComputeEllipse
//purpose :
//=======================================================================
Handle(Geom_Curve) GeomConvert_CurveToAnaCurve::ComputeEllipse(const Handle(Geom_Curve)& c3d,
const Standard_Real tol,
const Standard_Real c1, const Standard_Real c2,
Standard_Real& cf, Standard_Real& cl,
Standard_Real& Deviation)
{
if (c3d->IsKind (STANDARD_TYPE(Geom_Ellipse))) {
cf = c1;
cl = c2;
Deviation = 0.;
Handle(Geom_Ellipse) anElips = Handle(Geom_Ellipse)::DownCast(c3d);
return anElips;
}
Handle(Geom_Curve) res;
Standard_Real prec = Precision::PConfusion();
Standard_Real AF,BF,CF,DF,EF,Q1,Q2,Q3,c2n;
Standard_Integer i;
gp_Pnt PStart = c3d->Value(c1);
gp_Pnt PEnd = c3d->Value(c2);
const Standard_Boolean IsClos = PStart.Distance(PEnd) < prec;
if (IsClos)
{
c2n=c2-(c2-c1)/5;
}
else
c2n=c2;
//
gp_XYZ aBC;
Handle(TColgp_HArray1OfPnt) AP = new TColgp_HArray1OfPnt(1,5);
AP->SetValue(1,PStart);
aBC += PStart.XYZ();
Standard_Real dc=(c2n-c1)/4;
for (i = 1; i < 5; i++)
{
gp_Pnt aP = c3d->Value(c1 + dc*i);
AP->SetValue(i + 1, aP);
aBC += aP.XYZ();
}
aBC /= 5;
aBC *= -1;
gp_Vec aTrans(aBC);
for (i = 1; i <= 5; ++i)
{
AP->ChangeValue(i).Translate(aTrans);
}
gp_Dir ndir;
if(!IsArrayPntPlanar(AP,ndir,prec))
return res;
if (Abs(ndir.X()) < gp::Resolution() && Abs(ndir.Y()) < gp::Resolution()
&& Abs(ndir.Z()) < gp::Resolution())
return res;
gp_Ax3 AX(gp_Pnt(0,0,0),ndir);
gp_Trsf Tr;
Tr.SetTransformation(AX);
gp_Trsf Tr2 = Tr.Inverted();
math_Matrix Dt(1, 5, 1, 5);
math_Vector F(1, 5), Sl(1, 5);
Standard_Real XN,YN,ZN = 0.;
gp_Pnt PT,PP;
for(i=1; i<=5; i++) {
PT = AP->Value(i).Transformed(Tr);
PT.Coord(XN,YN,ZN);
Dt(i, 1) = XN*XN;
Dt(i, 2) = XN*YN;
Dt(i, 3) = YN*YN;
Dt(i, 4) = XN;
Dt(i, 5) = YN;
F(i) = -1.;
}
math_Gauss aSolver(Dt);
if (!aSolver.IsDone())
return res;
aSolver.Solve(F, Sl);
AF=Sl(1);
BF=Sl(2);
CF=Sl(3);
DF=Sl(4);
EF=Sl(5);
Q1=AF*CF+BF*EF*DF/4-CF*DF*DF/4-BF*BF/4-AF*EF*EF/4;
Q2=AF*CF-BF*BF/4;
Q3=AF+CF;
Standard_Real Rmax, Rmin;
gp_Pnt Center;
gp_Dir MainAxis;
Standard_Boolean IsParab = Standard_False, IsEllip = Standard_False;
if (Q2 > 0 && Q1*Q3 < 0) {
// ellipse
IsEllip = Standard_True;
if (ConicDefinition(AF, BF, CF, DF, EF, 1., IsParab, IsEllip,
Center, MainAxis, Rmin, Rmax)) {
// create ellipse
if (Rmax - Rmin < Precision::Confusion())
{
return res; //really it is circle, which must be recognized in other method
}
aTrans *= -1;
Center.SetZ(ZN);
gp_Pnt NewCenter = Center.Transformed(Tr2);
gp_Pnt Ptmp(Center.X() + MainAxis.X() * 10,
Center.Y() + MainAxis.Y() * 10,
Center.Z() + MainAxis.Z() * 10);
gp_Pnt NewPtmp = Ptmp.Transformed(Tr2);
gp_Dir NewMainAxis(NewPtmp.X() - NewCenter.X(),
NewPtmp.Y() - NewCenter.Y(),
NewPtmp.Z() - NewCenter.Z());
gp_Ax2 ax2(NewCenter, ndir, NewMainAxis);
gp_Elips anEllipse(ax2, Rmax, Rmin);
anEllipse.Translate(aTrans);
Handle(Geom_Ellipse) gell = new Geom_Ellipse(anEllipse);
// test for 20 points
Standard_Real param2 = 0;
dc = (c2 - c1) / 20;
for (i = 1; i <= 20; i++) {
PP = c3d->Value(c1 + i*dc);
Standard_Real aPar = ElCLib::Parameter(anEllipse, PP);
Standard_Real dist = gell->Value(aPar).Distance(PP);
if (dist > tol) return res; // not done
if (dist > param2)
param2 = dist;
}
Deviation = param2;
Standard_Real PI2 = 2 * M_PI;
cf = ElCLib::Parameter(anEllipse, c3d->Value(c1));
cf = ElCLib::InPeriod(cf, 0., PI2);
//first parameter should be closed to zero
if (Abs(cf) < Precision::PConfusion() || Abs(PI2 - cf) < Precision::PConfusion())
cf = 0.;
Standard_Real cm = ElCLib::Parameter(anEllipse, c3d->Value((c1 + c2) / 2.));
cm = ElCLib::InPeriod(cm, cf, cf + PI2);
cl = ElCLib::Parameter(anEllipse, c3d->Value(c2));
cl = ElCLib::InPeriod(cl, cm, cm + PI2);
res = gell;
}
}
/*
if (Q2 < 0 && Q1 != 0) {
// hyberbola
}
if (Q2 == 0 && Q1 != 0) {
// parabola
}
*/
return res;
}
//=======================================================================
//function : ComputeCurve
//purpose :
//=======================================================================
Handle(Geom_Curve) GeomConvert_CurveToAnaCurve::ComputeCurve(const Handle(Geom_Curve)& theC3d,
const Standard_Real tolerance,
const Standard_Real c1, const Standard_Real c2,
Standard_Real& cf, Standard_Real& cl,
Standard_Real& theGap,
const GeomConvert_ConvType theConvType, const GeomAbs_CurveType theTarget)
{
cf = c1; cl = c2;
Handle(Geom_Curve) c3d, newc3d[3];
Standard_Integer i, imin = -1;
c3d = theC3d;
if (c3d.IsNull()) return newc3d[imin];
gp_Pnt P1 = c3d->Value(c1);
gp_Pnt P2 = c3d->Value(c2);
gp_Pnt P3 = c3d->Value(c1 + (c2 - c1) / 2);
Standard_Real d[3] = { RealLast(), RealLast(), RealLast() };
Standard_Real fp[3], lp[3];
if (c3d->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) {
Handle(Geom_TrimmedCurve) aTc = Handle(Geom_TrimmedCurve)::DownCast(c3d);
c3d = aTc->BasisCurve();
}
if (theConvType == GeomConvert_Target)
{
theGap = RealLast();
if (theTarget == GeomAbs_Line)
{
newc3d[0] = ComputeLine(c3d, tolerance, c1, c2, fp[0], lp[0], theGap);
cf = fp[0];
cl = lp[0];
return newc3d[0];
}
if (theTarget == GeomAbs_Circle)
{
newc3d[1] = ComputeCircle(c3d, tolerance, c1, c2, fp[1], lp[1], theGap);
cf = fp[1];
cl = lp[1];
return newc3d[1];
}
if (theTarget == GeomAbs_Ellipse)
{
newc3d[2] = ComputeEllipse(c3d, tolerance, c1, c2, fp[2], lp[2], theGap);
cf = fp[2];
cl = lp[2];
return newc3d[2];
}
}
//
if (theConvType == GeomConvert_Simplest)
{
theGap = RealLast();
newc3d[0] = ComputeLine(c3d, tolerance, c1, c2, fp[0], lp[0], theGap);
if (!newc3d[0].IsNull())
{
cf = fp[0];
cl = lp[0];
return newc3d[0];
}
theGap = RealLast();
newc3d[1] = ComputeCircle(c3d, tolerance, c1, c2, fp[1], lp[1], theGap);
if (!newc3d[1].IsNull())
{
cf = fp[1];
cl = lp[1];
return newc3d[1];
}
theGap = RealLast();
newc3d[2] = ComputeEllipse(c3d, tolerance, c1, c2, fp[2], lp[2], theGap);
if (!newc3d[2].IsNull())
{
cf = fp[2];
cl = lp[2];
return newc3d[2];
}
// Conversion failed, returns null curve
return newc3d[0];
}
// theConvType == GeomConvert_MinGap
// recognition in case of small curve
imin = -1;
if((P1.Distance(P2) < 2*tolerance) && (P1.Distance(P3) < 2*tolerance)) {
newc3d[1] = ComputeCircle(c3d, tolerance, c1, c2, fp[1], lp[1], d[1]);
newc3d[0] = ComputeLine(c3d, tolerance, c1, c2, fp[0], lp[0], d[0]);
imin = 1;
if (newc3d[1].IsNull() || d[0] < d[1])
{
imin = 0;
}
}
else {
d[0] = RealLast();
newc3d[0] = ComputeLine (c3d,tolerance,c1,c2,fp[0],lp[0],d[0]);
Standard_Real tol = Min(tolerance, d[0]);
if (!Precision::IsInfinite(c1) && !Precision::IsInfinite(c2))
{
d[1] = RealLast();
newc3d[1] = ComputeCircle(c3d, tol, c1, c2, fp[1], lp[1], d[1]);
tol = Min(tol, d[1]);
d[2] = RealLast();
newc3d[2] = ComputeEllipse(c3d, tol, c1, c2, fp[2], lp[2], d[2]);
}
Standard_Real dd = RealLast();
for (i = 0; i < 3; ++i)
{
if (newc3d[i].IsNull()) continue;
if (d[i] < dd)
{
dd = d[i];
imin = i;
}
}
}
if (imin >= 0)
{
cf = fp[imin];
cl = lp[imin];
theGap = d[imin];
return newc3d[imin];
}
else
{
cf = c1;
cl = c2;
theGap = -1.;
return newc3d[0]; // must be null curve;
}
}

View File

@ -0,0 +1,133 @@
// Created: 2001-05-21
//
// Copyright (c) 2001-2013 OPEN CASCADE SAS
//
// This file is part of commercial software by OPEN CASCADE SAS,
// furnished in accordance with the terms and conditions of the contract
// and with the inclusion of this copyright notice.
// This file or any part thereof may not be provided or otherwise
// made available to any third party.
//
// No ownership title to the software is transferred hereby.
//
// OPEN CASCADE SAS makes no representation or warranties with respect to the
// performance of this software, and specifically disclaims any responsibility
// for any damages, special or consequential, connected with its use.
#ifndef _GeomConvert_CurveToAnaCurve_HeaderFile
#define _GeomConvert_CurveToAnaCurve_HeaderFile
#include <Standard.hxx>
#include <Standard_DefineAlloc.hxx>
#include <Standard_Handle.hxx>
#include <Standard_Boolean.hxx>
#include <Standard_Real.hxx>
#include <TColgp_Array1OfPnt.hxx>
#include <GeomConvert_ConvType.hxx>
#include <GeomAbs_CurveType.hxx>
class Geom_Curve;
class Geom_Line;
class gp_Lin;
class gp_Pnt;
class gp_Circ;
class GeomConvert_CurveToAnaCurve
{
public:
DEFINE_STANDARD_ALLOC
Standard_EXPORT GeomConvert_CurveToAnaCurve();
Standard_EXPORT GeomConvert_CurveToAnaCurve(const Handle(Geom_Curve)& C);
Standard_EXPORT void Init (const Handle(Geom_Curve)& C);
//! Converts me to analytical if possible with given
//! tolerance. The new first and last parameters are
//! returned to newF, newL
Standard_EXPORT Standard_Boolean ConvertToAnalytical (const Standard_Real theTol, Handle(Geom_Curve)& theResultCurve, const Standard_Real F, const Standard_Real L, Standard_Real& newF, Standard_Real& newL);
Standard_EXPORT static Handle(Geom_Curve) ComputeCurve (const Handle(Geom_Curve)& curve, const Standard_Real tolerance,
const Standard_Real c1, const Standard_Real c2, Standard_Real& cf, Standard_Real& cl,
Standard_Real& theGap, const GeomConvert_ConvType theCurvType = GeomConvert_MinGap, const GeomAbs_CurveType theTarget = GeomAbs_Line);
//! Tries to convert the given curve to circle with given
//! tolerance. Returns NULL curve if conversion is
//! not possible.
Standard_EXPORT static Handle(Geom_Curve) ComputeCircle (const Handle(Geom_Curve)& curve, const Standard_Real tolerance, const Standard_Real c1, const Standard_Real c2, Standard_Real& cf, Standard_Real& cl, Standard_Real& Deviation);
//! Tries to convert the given curve to ellipse with given
//! tolerance. Returns NULL curve if conversion is
//! not possible.
Standard_EXPORT static Handle(Geom_Curve) ComputeEllipse (const Handle(Geom_Curve)& curve, const Standard_Real tolerance, const Standard_Real c1, const Standard_Real c2, Standard_Real& cf, Standard_Real& cl, Standard_Real& Deviation);
//! Tries to convert the given curve to line with given
//! tolerance. Returns NULL curve if conversion is
//! not possible.
Standard_EXPORT static Handle(Geom_Line) ComputeLine (const Handle(Geom_Curve)& curve, const Standard_Real tolerance, const Standard_Real c1, const Standard_Real c2, Standard_Real& cf, Standard_Real& cl, Standard_Real& Deviation);
//! Returns true if the set of points is linear with given
//! tolerance
Standard_EXPORT static Standard_Boolean IsLinear (const TColgp_Array1OfPnt& aPoints, const Standard_Real tolerance, Standard_Real& Deviation);
//! Creates line on two points.
//! Resulting parameters returned
Standard_EXPORT static gp_Lin GetLine(const gp_Pnt& P1, const gp_Pnt& P2, Standard_Real& cf, Standard_Real& cl);
//! Creates circle on points. Returns true if OK.
Standard_EXPORT static Standard_Boolean GetCircle(gp_Circ& Circ, const gp_Pnt& P0, const gp_Pnt& P1, const gp_Pnt& P2);
//! Returns maximal deviation of converted surface from the original
//! one computed by last call to ConvertToAnalytical
Standard_Real Gap() const
{
return myGap;
}
//! Returns conversion type
GeomConvert_ConvType GetConvType() const
{
return myConvType;
}
//! Sets type of convertion
void SetConvType(const GeomConvert_ConvType theConvType)
{
myConvType = theConvType;
}
//! Returns target curve type
GeomAbs_CurveType GetTarget() const
{
return myTarget;
}
//! Sets target curve type
void SetTarget(const GeomAbs_CurveType theTarget)
{
myTarget = theTarget;
}
protected:
private:
Handle(Geom_Curve) myCurve;
Standard_Real myGap;
GeomConvert_ConvType myConvType;
GeomAbs_CurveType myTarget;
};
#endif // _GeomConvert_CurveToAnaCurve_HeaderFile

View File

@ -0,0 +1,764 @@
// Created: 1998-06-03
//
// Copyright (c) 1999-2013 OPEN CASCADE SAS
//
// This file is part of commercial software by OPEN CASCADE SAS,
// furnished in accordance with the terms and conditions of the contract
// and with the inclusion of this copyright notice.
// This file or any part thereof may not be provided or otherwise
// made available to any third party.
//
// No ownership title to the software is transferred hereby.
//
// OPEN CASCADE SAS makes no representation or warranties with respect to the
// performance of this software, and specifically disclaims any responsibility
// for any damages, special or consequential, connected with its use.
//abv 06.01.99 fix of misprint
//:p6 abv 26.02.99: make ConvertToPeriodic() return Null if nothing done
#include <BRepTopAdaptor_TopolTool.hxx>
#include <ElSLib.hxx>
#include <Geom_RectangularTrimmedSurface.hxx>
#include <Geom_BezierSurface.hxx>
#include <Geom_BSplineSurface.hxx>
#include <Geom_Circle.hxx>
#include <Geom_ConicalSurface.hxx>
#include <Geom_Curve.hxx>
#include <Geom_CylindricalSurface.hxx>
#include <Geom_Line.hxx>
#include <Geom_Plane.hxx>
#include <Geom_SphericalSurface.hxx>
#include <Geom_Surface.hxx>
#include <Geom_SurfaceOfRevolution.hxx>
#include <Geom_ToroidalSurface.hxx>
#include <Geom_TrimmedCurve.hxx>
#include <GeomAdaptor_Surface.hxx>
#include <GeomAdaptor_Surface.hxx>
#include <GeomLib_IsPlanarSurface.hxx>
#include <gp_Ax3.hxx>
#include <gp_Circ.hxx>
#include <gp_Dir.hxx>
#include <gp_Pln.hxx>
#include <gp_Vec.hxx>
#include <IntAna_QuadQuadGeo.hxx>
#include <GeomConvert_CurveToAnaCurve.hxx>
#include <GeomConvert_SurfToAnaSurf.hxx>
#include <TColgp_Array1OfPnt.hxx>
#include <TColStd_Array1OfReal.hxx>
#include <Extrema_ExtElC.hxx>
//static method for checking surface of revolution
//To avoid two-parts cone-like surface
static void CheckVTrimForRevSurf(const Handle(Geom_SurfaceOfRevolution)& aRevSurf,
Standard_Real& V1, Standard_Real& V2)
{
const Handle(Geom_Curve)& aBC = aRevSurf->BasisCurve();
Handle(Geom_Line) aLine = Handle(Geom_Line)::DownCast(aBC);
if (aLine.IsNull())
return;
const gp_Ax1& anAxis = aRevSurf->Axis();
gp_Lin anALin(anAxis);
Extrema_ExtElC anExtLL(aLine->Lin(), anALin, Precision::Angular());
if (!anExtLL.IsDone() || anExtLL.IsParallel())
return;
Standard_Integer aNbExt = anExtLL.NbExt();
if (aNbExt == 0)
return;
Standard_Integer i;
Standard_Integer imin = 0;
for (i = 1; i <= aNbExt; ++i)
{
if (anExtLL.SquareDistance(i) < Precision::SquareConfusion())
{
imin = i;
break;
}
}
if (imin == 0)
return;
Extrema_POnCurv aP1, aP2;
anExtLL.Points(imin, aP1, aP2);
Standard_Real aVExt = aP1.Parameter();
if (aVExt <= V1 || aVExt >= V2)
return;
if (aVExt - V1 > V2 - aVExt)
{
V2 = aVExt;
}
else
{
V1 = aVExt;
}
}
// static method to try create toroidal surface.
// In case <isTryUMajor> = Standard_True try to use V isoline radius as minor radaius.
static Handle(Geom_Surface) TryTorusSphere(const Handle(Geom_Surface)& theSurf,
const Handle(Geom_Circle)& circle,
const Handle(Geom_Circle)& otherCircle,
const Standard_Real Param1,
const Standard_Real Param2,
const Standard_Real aParam1ToCrv,
const Standard_Real aParam2ToCrv,
const Standard_Real toler,
const Standard_Boolean isTryUMajor)
{
Handle(Geom_Surface) newSurface;
Standard_Real cf, cl;
Handle(Geom_Curve) IsoCrv1;
Handle(Geom_Curve) IsoCrv2;
Standard_Real aGap1, aGap2;
// initial radius
Standard_Real R = circle->Circ().Radius();
// iso lines
if (isTryUMajor)
{
IsoCrv1 = theSurf->VIso(Param1 + ((Param2 - Param1) / 3.));
IsoCrv2 = theSurf->VIso(Param1 + ((Param2 - Param1)*2. / 3));
}
else
{
IsoCrv1 = theSurf->UIso(Param1 + ((Param2 - Param1) / 3.));
IsoCrv2 = theSurf->UIso(Param1 + ((Param2 - Param1)*2. / 3));
}
Handle(Geom_Curve) Crv1 = GeomConvert_CurveToAnaCurve::ComputeCurve(IsoCrv1, toler, aParam1ToCrv, aParam2ToCrv, cf, cl,
aGap1);
Handle(Geom_Curve) Crv2 = GeomConvert_CurveToAnaCurve::ComputeCurve(IsoCrv2, toler, aParam1ToCrv, aParam2ToCrv, cf, cl,
aGap2);
if (Crv1.IsNull() || Crv2.IsNull() ||
!Crv1->IsKind(STANDARD_TYPE(Geom_Circle)) ||
!Crv2->IsKind(STANDARD_TYPE(Geom_Circle)))
return newSurface;
Handle(Geom_Circle) aCircle1 = Handle(Geom_Circle)::DownCast(Crv1);
Handle(Geom_Circle) aCircle2 = Handle(Geom_Circle)::DownCast(Crv2);
Standard_Real R1 = aCircle1->Circ().Radius();
Standard_Real R2 = aCircle2->Circ().Radius();
// check radiuses
if ((Abs(R - R1) > toler) || (Abs(R - R2) > toler))
return newSurface;
// get centers of the major radius
gp_Pnt aPnt1, aPnt2, aPnt3;
aPnt1 = circle->Circ().Location();
aPnt2 = aCircle1->Circ().Location();
aPnt3 = aCircle2->Circ().Location();
//Standard_Real eps = 1.e-09; // angular resolution
Standard_Real d0 = aPnt1.Distance(aPnt2); Standard_Real d1 = aPnt1.Distance(aPnt3);
gp_Circ circ;
if (d0 < toler || d1 < toler)
{
// compute sphere
gp_Dir MainDir = otherCircle->Circ().Axis().Direction();
gp_Ax3 Axes(circle->Circ().Location(), MainDir);
Handle(Geom_SphericalSurface) anObject =
new Geom_SphericalSurface(Axes, R);
if (!anObject.IsNull())
newSurface = anObject;
return newSurface;
}
if (!GeomConvert_CurveToAnaCurve::GetCircle(circ, aPnt1, aPnt2, aPnt3) /*, d0, d1, eps)*/)
return newSurface;
Standard_Real aMajorR = circ.Radius();
gp_Pnt aCenter = circ.Location();
gp_Dir aDir((aPnt1.XYZ() - aCenter.XYZ()) ^ (aPnt3.XYZ() - aCenter.XYZ()));
gp_Ax3 anAx3(aCenter, aDir);
newSurface = new Geom_ToroidalSurface(anAx3, aMajorR, R);
return newSurface;
}
static Standard_Real ComputeGap(const Handle(Geom_Surface)& theSurf,
const Standard_Real theU1, const Standard_Real theU2, const Standard_Real theV1, const Standard_Real theV2,
const Handle(Geom_Surface) theNewSurf, const Standard_Real theTol = RealLast())
{
GeomAdaptor_Surface aGAS(theNewSurf);
GeomAbs_SurfaceType aSType = aGAS.GetType();
gp_Pln aPln;
gp_Cylinder aCyl;
gp_Cone aCon;
gp_Sphere aSphere;
gp_Torus aTor;
switch (aSType)
{
case GeomAbs_Plane:
aPln = aGAS.Plane();
break;
case GeomAbs_Cylinder:
aCyl = aGAS.Cylinder();
break;
case GeomAbs_Cone:
aCon = aGAS.Cone();
break;
case GeomAbs_Sphere:
aSphere = aGAS.Sphere();
break;
case GeomAbs_Torus:
aTor = aGAS.Torus();
break;
default:
return Precision::Infinite();
break;
}
Standard_Real aGap = 0.;
Standard_Boolean onSurface = Standard_True;
Standard_Real S, T;
gp_Pnt P3d, P3d2;
const Standard_Integer NP = 21;
Standard_Real DU, DV;
Standard_Integer j, i;
DU = (theU2 - theU1) / (NP - 1);
DV = (theV2 - theV1) / (NP - 1);
Standard_Real DU2 = DU / 2., DV2 = DV / 2.;
for (j = 1; (j < NP) && onSurface; j++) {
Standard_Real V = theV1 + DV*(j - 1) + DV2;
for (i = 1; i <= NP; i++) {
Standard_Real U = theU1 + DU*(i - 1) + DU2;
theSurf->D0(U, V, P3d);
switch (aSType) {
case GeomAbs_Plane:
{
ElSLib::Parameters(aPln, P3d, S, T);
P3d2 = ElSLib::Value(S, T, aPln);
break;
}
case GeomAbs_Cylinder:
{
ElSLib::Parameters(aCyl, P3d, S, T);
P3d2 = ElSLib::Value(S, T, aCyl);
break;
}
case GeomAbs_Cone:
{
ElSLib::Parameters(aCon, P3d, S, T);
P3d2 = ElSLib::Value(S, T, aCon);
break;
}
case GeomAbs_Sphere:
{
ElSLib::Parameters(aSphere, P3d, S, T);
P3d2 = ElSLib::Value(S, T, aSphere);
break;
}
case GeomAbs_Torus:
{
ElSLib::Parameters(aTor, P3d, S, T);
P3d2 = ElSLib::Value(S, T, aTor);
break;
}
default:
S = 0.; T = 0.;
theNewSurf->D0(S, T, P3d2);
break;
}
Standard_Real dis = P3d.Distance(P3d2);
if (dis > aGap) aGap = dis;
if (aGap > theTol) {
onSurface = Standard_False;
break;
}
}
}
return aGap;
}
//=======================================================================
//function : GeomConvert_SurfToAnaSurf
//purpose :
//=======================================================================
GeomConvert_SurfToAnaSurf::GeomConvert_SurfToAnaSurf() :
myGap (-1.),
myConvType (GeomConvert_Simplest),
myTarget (GeomAbs_Plane)
{
}
//=======================================================================
//function : GeomConvert_SurfToAnaSurf
//purpose :
//=======================================================================
GeomConvert_SurfToAnaSurf::GeomConvert_SurfToAnaSurf (const Handle(Geom_Surface)& S) :
myGap(-1.),
myConvType(GeomConvert_Simplest),
myTarget(GeomAbs_Plane)
{
Init ( S );
}
//=======================================================================
//function : Init
//purpose :
//=======================================================================
void GeomConvert_SurfToAnaSurf::Init (const Handle(Geom_Surface)& S)
{
mySurf = S;
}
//=======================================================================
//function : ConvertToAnalytical
//purpose :
//=======================================================================
Handle(Geom_Surface) GeomConvert_SurfToAnaSurf::ConvertToAnalytical (const Standard_Real InitialToler)
{
Standard_Real U1, U2, V1, V2;
mySurf->Bounds(U1, U2, V1, V2);
if(Precision::IsInfinite(U1) && Precision::IsInfinite(U2) ) {
U1 = -1.;
U2 = 1.;
}
if(Precision::IsInfinite(V1) && Precision::IsInfinite(V2) ) {
V1 = -1.;
V2 = 1.;
Handle(Geom_SurfaceOfRevolution) aRevSurf = Handle(Geom_SurfaceOfRevolution)::DownCast(mySurf);
if (!aRevSurf.IsNull())
{
CheckVTrimForRevSurf(aRevSurf, V1, V2);
}
}
return ConvertToAnalytical(InitialToler, U1, U2, V1, V2);
}
//=======================================================================
//function : ConvertToAnalytical
//purpose :
//=======================================================================
Handle(Geom_Surface) GeomConvert_SurfToAnaSurf::ConvertToAnalytical(const Standard_Real InitialToler,
const Standard_Real Umin, const Standard_Real Umax,
const Standard_Real Vmin, const Standard_Real Vmax)
{
//
GeomAdaptor_Surface aGAS(mySurf);
GeomAbs_SurfaceType aSType = aGAS.GetType();
switch (aSType)
{
case GeomAbs_Plane:
{
myGap = 0.;
return new Geom_Plane(aGAS.Plane());
}
case GeomAbs_Cylinder:
{
myGap = 0.;
return new Geom_CylindricalSurface(aGAS.Cylinder());
}
case GeomAbs_Cone:
{
myGap = 0.;
return new Geom_ConicalSurface(aGAS.Cone());
}
case GeomAbs_Sphere:
{
myGap = 0.;
return new Geom_SphericalSurface(aGAS.Sphere());
}
case GeomAbs_Torus:
{
myGap = 0.;
return new Geom_ToroidalSurface(aGAS.Torus());
}
default:
break;
}
//
Standard_Real toler = InitialToler;
Handle(Geom_Surface) newSurf[5];
Standard_Real dd[5] = { -1., -1., -1., -1., -1 };
//Check boundaries
Standard_Real U1, U2, V1, V2;
mySurf->Bounds(U1, U2, V1, V2);
Standard_Boolean aDoSegment = Standard_False;
Standard_Real aTolBnd = Precision::PConfusion();
Standard_Integer isurf = 0;
if (Umin < U1 || Umax > U2 || Vmin < V1 || Vmax > V2)
{
return newSurf[isurf];
}
else
{
if (Umin - U1 > aTolBnd)
{
U1 = Umin;
aDoSegment = Standard_True;
}
if (U2 - Umax > aTolBnd)
{
U2 = Umax;
aDoSegment = Standard_True;
}
if (Vmin - V1 > aTolBnd)
{
V1 = Vmin;
aDoSegment = Standard_True;
}
if (V2 - Vmax > aTolBnd)
{
V2 = Vmax;
aDoSegment = Standard_True;
}
}
Standard_Boolean IsBz = aSType == GeomAbs_BezierSurface;
Standard_Boolean IsBs = aSType == GeomAbs_BSplineSurface;
Handle(Geom_Surface) aTempS = mySurf;
if (IsBs)
{
Handle(Geom_BSplineSurface) aBs = Handle(Geom_BSplineSurface)::DownCast(mySurf->Copy());
if (aDoSegment)
{
aBs->Segment(U1, U2, V1, V2);
}
aTempS = aBs;
}
else if (IsBz)
{
Handle(Geom_BezierSurface) aBz = Handle(Geom_BezierSurface)::DownCast(mySurf->Copy());
if (aDoSegment)
{
aBz->Segment(U1, U2, V1, V2);
}
aTempS = aBz;
}
// check the planarity first
if (!IsBs && !IsBz)
{
aTempS = new Geom_RectangularTrimmedSurface(aTempS, U1, U2, V1, V2);
}
isurf = 0; // set plane
GeomLib_IsPlanarSurface GeomIsPlanar(aTempS, toler);
if (GeomIsPlanar.IsPlanar()) {
gp_Pln newPln = GeomIsPlanar.Plan();
newSurf[isurf] = new Geom_Plane(newPln);
dd[isurf] = ComputeGap(aTempS, U1, U2, V1, V2, newSurf[isurf]);
if ( myConvType == GeomConvert_Simplest ||
(myConvType == GeomConvert_Target && myTarget == GeomAbs_Plane))
{
myGap = dd[isurf];
return newSurf[isurf];
}
}
else
{
if (myConvType == GeomConvert_Target && myTarget == GeomAbs_Plane)
{
myGap = dd[isurf];
return newSurf[isurf];
}
}
Standard_Real diagonal = mySurf->Value(U1, V1).Distance(mySurf->Value((U1 + U2), (V1 + V2) / 2));
Standard_Real twist = 1000;
if (toler > diagonal / twist) toler = diagonal / twist;
isurf = 1; // set cylinder
Standard_Boolean aCylinderConus = Standard_False;
Standard_Boolean aToroidSphere = Standard_False;
//convert middle uiso and viso to canonical representation
Standard_Real VMid = 0.5*(V1 + V2);
Standard_Real UMid = 0.5*(U1 + U2);
Handle(Geom_Surface) TrSurf = aTempS;
if(!aDoSegment)
TrSurf = new Geom_RectangularTrimmedSurface(aTempS, U1, U2, V1, V2);
Handle(Geom_Curve) UIso = TrSurf->UIso(UMid);
Handle(Geom_Curve) VIso = TrSurf->VIso(VMid);
Standard_Real cuf, cul, cvf, cvl, aGap1, aGap2;
Handle(Geom_Curve) umidiso = GeomConvert_CurveToAnaCurve::ComputeCurve(UIso, toler, V1, V2, cuf, cul, aGap1);
Handle(Geom_Curve) vmidiso = GeomConvert_CurveToAnaCurve::ComputeCurve(VIso, toler, U1, U2, cvf, cvl, aGap2);
if (umidiso.IsNull() || vmidiso.IsNull()) {
return newSurf[isurf];
}
//
Standard_Boolean VCase = Standard_False;
if (umidiso->IsKind(STANDARD_TYPE(Geom_Circle)) && vmidiso->IsKind(STANDARD_TYPE(Geom_Circle)))
{
aToroidSphere = Standard_True;
if (myConvType == GeomConvert_Target && (myTarget == GeomAbs_Cylinder || myTarget == GeomAbs_Cone))
{
isurf = 1;
myGap = dd[isurf];
return newSurf[isurf];
}
isurf = 3; // set sphere
}
else if (umidiso->IsKind(STANDARD_TYPE(Geom_Line)) && vmidiso->IsKind(STANDARD_TYPE(Geom_Circle))) {
aCylinderConus = Standard_True; VCase = Standard_True;
if (myConvType == GeomConvert_Target && (myTarget == GeomAbs_Sphere || myTarget == GeomAbs_Torus))
{
isurf = 3;
myGap = dd[isurf];
return newSurf[isurf];
}
isurf = 1;// set cylinder
}
else if (umidiso->IsKind(STANDARD_TYPE(Geom_Circle)) && vmidiso->IsKind(STANDARD_TYPE(Geom_Line)))
{
aCylinderConus = Standard_True;
if (myConvType == GeomConvert_Target && (myTarget == GeomAbs_Sphere || myTarget == GeomAbs_Torus))
{
isurf = 3;
myGap = dd[isurf];
return newSurf[isurf];
}
isurf = 1;// set cylinder
}
Standard_Real cl = 0.0;
//case of torus-sphere
if (aToroidSphere) {
isurf = 3; // Set spherical surface
Handle(Geom_Circle) Ucircle = Handle(Geom_Circle)::DownCast(umidiso);
Handle(Geom_Circle) Vcircle = Handle(Geom_Circle)::DownCast(vmidiso);
// torus
// try when V isolines is with same radius
Handle(Geom_Surface) anObject =
TryTorusSphere(mySurf, Vcircle, Ucircle, V1, V2, U1, U2, toler, Standard_True);
if (anObject.IsNull()) // try when U isolines is with same radius
anObject = TryTorusSphere(mySurf, Ucircle, Vcircle, U1, U2, V1, V2, toler, Standard_False);
if (!anObject.IsNull())
{
if (anObject->IsKind(STANDARD_TYPE(Geom_ToroidalSurface)))
{
isurf = 4; // set torus
}
newSurf[isurf] = anObject;
}
else
{
myGap = dd[isurf];
}
}
//case of cone - cylinder
else if (aCylinderConus) {
Standard_Real param1, param2, cf1, cf2;
Handle(Geom_Curve) firstiso, lastiso;
Handle(Geom_Circle) firstisocirc, lastisocirc, midisocirc;
gp_Dir isoline;
if (VCase) {
param1 = U1; param2 = U2;
firstiso = TrSurf->VIso(V1);
lastiso = TrSurf->VIso(V2);
midisocirc = Handle(Geom_Circle)::DownCast(vmidiso);
isoline = Handle(Geom_Line)::DownCast(umidiso)->Lin().Direction();
}
else {
param1 = V1; param2 = V2;
firstiso = TrSurf->UIso(U1);
lastiso = TrSurf->UIso(U2);
midisocirc = Handle(Geom_Circle)::DownCast(umidiso);
isoline = Handle(Geom_Line)::DownCast(vmidiso)->Lin().Direction();
}
firstisocirc = Handle(Geom_Circle)::DownCast(GeomConvert_CurveToAnaCurve::ComputeCurve(firstiso, toler, param1, param2, cf1, cl, aGap1));
lastisocirc = Handle(Geom_Circle)::DownCast(GeomConvert_CurveToAnaCurve::ComputeCurve(lastiso, toler, param1, param2, cf2, cl, aGap2));
if (!firstisocirc.IsNull() || !lastisocirc.IsNull()) {
Standard_Real R1, R2, R3;
gp_Pnt P1, P2, P3;
if (!firstisocirc.IsNull()) {
R1 = firstisocirc->Circ().Radius();
P1 = firstisocirc->Circ().Location();
}
else {
R1 = 0;
P1 = firstiso->Value((firstiso->LastParameter() - firstiso->FirstParameter()) / 2);
}
R2 = midisocirc->Circ().Radius();
P2 = midisocirc->Circ().Location();
if (!lastisocirc.IsNull()) {
R3 = lastisocirc->Circ().Radius();
P3 = lastisocirc->Circ().Location();
}
else {
R3 = 0;
P3 = lastiso->Value((lastiso->LastParameter() - lastiso->FirstParameter()) / 2);
}
//cylinder
if (((Abs(R2 - R1)) < toler) && ((Abs(R3 - R1)) < toler) &&
((Abs(R3 - R2)) < toler)) {
isurf = 1;
gp_Ax3 Axes(P1, gp_Dir(gp_Vec(P1, P3)));
Handle(Geom_CylindricalSurface) anObject =
new Geom_CylindricalSurface(Axes, R1);
if (myConvType == GeomConvert_Target && myTarget != GeomAbs_Cylinder)
{
return newSurf[isurf];
}
newSurf[isurf] = anObject;
}
//cone
else if ((((Abs(R1)) > (Abs(R2))) && ((Abs(R2)) > (Abs(R3)))) ||
(((Abs(R3)) > (Abs(R2))) && ((Abs(R2)) > (Abs(R1))))) {
Standard_Real radius;
gp_Ax3 Axes;
Standard_Real semiangle =
gp_Vec(isoline).Angle(gp_Vec(P3, P1));
if (semiangle>M_PI / 2) semiangle = M_PI - semiangle;
if (R1 > R3) {
radius = R3;
Axes = gp_Ax3(P3, gp_Dir(gp_Vec(P3, P1)));
}
else {
radius = R1;
Axes = gp_Ax3(P1, gp_Dir(gp_Vec(P1, P3)));
}
Handle(Geom_ConicalSurface) anObject =
new Geom_ConicalSurface(Axes, semiangle, radius);
isurf = 2;
if (myConvType == GeomConvert_Target && myTarget != GeomAbs_Cone)
{
return newSurf[isurf];
}
newSurf[isurf] = anObject;
}
}
else
{
myGap = dd[isurf];
}
}
//
//---------------------------------------------------------------------
// verification
//---------------------------------------------------------------------
GeomAbs_SurfaceType aSTypes[5] = { GeomAbs_Plane, GeomAbs_Cylinder,
GeomAbs_Cone, GeomAbs_Sphere, GeomAbs_Torus };
Standard_Integer imin = -1;
Standard_Real aDmin = RealLast();
for (isurf = 0; isurf < 5; ++isurf)
{
if (newSurf[isurf].IsNull())
continue;
dd[isurf] = ComputeGap(TrSurf, U1, U2, V1, V2, newSurf[isurf], toler);
if (dd[isurf] <= toler)
{
if (myConvType == GeomConvert_Simplest || (myConvType == GeomConvert_Target && myTarget == aSTypes[isurf]))
{
myGap = dd[isurf];
return newSurf[isurf];
}
else if (myConvType == GeomConvert_MinGap)
{
if (dd[isurf] < aDmin)
{
aDmin = dd[isurf];
imin = isurf;
}
}
}
}
//
if (imin >= 0)
{
myGap = dd[imin];
return newSurf[imin];
}
return newSurf[0];
}
//=======================================================================
//function : IsSame
//purpose :
//=======================================================================
Standard_Boolean GeomConvert_SurfToAnaSurf::IsSame(const Handle(Geom_Surface)& S1,
const Handle(Geom_Surface)& S2,
const Standard_Real tol)
{
// only elementary surfaces are processed
if(!S1->IsKind(STANDARD_TYPE(Geom_ElementarySurface)) ||
!S2->IsKind(STANDARD_TYPE(Geom_ElementarySurface)))
return Standard_False;
Handle(GeomAdaptor_Surface) anAdaptor1 = new GeomAdaptor_Surface(S1);
Handle(GeomAdaptor_Surface) anAdaptor2 = new GeomAdaptor_Surface(S2);
GeomAbs_SurfaceType aST1 = anAdaptor1->GetType();
GeomAbs_SurfaceType aST2 = anAdaptor2->GetType();
if (aST1 != aST2)
{
return Standard_False;
}
IntAna_QuadQuadGeo interii;
if (aST1 == GeomAbs_Plane)
{
interii.Perform(anAdaptor1->Plane(), anAdaptor2->Plane(), tol, tol);
}
else if (aST1 == GeomAbs_Cylinder)
{
interii.Perform(anAdaptor1->Cylinder(), anAdaptor2->Cylinder(), tol);
}
else if (aST1 == GeomAbs_Cone)
{
interii.Perform(anAdaptor1->Cone(), anAdaptor2->Cone(), tol);
}
else if (aST1 == GeomAbs_Sphere)
{
interii.Perform(anAdaptor1->Sphere(), anAdaptor2->Sphere(), tol);
}
else if (aST1 == GeomAbs_Torus)
{
interii.Perform(anAdaptor1->Torus(), anAdaptor2->Torus(), tol);
}
if (!interii.IsDone())
return Standard_False;
IntAna_ResultType aTypeRes = interii.TypeInter();
return aTypeRes == IntAna_Same;
}
//=======================================================================
//function : IsCanonical
//purpose :
//=======================================================================
Standard_Boolean GeomConvert_SurfToAnaSurf::IsCanonical(const Handle(Geom_Surface)& S)
{
if(S.IsNull())
return Standard_False;
if ( S->IsKind(STANDARD_TYPE(Geom_Plane))
|| S->IsKind(STANDARD_TYPE(Geom_CylindricalSurface))
|| S->IsKind(STANDARD_TYPE(Geom_ConicalSurface))
|| S->IsKind(STANDARD_TYPE(Geom_SphericalSurface))
|| S->IsKind(STANDARD_TYPE(Geom_ToroidalSurface)))
return Standard_True;
return Standard_False;
}

View File

@ -0,0 +1,91 @@
// Created: 1998-06-03
//
// Copyright (c) 1999-2013 OPEN CASCADE SAS
//
// This file is part of commercial software by OPEN CASCADE SAS,
// furnished in accordance with the terms and conditions of the contract
// and with the inclusion of this copyright notice.
// This file or any part thereof may not be provided or otherwise
// made available to any third party.
//
// No ownership title to the software is transferred hereby.
//
// OPEN CASCADE SAS makes no representation or warranties with respect to the
// performance of this software, and specifically disclaims any responsibility
// for any damages, special or consequential, connected with its use.
#ifndef _GeomConvert_SurfToAnaSurf_HeaderFile
#define _GeomConvert_SurfToAnaSurf_HeaderFile
#include <Standard.hxx>
#include <Standard_DefineAlloc.hxx>
#include <Standard_Handle.hxx>
#include <Standard_Real.hxx>
#include <Standard_Boolean.hxx>
#include <GeomConvert_ConvType.hxx>
#include <GeomAbs_SurfaceType.hxx>
class Geom_Surface;
//! Converts a surface to the analitical form with given
//! precision. Conversion is done only the surface is bspline
//! of bezier and this can be approximed by some analytical
//! surface with that precision.
class GeomConvert_SurfToAnaSurf
{
public:
DEFINE_STANDARD_ALLOC
Standard_EXPORT GeomConvert_SurfToAnaSurf();
Standard_EXPORT GeomConvert_SurfToAnaSurf(const Handle(Geom_Surface)& S);
Standard_EXPORT void Init (const Handle(Geom_Surface)& S);
void SetConvType(const GeomConvert_ConvType theConvType = GeomConvert_Simplest)
{
myConvType = theConvType;
}
void SetTarget(const GeomAbs_SurfaceType theSurfType = GeomAbs_Plane)
{
myTarget = theSurfType;
}
//! Returns maximal deviation of converted surface from the original
//! one computed by last call to ConvertToAnalytical
Standard_Real Gap() const
{
return myGap;
}
//! Tries to convert the Surface to an Analytic form
//! Returns the result
//! In case of failure, returns a Null Handle
//!
Standard_EXPORT Handle(Geom_Surface) ConvertToAnalytical (const Standard_Real InitialToler);
Standard_EXPORT Handle(Geom_Surface) ConvertToAnalytical (const Standard_Real InitialToler,
const Standard_Real Umin, const Standard_Real Umax,
const Standard_Real Vmin, const Standard_Real Vmax);
//! Returns true if surfaces is same with the given tolerance
Standard_EXPORT static Standard_Boolean IsSame (const Handle(Geom_Surface)& S1, const Handle(Geom_Surface)& S2, const Standard_Real tol);
//! Returns true, if surface is canonical
Standard_EXPORT static Standard_Boolean IsCanonical (const Handle(Geom_Surface)& S);
protected:
private:
Handle(Geom_Surface) mySurf;
Standard_Real myGap;
GeomConvert_ConvType myConvType;
GeomAbs_SurfaceType myTarget;
};
#endif // _GeomConvert_SurfToAnaSurf_HeaderFile

View File

@ -59,7 +59,9 @@
#include <Geom2dConvert.hxx>
#include <Geom2dConvert_BSplineCurveToBezierCurve.hxx>
#include <GeomLProp_SLProps.hxx>
#include <GeomConvert_SurfToAnaSurf.hxx>
#include <GeomConvert_CurveToAnaCurve.hxx>
#include <GeomConvert_ConvType.hxx>
#include <DrawTrSurf_BezierSurface.hxx>
#include <DrawTrSurf_BSplineSurface.hxx>
@ -522,6 +524,111 @@ static Standard_Integer converting(Draw_Interpretor& , Standard_Integer n, const
return 0;
}
//=======================================================================
//function : converting to canonical
//purpose :
//=======================================================================
static Standard_Integer tocanon(Draw_Interpretor& di, Standard_Integer n, const char ** a)
{
if (n < 3) return 1;
GeomConvert_ConvType aConvType = GeomConvert_Simplest;
GeomAbs_CurveType aCurv = GeomAbs_Line;
GeomAbs_SurfaceType aSurf = GeomAbs_Plane;
if (n > 4)
{
if (strcmp(a[4], "sim") == 0) {
aConvType = GeomConvert_Simplest;
}
else if (strcmp(a[4], "gap") == 0) {
aConvType = GeomConvert_MinGap;
}
else if (strcmp(a[4], "lin") == 0) {
aConvType = GeomConvert_Target;
aCurv = GeomAbs_Line;
}
else if (strcmp(a[4], "cir") == 0) {
aConvType = GeomConvert_Target;
aCurv = GeomAbs_Circle;
}
else if (strcmp(a[4], "ell") == 0) {
aConvType = GeomConvert_Target;
aCurv = GeomAbs_Ellipse;
}
else if (strcmp(a[4], "pln") == 0) {
aConvType = GeomConvert_Target;
aSurf = GeomAbs_Plane;
}
else if (strcmp(a[4], "cyl") == 0) {
aConvType = GeomConvert_Target;
aSurf = GeomAbs_Cylinder;
}
else if (strcmp(a[4], "con") == 0) {
aConvType = GeomConvert_Target;
aSurf = GeomAbs_Cone;
}
else if (strcmp(a[4], "sph") == 0) {
aConvType = GeomConvert_Target;
aSurf = GeomAbs_Sphere;
}
else if (strcmp(a[4], "tor") == 0) {
aConvType = GeomConvert_Target;
aSurf = GeomAbs_Torus;
}
}
Standard_Real tol = Precision::Confusion();
if (n > 3)
{
tol = Draw::Atof(a[3]);
}
Handle(Geom_Curve) GC = DrawTrSurf::GetCurve(a[2]);
if (GC.IsNull()) {
Handle(Geom_Surface) GS = DrawTrSurf::GetSurface(a[2]);
if (GS.IsNull()) {
return 1;
}
else {
GeomConvert_SurfToAnaSurf aSurfToAna(GS);
aSurfToAna.SetConvType(aConvType);
if(aConvType == GeomConvert_Target)
aSurfToAna.SetTarget(aSurf);
Handle(Geom_Surface) anAnaSurf = aSurfToAna.ConvertToAnalytical(tol);
if (!anAnaSurf.IsNull())
{
DrawTrSurf::Set(a[1], anAnaSurf);
Standard_Real aGap = aSurfToAna.Gap();
di << "Gap = " << aGap << "\n";
}
else
di << "Conversion failed" << "\n";
}
}
else {
GeomConvert_CurveToAnaCurve aCurvToAna(GC);
aCurvToAna.SetConvType(aConvType);
if (aConvType == GeomConvert_Target)
aCurvToAna.SetTarget(aCurv);
Handle(Geom_Curve) anAnaCurv;
Standard_Real tf = GC->FirstParameter(), tl = GC->LastParameter(), ntf, ntl;
Standard_Boolean isdone = aCurvToAna.ConvertToAnalytical(tol, anAnaCurv, tf, tl, ntf, ntl);
if (isdone)
{
anAnaCurv = new Geom_TrimmedCurve(anAnaCurv, ntf, ntl);
DrawTrSurf::Set(a[1], anAnaCurv);
Standard_Real aGap = aCurvToAna.Gap();
di << "Gap = " << aGap << "\n";
}
else
di << "Conversion failed" << "\n";
}
return 0;
}
//=======================================================================
//function : tobezier
@ -1714,6 +1821,11 @@ void GeomliteTest::SurfaceCommands(Draw_Interpretor& theCommands)
__FILE__,
converting,g);
theCommands.Add("tocanon",
"tocanon result c3d/surf [tol [sim gap lin cir ell pln cyl con sph tor]]",
__FILE__,
tocanon, g);
theCommands.Add("tobezier",
"tobezier result c2d/c3d/surf [ufirst, ulast / ufirst, ulast, vfirst, vlast]",
__FILE__,

View File

@ -61,6 +61,14 @@
#include <Adaptor3d_CurveOnSurface.hxx>
#include <BRepAdaptor_Curve2d.hxx>
#include <BRepAdaptor_Surface.hxx>
#include <Geom_Plane.hxx>
#include <Geom_CylindricalSurface.hxx>
#include <Geom_ConicalSurface.hxx>
#include <Geom_SphericalSurface.hxx>
#include <Geom_Line.hxx>
#include <Geom_Circle.hxx>
#include <Geom_Ellipse.hxx>
#include <ShapeAnalysis_CanonicalRecognition.hxx>
#include <stdio.h>
static Standard_Integer tolerance
@ -976,6 +984,203 @@ static Standard_Integer checkedge(Draw_Interpretor& di, Standard_Integer argc, c
return 0;
}
//=======================================================================
// getanasurf
//=======================================================================
static Standard_Integer getanasurf(Draw_Interpretor& di,
Standard_Integer n, const char** a)
{
if (n < 3) {
di << "Usage: \n";
di << "getanasurf res shape [target [tol [sample]]] \n";
di << "target is reqired type of surface and can be: pln, cyl, con sph \n";
di << "sample is surface of required type, which parameters are used as starting \n";
di << "point for seaching parametrs of surface by Least Square method when input shape \n";
di << "is edge or wire \n";
return 1;
}
TopoDS_Shape sh = DBRep::Get(a[2]);
if (sh.IsNull()) return 1;
TopAbs_ShapeEnum aShType = sh.ShapeType();
if (!(aShType == TopAbs_SHELL || aShType == TopAbs_FACE || aShType == TopAbs_EDGE || aShType == TopAbs_WIRE))
{
di << "Wrong shape type, shape can be shell or face or edge or wire\n";
return 1;
}
GeomAbs_SurfaceType aTargets[] = { GeomAbs_Plane, GeomAbs_Cylinder, GeomAbs_Cone, GeomAbs_Sphere };
Standard_Integer isurf = 0;
if (n > 3)
{
if (strcmp(a[3], "pln") == 0)
isurf = 0;
else if (strcmp(a[3], "cyl") == 0)
isurf = 1;
else if (strcmp(a[3], "con") == 0)
isurf = 2;
else if (strcmp(a[3], "sph") == 0)
isurf = 3;
}
Standard_Real tol = 1.e-7;
if (n > 4)
tol = Draw::Atof(a[4]);
// get sample target for edge and wire
GeomAdaptor_Surface aSampleSurf;
if (n > 5 && (sh.ShapeType() == TopAbs_EDGE || sh.ShapeType() == TopAbs_WIRE ))
{
Handle(Geom_Surface) aGSurf = DrawTrSurf::GetSurface(a[5]);
if (aGSurf.IsNull())
{
di << "Sample surface is null" << "\n";
return 1;
}
aSampleSurf.Load(aGSurf);
GeomAbs_SurfaceType aSType = aSampleSurf.GetType();
if (aSType != aTargets[isurf])
{
di << "Sample surface has wrong type" << "\n";
return 1;
}
}
ShapeAnalysis_CanonicalRecognition aCanonRec(sh);
Handle(Geom_Surface) aRes;
switch (aTargets[isurf])
{
case GeomAbs_Plane:
{
gp_Pln aPln;
if (aSampleSurf.GetType() == GeomAbs_Plane)
aPln = aSampleSurf.Plane();
if (aCanonRec.IsPlane(tol, aPln))
aRes = new Geom_Plane(aPln);
break;
}
case GeomAbs_Cylinder:
{
gp_Cylinder aCyl;
if (aSampleSurf.GetType() == GeomAbs_Cylinder)
aCyl = aSampleSurf.Cylinder();
if (aCanonRec.IsCylinder(tol, aCyl))
aRes = new Geom_CylindricalSurface(aCyl);
break;
}
case GeomAbs_Cone:
{
gp_Cone aCon;
if (aSampleSurf.GetType() == GeomAbs_Cone)
aCon = aSampleSurf.Cone();
if (aCanonRec.IsCone(tol, aCon))
aRes = new Geom_ConicalSurface(aCon);
break;
}
case GeomAbs_Sphere:
{
gp_Sphere aSph;
if (aSampleSurf.GetType() == GeomAbs_Sphere)
aSph = aSampleSurf.Sphere();
if (aCanonRec.IsSphere(tol, aSph))
aRes = new Geom_SphericalSurface(aSph);
break;
}
default:
break;
}
if (!aRes.IsNull())
{
DrawTrSurf::Set(a[1], aRes);
di << "Gap = " << aCanonRec.GetGap() << "\n";
}
else
{
di << "Cannot get required surface" << "\n";
}
return 0;
}
//=======================================================================
//function : getanacurve
//purpose :
//=======================================================================
Standard_Integer getanacurve(Draw_Interpretor& di,
Standard_Integer n, const char** a)
{
if (n < 3) {
di << "Usage: \n";
di << "getanacurve res shape [target [tol]] \n";
di << "target is reqired type of curve and can be: lin, cir, ell \n";
return 1;
}
TopoDS_Shape sh = DBRep::Get(a[2]);
if (sh.IsNull()) return 1;
TopAbs_ShapeEnum aShType = sh.ShapeType();
if (!(aShType == TopAbs_WIRE || aShType == TopAbs_EDGE))
{
di << "Wrong shape type, shape can be wire or or edge \n";
return 1;
}
GeomAbs_CurveType aTargets[] = { GeomAbs_Line, GeomAbs_Circle, GeomAbs_Ellipse };
Standard_Integer icurv = 0;
if (n > 3)
{
if (strcmp(a[3],"lin") == 0)
icurv = 0;
else if (strcmp(a[3], "cir") == 0)
icurv = 1;
else if (strcmp(a[3], "ell") == 0)
icurv = 2;
}
Standard_Real tol = Precision::Confusion();
if (n > 4)
tol = Draw::Atof(a[4]);
ShapeAnalysis_CanonicalRecognition aCanonRec(sh);
Handle(Geom_Curve) aRes;
switch (aTargets[icurv])
{
case GeomAbs_Line:
{
gp_Lin aLin;
if (aCanonRec.IsLine(tol, aLin))
aRes = new Geom_Line(aLin);
break;
}
case GeomAbs_Circle:
{
gp_Circ aCirc;
if (aCanonRec.IsCircle(tol, aCirc))
aRes = new Geom_Circle(aCirc);
break;
}
case GeomAbs_Ellipse:
{
gp_Elips anElips;
if (aCanonRec.IsEllipse(tol, anElips))
aRes = new Geom_Ellipse(anElips);
break;
}
default:
break;
}
if (!aRes.IsNull())
{
DrawTrSurf::Set(a[1], aRes);
di << "Gap = " << aCanonRec.GetGap() << "\n";
}
else
{
di << "Cannot get required curve" << "\n";
}
return 0;
}
//=======================================================================
//function : InitCommands
@ -1018,4 +1223,8 @@ static Standard_Integer checkedge(Draw_Interpretor& di, Standard_Integer argc, c
theCommands.Add("getareacontour","wire ",__FILE__, getareacontour, groupold);
theCommands.Add ("checkselfintersection","wire [face]", __FILE__,checkselfintersection,g);
theCommands.Add ("checkedge","edge [face]", __FILE__,checkedge,g);
theCommands.Add("getanasurf", "getanasurf res shape [target [tol [sample]]] ", __FILE__, getanasurf, g);
theCommands.Add("getanacurve", "getanacurve res shape [target [tol]]", __FILE__, getanacurve, g);
}

View File

@ -44,3 +44,11 @@ ShapeAnalysis_WireOrder.cxx
ShapeAnalysis_WireOrder.hxx
ShapeAnalysis_WireVertex.cxx
ShapeAnalysis_WireVertex.hxx
ShapeAnalysis_CanonicalRecognition.cxx
ShapeAnalysis_CanonicalRecognition.hxx
ShapeAnalysis_FuncSphereLSDist.cxx
ShapeAnalysis_FuncSphereLSDist.hxx
ShapeAnalysis_FuncCylinderLSDist.cxx
ShapeAnalysis_FuncCylinderLSDist.hxx
ShapeAnalysis_FuncConeLSDist.cxx
ShapeAnalysis_FuncConeLSDist.hxx

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,169 @@
// Copyright (c) 2022 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.
#ifndef _ShapeAnalysis_CanonicalRecognition_HeaderFile
#define _ShapeAnalysis_CanonicalRecognition_HeaderFile
#include <Standard.hxx>
#include <Standard_DefineAlloc.hxx>
#include <Standard_Handle.hxx>
#include <Standard_Boolean.hxx>
#include <Standard_Integer.hxx>
#include <TopAbs_ShapeEnum.hxx>
#include <TopoDS_Shape.hxx>
#include <TopoDS_Shell.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Wire.hxx>
#include <TopoDS_Edge.hxx>
#include <GeomAbs_SurfaceType.hxx>
#include <GeomAbs_CurveType.hxx>
#include <GeomConvert_ConvType.hxx>
#include <TColStd_Array1OfReal.hxx>
class gp_Pln;
class gp_Cone;
class gp_Cylinder;
class gp_Sphere;
class gp_Lin;
class gp_Circ;
class gp_Elips;
class Geom_Curve;
class Geom_Surface;
//! This class provides operators for analysis surfaces and curves of shapes
//! in order to find out more simple geometry entities, which could replace
//! existing complex (for exampe, BSpline) geometry objects with given tolerance.
class ShapeAnalysis_CanonicalRecognition
{
public:
DEFINE_STANDARD_ALLOC
//! Empty constructor
Standard_EXPORT ShapeAnalysis_CanonicalRecognition();
//! constructor with shape initialisation
Standard_EXPORT ShapeAnalysis_CanonicalRecognition(const TopoDS_Shape& theShape);
//! Sets shape
Standard_EXPORT void SetShape(const TopoDS_Shape& theShape);
//! Returns input shape
const TopoDS_Shape& GetShape() const
{
return myShape;
}
//! Returns deviation between input geometry entity and analytical entity
Standard_Real GetGap() const
{
return myGap;
}
//! Returns status of operation.
//! Current meaning of possible values of status:
//! -1 - algorithm is not initalazed by shape
//! 0 - no errors
//! 1 - error during any operation (usually - because of wrong input data)
//! Any operation (calling any methods like IsPlane(...), ...) can be performed
//! when current staue is equal 0.
//! If after any operation status != 0, it is necessary to set it 0 by method ClearStatus()
//! before calling other operation.
Standard_Integer GetStatus() const
{
return myStatus;
}
//! Returns status to be equal 0.
void ClearStatus()
{
myStatus = 0;
}
//! Returns true if the underlined surface can be represent by plane with tolerance theTol
//! and sets in thePln the result plane.
Standard_EXPORT Standard_Boolean IsPlane(const Standard_Real theTol, gp_Pln& thePln);
//! Returns true if the underlined surface can be represent by cylindrical one with tolerance theTol
//! and sets in theCyl the result cylinrical surface.
Standard_EXPORT Standard_Boolean IsCylinder(const Standard_Real theTol, gp_Cylinder& theCyl);
//! Returns true if the underlined surface can be represent by conical one with tolerance theTol
//! and sets in theCone the result conical surface.
Standard_EXPORT Standard_Boolean IsCone(const Standard_Real theTol, gp_Cone& theCone);
//! Returns true if the underlined surface can be represent by spherical one with tolerance theTol
//! and sets in theSphere the result spherical surface.
Standard_EXPORT Standard_Boolean IsSphere(const Standard_Real theTol, gp_Sphere& theSphere);
//! Returns true if the underlined curve can be represent by line with tolerance theTol
//! and sets in theLin the result line.
Standard_EXPORT Standard_Boolean IsLine(const Standard_Real theTol, gp_Lin& theLin);
//! Returns true if the underlined curve can be represent by circle with tolerance theTol
//! and sets in theCirc the result circle.
Standard_EXPORT Standard_Boolean IsCircle(const Standard_Real theTol, gp_Circ& theCirc);
//! Returns true if the underlined curve can be represent by ellipse with tolerance theTol
//! and sets in theCirc the result ellipse.
Standard_EXPORT Standard_Boolean IsEllipse(const Standard_Real theTol, gp_Elips& theElips);
private:
Standard_Boolean IsElementarySurf(const GeomAbs_SurfaceType theTarget, const Standard_Real theTol,
gp_Ax3& thePos, TColStd_Array1OfReal& theParams);
Standard_Boolean IsConic(const GeomAbs_CurveType theTarget, const Standard_Real theTol,
gp_Ax2& thePos, TColStd_Array1OfReal& theParams);
static Handle(Geom_Surface) GetSurface(const TopoDS_Face& theFace, const Standard_Real theTol,
const GeomConvert_ConvType theType, const GeomAbs_SurfaceType theTarget,
Standard_Real& theGap, Standard_Integer& theStatus);
static Handle(Geom_Surface) GetSurface(const TopoDS_Shell& theShell, const Standard_Real theTol,
const GeomConvert_ConvType theType, const GeomAbs_SurfaceType theTarget,
Standard_Real& theGap, Standard_Integer& theStatus);
static Handle(Geom_Surface) GetSurface(const TopoDS_Edge& theEdge, const Standard_Real theTol,
const GeomConvert_ConvType theType, const GeomAbs_SurfaceType theTarget,
gp_Ax3& thePos, TColStd_Array1OfReal& theParams,
Standard_Real& theGap, Standard_Integer& theStatus);
static Handle(Geom_Surface) GetSurface(const TopoDS_Wire& theWire, const Standard_Real theTol,
const GeomConvert_ConvType theType, const GeomAbs_SurfaceType theTarget,
gp_Ax3& thePos, TColStd_Array1OfReal& theParams,
Standard_Real& theGap, Standard_Integer& theStatus);
static Handle(Geom_Curve) GetCurve(const TopoDS_Edge& theEdge, const Standard_Real theTol,
const GeomConvert_ConvType theType, const GeomAbs_CurveType theTarget,
Standard_Real& theGap, Standard_Integer& theStatus);
static Standard_Boolean GetSurfaceByLS(const TopoDS_Wire& theWire, const Standard_Real theTol,
const GeomAbs_SurfaceType theTarget,
gp_Ax3& thePos, TColStd_Array1OfReal& theParams,
Standard_Real& theGap, Standard_Integer& theStatus);
void Init(const TopoDS_Shape& theShape);
private:
TopoDS_Shape myShape;
TopAbs_ShapeEnum mySType;
Standard_Real myGap;
Standard_Integer myStatus;
};
#endif // _ShapeAnalysis_CanonicalRecognition_HeaderFile

View File

@ -0,0 +1,68 @@
// Copyright (c) 1995-1999 Matra Datavision
// Copyright (c) 1999-2022 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 <ShapeAnalysis_FuncConeLSDist.hxx>
#include <gp_Pnt.hxx>
#include <gp_Vec.hxx>
#include <gp_Ax3.hxx>
#include <math_Vector.hxx>
#include <ElSLib.hxx>
//=======================================================================
//function : ShapeAnalysis_FuncConeLSDist
//purpose :
//=======================================================================
ShapeAnalysis_FuncConeLSDist::ShapeAnalysis_FuncConeLSDist(
const Handle(TColgp_HArray1OfXYZ)& thePoints,
const gp_Dir& theDir):
myPoints(thePoints), myDir(theDir)
{
}
//=======================================================================
//function : NbVariables
//purpose :
//=======================================================================
Standard_Integer ShapeAnalysis_FuncConeLSDist::NbVariables () const
{
return 5;
}
//=======================================================================
//function : Value
//purpose :
//=======================================================================
Standard_Boolean ShapeAnalysis_FuncConeLSDist::Value(const math_Vector& X, Standard_Real& F)
{
gp_Pnt aLoc(X(1), X(2), X(3));
Standard_Real aSemiAngle = X(4), anR = X(5);
gp_Ax3 aPos(aLoc, myDir);
F = 0.;
Standard_Integer i;
for (i = myPoints->Lower(); i <= myPoints->Upper(); ++i)
{
Standard_Real u, v;
gp_Pnt aPi(myPoints->Value(i));
ElSLib::ConeParameters(aPos, anR, aSemiAngle, aPi, u, v);
gp_Pnt aPp;
ElSLib::ConeD0(u, v, aPos, anR, aSemiAngle, aPp);
F += aPi.SquareDistance(aPp);
}
return Standard_True;
}

View File

@ -0,0 +1,66 @@
// Copyright (c) 1991-1999 Matra Datavision
// Copyright (c) 1999-2022 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.
#ifndef _ShapeAnalysis_FuncConeLSDist_HeaderFile
#define _ShapeAnalysis_FuncConeLSDist_HeaderFile
#include <Standard.hxx>
#include <Standard_DefineAlloc.hxx>
#include <math_MultipleVarFunction.hxx>
#include <TColgp_HArray1OfXYZ.hxx>
#include <math_Vector.hxx>
#include <gp_Dir.hxx>
//! Function for search of Cone canonic parameters: coordinates of center local coordinate system,
//! direction of axis, radius and semi-angle from set of points
//! by least square method.
//!
//!
class ShapeAnalysis_FuncConeLSDist : public math_MultipleVarFunction
{
public:
DEFINE_STANDARD_ALLOC
//! Constructor.
Standard_EXPORT ShapeAnalysis_FuncConeLSDist() {};
Standard_EXPORT ShapeAnalysis_FuncConeLSDist(const Handle(TColgp_HArray1OfXYZ)& thePoints,
const gp_Dir& theDir);
void SetPoints(const Handle(TColgp_HArray1OfXYZ)& thePoints)
{
myPoints = thePoints;
}
void SetDir(const gp_Dir& theDir)
{
myDir = theDir;
}
//! Number of variables.
Standard_EXPORT Standard_Integer NbVariables() const Standard_OVERRIDE;
//! Value.
Standard_EXPORT Standard_Boolean Value(const math_Vector& X,Standard_Real& F) Standard_OVERRIDE;
private:
Handle(TColgp_HArray1OfXYZ) myPoints;
gp_Dir myDir;
};
#endif // _ShapeAnalysis_FuncConeLSDist_HeaderFile

View File

@ -0,0 +1,140 @@
// Copyright (c) 1995-1999 Matra Datavision
// Copyright (c) 1999-2022 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 <ShapeAnalysis_FuncCylinderLSDist.hxx>
#include <gp_Pnt.hxx>
#include <gp_Vec.hxx>
#include <math_Vector.hxx>
//=======================================================================
//function : ShapeAnalysis_FuncCylinderLSDist
//purpose :
//=======================================================================
ShapeAnalysis_FuncCylinderLSDist::ShapeAnalysis_FuncCylinderLSDist(
const Handle(TColgp_HArray1OfXYZ)& thePoints,
const gp_Dir& theDir):
myPoints(thePoints), myDir(theDir)
{
}
//=======================================================================
//function : NbVariables
//purpose :
//=======================================================================
Standard_Integer ShapeAnalysis_FuncCylinderLSDist::NbVariables () const
{
return 4;
}
//=======================================================================
//function : Value
//purpose :
//=======================================================================
Standard_Boolean ShapeAnalysis_FuncCylinderLSDist::Value(const math_Vector& X,Standard_Real& F)
{
gp_XYZ aLoc(X(1), X(2), X(3));
Standard_Real anR2 = X(4)*X(4);
F = 0.;
Standard_Integer i;
for (i = myPoints->Lower(); i <= myPoints->Upper(); ++i)
{
gp_Vec aV(myPoints->Value(i) - aLoc);
Standard_Real aD2 = aV.CrossSquareMagnitude(myDir);
Standard_Real d = aD2 - anR2;
F += d * d;
}
return Standard_True;
}
//=======================================================================
//function : Gradient
//purpose :
//=======================================================================
Standard_Boolean ShapeAnalysis_FuncCylinderLSDist::Gradient(const math_Vector& X,math_Vector& G)
{
gp_XYZ aLoc(X(1), X(2), X(3));
Standard_Real anR = X(4), anR2 = anR * anR;
Standard_Real x = myDir.X(), y = myDir.Y(), z = myDir.Z();
G.Init(0.);
Standard_Integer i;
for (i = myPoints->Lower(); i <= myPoints->Upper(); ++i)
{
gp_Vec aV(myPoints->Value(i) - aLoc);
Standard_Real aD2 = aV.CrossSquareMagnitude(myDir);
Standard_Real d = aD2 - anR2;
Standard_Real Dx0 = 2.*(aV.Z()*x - aV.X()*z)*z
-2.*(aV.X()*y - aV.Y()*x)*y;
Standard_Real Dy0 = -2.*(aV.Y()*z - aV.Z()*y)*z
+2.*(aV.X()*y - aV.Y()*x)*x;
Standard_Real Dz0 = 2.*(aV.Y()*z - aV.Z()*y)*y
-2.*(aV.Z()*x - aV.X()*z)*x;
G(1) += d * Dx0;
G(2) += d * Dy0;
G(3) += d * Dz0;
//
G(4) += d;
}
G *= 2;
G(6) *= -2.*anR;
return Standard_True;
}
//=======================================================================
//function : Values
//purpose :
//=======================================================================
Standard_Boolean ShapeAnalysis_FuncCylinderLSDist::Values(const math_Vector& X,Standard_Real& F,math_Vector& G)
{
gp_XYZ aLoc(X(1), X(2), X(3));
Standard_Real anR = X(4), anR2 = anR * anR;
Standard_Real x = myDir.X(), y = myDir.Y(), z = myDir.Z();
F = 0.;
G.Init(0.);
Standard_Integer i;
for (i = myPoints->Lower(); i <= myPoints->Upper(); ++i)
{
gp_Vec aV(myPoints->Value(i) - aLoc);
Standard_Real aD2 = aV.CrossSquareMagnitude(myDir);
Standard_Real d = aD2 - anR2;
Standard_Real Dx0 = 2.*(aV.Z()*x - aV.X()*z)*z
- 2.*(aV.X()*y - aV.Y()*x)*y;
Standard_Real Dy0 = -2.*(aV.Y()*z - aV.Z()*y)*z
+ 2.*(aV.X()*y - aV.Y()*x)*x;
Standard_Real Dz0 = 2.*(aV.Y()*z - aV.Z()*y)*y
- 2.*(aV.Z()*x - aV.X()*z)*x;
G(1) += d * Dx0;
G(2) += d * Dy0;
G(3) += d * Dz0;
//
G(4) += d;
//
F += d * d;
}
G *= 2;
G(4) *= -2.*anR;
return true;
}

View File

@ -0,0 +1,100 @@
// Copyright (c) 1991-1999 Matra Datavision
// Copyright (c) 1999-2022 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.
#ifndef _ShapeAnalysis_FuncCylinderLSDist_HeaderFile
#define _ShapeAnalysis_FuncCylinderLSDist_HeaderFile
#include <Standard.hxx>
#include <Standard_DefineAlloc.hxx>
#include <math_MultipleVarFunctionWithGradient.hxx>
#include <TColgp_HArray1OfXYZ.hxx>
#include <math_Vector.hxx>
#include <gp_Dir.hxx>
//! Function for search of cylinder canonic parameters: coordinates of center local coordinate system,
//! direction of axis and radius from set of points
//! by least square method.
//!
//! The class inherits math_MultipleVarFunctionWithGradient and thus is intended
//! for use in math_BFGS algorithm.
//!
//! Parametrisation:
//! Cylinder is defined by its axis and radius. Axis is defined by 3 cartesian coordinats it location x0, y0, z0
//! and direction, which is constant and set by user:
//! dir.x, dir.y, dir.z
//! The criteria is:
//! F(x0, y0, z0, theta, phi, R) = Sum[|(P(i) - Loc)^dir|^2 - R^2]^2 => min
//! P(i) is i-th sample point, Loc, dir - axis location and direction, R - radius
//!
//! The square vector product |(P(i) - Loc)^dir|^2 is:
//!
//! [(y - y0)*dir.z - (z - z0)*dir.y]^2 +
//! [(z - z0)*dir.x - (x - x0)*dir.z]^2 +
//! [(x - x0)*dir.y - (y - y0)*dir.x]^2
//!
//! First derivative of square vector product are:
//! Dx0 = 2*[(z - z0)*dir.x - (x - x0)*dir.z]*dir.z
//! -2*[(x - x0)*dir.y - (y - y0)*dir.x]*dir.y
//! Dy0 = -2*[(y - y0)*dir.z - (z - z0)*dir.y]*dir.z
//! +2*[(x - x0)*dir.y - (y - y0)*dir.x]*dir.x
//! Dz0 = 2*[(y - y0)*dir.z - (z - z0)*dir.y]*dir.y
//! -2*[(z - z0)*dir.x - (x - x0)*dir.z]*dir.x
//!
//! dF/dx0 : G1(...) = 2*Sum{[...]*Dx0}
//! dF/dy0 : G2(...) = 2*Sum{[...]*Dy0}
//! dF/dz0 : G3(...) = 2*Sum{[...]*Dz0}
//! dF/dR : G4(...) = -4*R*Sum[...]
//! [...] = [|(P(i) - Loc)^dir|^2 - R^2]
class ShapeAnalysis_FuncCylinderLSDist : public math_MultipleVarFunctionWithGradient
{
public:
DEFINE_STANDARD_ALLOC
//! Constructor.
Standard_EXPORT ShapeAnalysis_FuncCylinderLSDist() {};
Standard_EXPORT ShapeAnalysis_FuncCylinderLSDist(const Handle(TColgp_HArray1OfXYZ)& thePoints,
const gp_Dir& theDir);
void SetPoints(const Handle(TColgp_HArray1OfXYZ)& thePoints)
{
myPoints = thePoints;
}
void SetDir(const gp_Dir& theDir)
{
myDir = theDir;
}
//! Number of variables.
Standard_EXPORT Standard_Integer NbVariables() const Standard_OVERRIDE;
//! Value.
Standard_EXPORT Standard_Boolean Value(const math_Vector& X,Standard_Real& F) Standard_OVERRIDE;
//! Gradient.
Standard_EXPORT Standard_Boolean Gradient(const math_Vector& X,math_Vector& G) Standard_OVERRIDE;
//! Value and gradient.
Standard_EXPORT Standard_Boolean Values(const math_Vector& X,Standard_Real& F,math_Vector& G) Standard_OVERRIDE;
private:
Handle(TColgp_HArray1OfXYZ) myPoints;
gp_Dir myDir;
};
#endif // _ShapeAnalysis_FuncCylinderLSDist_HeaderFile

View File

@ -0,0 +1,115 @@
// Created on: 2016-05-10
// Created by: Alexander MALYSHEV
// Copyright (c) 1995-1999 Matra Datavision
// Copyright (c) 1999-2016 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 <ShapeAnalysis_FuncSphereLSDist.hxx>
#include <gp_Pnt.hxx>
#include <gp_Vec.hxx>
#include <math_Vector.hxx>
//=======================================================================
//function : ShapeAnalysis_FuncSphereLSDist
//purpose :
//=======================================================================
ShapeAnalysis_FuncSphereLSDist::ShapeAnalysis_FuncSphereLSDist(const Handle(TColgp_HArray1OfXYZ)& thePoints):
myPoints(thePoints)
{
}
//=======================================================================
//function : NbVariables
//purpose :
//=======================================================================
Standard_Integer ShapeAnalysis_FuncSphereLSDist::NbVariables () const
{
return 4;
}
//=======================================================================
//function : Value
//purpose :
//=======================================================================
Standard_Boolean ShapeAnalysis_FuncSphereLSDist::Value(const math_Vector& X,Standard_Real& F)
{
gp_XYZ aLoc(X(1), X(2), X(3));
Standard_Real anR2 = X(4)*X(4);
F = 0.;
Standard_Integer i;
for (i = myPoints->Lower(); i <= myPoints->Upper(); ++i)
{
Standard_Real d = (myPoints->Value(i) - aLoc).SquareModulus() - anR2;
F += d * d;
}
return Standard_True;
}
//=======================================================================
//function : Gradient
//purpose :
//=======================================================================
Standard_Boolean ShapeAnalysis_FuncSphereLSDist::Gradient(const math_Vector& X,math_Vector& G)
{
gp_XYZ aLoc(X(1), X(2), X(3));
Standard_Real anR = X(4), anR2 = anR * anR;
G.Init(0.);
Standard_Integer i;
for (i = myPoints->Lower(); i <= myPoints->Upper(); ++i)
{
gp_XYZ dLoc = myPoints->Value(i) - aLoc;
Standard_Real d = dLoc.SquareModulus() - anR2;
G(1) += d * dLoc.X();
G(2) += d * dLoc.Y();
G(3) += d * dLoc.Z();
G(4) += d;
}
G *= -4;
G(4) *= anR;
return Standard_True;
}
//=======================================================================
//function : Values
//purpose :
//=======================================================================
Standard_Boolean ShapeAnalysis_FuncSphereLSDist::Values(const math_Vector& X,Standard_Real& F,math_Vector& G)
{
gp_XYZ aLoc(X(1), X(2), X(3));
Standard_Real anR = X(4), anR2 = anR * anR;
G.Init(0.);
F = 0.;
Standard_Integer i;
for (i = myPoints->Lower(); i <= myPoints->Upper(); ++i)
{
gp_XYZ dLoc = myPoints->Value(i) - aLoc;
Standard_Real d = dLoc.SquareModulus() - anR2;
G(1) += d * dLoc.X();
G(2) += d * dLoc.Y();
G(3) += d * dLoc.Z();
G(4) += d;
F += d * d;
}
G *= -4;
G(4) *= anR;
return true;
}

View File

@ -0,0 +1,77 @@
// Copyright (c) 1991-1999 Matra Datavision
// Copyright (c) 1999-2022 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.
#ifndef _ShapeAnalysis_FuncSphereLSDist_HeaderFile
#define _ShapeAnalysis_FuncSphereLSDist_HeaderFile
#include <Standard.hxx>
#include <Standard_DefineAlloc.hxx>
#include <math_MultipleVarFunctionWithGradient.hxx>
#include <TColgp_HArray1OfXYZ.hxx>
#include <math_Vector.hxx>
//! Function for search of sphere canonic parameters: coordinates of center and radius from set of moints
//! by least square method.
//! //!
//! The class inherits math_MultipleVarFunctionWithGradient and thus is intended
//! for use in math_BFGS algorithm.
//!
//! The criteria is:
//! F(x0, y0, z0, R) = Sum[(x(i) - x0)^2 + (y(i) - y0)^2 + (z(i) - z0)^2 - R^2]^2 => min,
//! x(i), y(i), z(i) - coordinates of sample points, x0, y0, z0, R - coordinates of center and radius of sphere,
//! which must be defined
//!
//! The first derivative are:
//! dF/dx0 : G1(x0, y0, z0, R) = -4*Sum{[...]*(x(i) - x0)}
//! dF/dy0 : G2(x0, y0, z0, R) = -4*Sum{[...]*(y(i) - y0)}
//! dF/dz0 : G3(x0, y0, z0, R) = -4*Sum{[...]*(z(i) - z0)}
//! dF/dR : G4(x0, y0, z0, R) = -4*R*Sum[...]
//! [...] = [(x(i) - x0)^2 + (y(i) - y0)^2 + (z(i) - z0)^2 - R^2]
//!
class ShapeAnalysis_FuncSphereLSDist : public math_MultipleVarFunctionWithGradient
{
public:
DEFINE_STANDARD_ALLOC
//! Constructor.
Standard_EXPORT ShapeAnalysis_FuncSphereLSDist() {};
Standard_EXPORT ShapeAnalysis_FuncSphereLSDist(const Handle(TColgp_HArray1OfXYZ)& thePoints);
void SetPoints(const Handle(TColgp_HArray1OfXYZ)& thePoints)
{
myPoints = thePoints;
}
//! Number of variables.
Standard_EXPORT Standard_Integer NbVariables() const Standard_OVERRIDE;
//! Value.
Standard_EXPORT Standard_Boolean Value(const math_Vector& X,Standard_Real& F) Standard_OVERRIDE;
//! Gradient.
Standard_EXPORT Standard_Boolean Gradient(const math_Vector& X,math_Vector& G) Standard_OVERRIDE;
//! Value and gradient.
Standard_EXPORT Standard_Boolean Values(const math_Vector& X,Standard_Real& F,math_Vector& G) Standard_OVERRIDE;
private:
Handle(TColgp_HArray1OfXYZ) myPoints;
};
#endif // _ShapeAnalysis_FuncSphereLSDist_HeaderFile

View File

@ -53,7 +53,7 @@ gce_MakeCirc::gce_MakeCirc(const gp_Pnt& P1 ,
//=========================================================================
Standard_Real dist1, dist2, dist3, aResolution;
//
aResolution=gp::Resolution();
aResolution = gp::Resolution();
//
dist1 = P1.Distance(P2);
dist2 = P1.Distance(P3);
@ -76,7 +76,7 @@ gce_MakeCirc::gce_MakeCirc(const gp_Pnt& P1 ,
P2.Coord(x2,y2,z2);
P3.Coord(x3,y3,z3);
gp_Dir Dir1(x2-x1,y2-y1,z2-z1);
gp_Dir Dir2(x3-x2,y3-y2,z3-z2);
gp_Vec VDir2(x3-x2,y3-y2,z3-z2);
//
gp_Ax1 anAx1(P1, Dir1);
gp_Lin aL12 (anAx1);
@ -85,14 +85,21 @@ gce_MakeCirc::gce_MakeCirc(const gp_Pnt& P1 ,
return;
}
//
gp_Dir Dir3 = Dir1.Crossed(Dir2);
gp_Vec VDir1(Dir1);
gp_Vec VDir3 = VDir1.Crossed(VDir2);
if(VDir3.SquareMagnitude() < aResolution)
{
TheError = gce_ColinearPoints;
return;
}
//
gp_Dir Dir3(VDir3);
gp_Dir dir = Dir1.Crossed(Dir3);
gp_Lin L1(gp_Pnt((P1.XYZ()+P2.XYZ())/2.),dir);
dir = Dir2.Crossed(Dir3);
dir = VDir2.Crossed(Dir3);
gp_Lin L2(gp_Pnt((P3.XYZ()+P2.XYZ())/2.),dir);
Standard_Real Tol = 0.000000001;
Standard_Real Tol = Precision::PConfusion();
Extrema_ExtElC distmin(L1,L2,Tol);
if (!distmin.IsDone()) {
@ -139,7 +146,7 @@ gce_MakeCirc::gce_MakeCirc(const gp_Pnt& P1 ,
//Dir2 = gp_Dir(x2-x3,y2-y3,z2-z3);
//modified by NIZNHY-PKV Thu Mar 3 11:31:13 2005t
//
TheCirc = gp_Circ(gp_Ax2(pInt, Dir3, Dir1),(dist1+dist2+dist3)/3.);
TheCirc = gp_Circ(gp_Ax2(pInt, gp_Dir(VDir3), Dir1),(dist1+dist2+dist3)/3.);
TheError = gce_Done;
}
}

12
tests/cr/approx/A1 Normal file
View File

@ -0,0 +1,12 @@
polyline w 0 0 0 1 0 0 1 1 0 0 1 0 0 0 0
getanasurf res w pln 1.e-3
if {[isdraw res]} {
set log [dump res]
if { [regexp {Plane} $log ] != 1 } {
puts "Error: surface is not a plane"
}
} else {
puts "Error: required surface is not got"
}

15
tests/cr/approx/A2 Normal file
View File

@ -0,0 +1,15 @@
cylinder cyl 0 0 0 1 1 1 1
mkface f cyl 0 2 0 1
explode f w
nurbsconvert w f_1
cylinder cyl 0.1 0.1 0.1 1 1 1 .9
getanasurf res w cyl 1.e-3 cyl
if {[isdraw res]} {
set log [dump res]
if { [regexp {CylindricalSurface} $log ] != 1 } {
puts "Error: surface is not a cylindrical surface"
}
} else {
puts "Error: required surface is not got"
}

15
tests/cr/approx/A3 Normal file
View File

@ -0,0 +1,15 @@
plane pl 0 0 0 1 1 1
pcone con pl 2 1 3 60
explode con w
nurbsconvert w con_1
cone con 0.1 .1 .1 1 1 1 -17 1.9
getanasurf res w con 1.e-3 con
if {[isdraw res]} {
set log [dump res]
if { [regexp {ConicalSurface} $log ] != 1 } {
puts "Error: surface is not a conical surface"
}
} else {
puts "Error: required surface is not got"
}

16
tests/cr/approx/A4 Normal file
View File

@ -0,0 +1,16 @@
sphere sph 1
mkface f sph 0 2 0 pi/2
explode f w
nurbsconvert w f_1
sphere sph 0.1 0.1 0.1 1
getanasurf res w sph 1.e-3 sph
if {[isdraw res]} {
set log [dump res]
if { [regexp {SphericalSurface} $log ] != 1 } {
puts "Error: surface is not a spherical surface"
}
} else {
puts "Error: required surface is not got"
}

13
tests/cr/base/A1 Normal file
View File

@ -0,0 +1,13 @@
beziercurve bz 3 0 0 0 .5 .5e-3 0 1 0 0
mkedge e bz
getanacurve c e lin 1.e-3
if {[isdraw c]} {
set log [dump c]
if { [regexp {Line} $log ] != 1 } {
puts "Error: curve is not a line"
}
} else {
puts "Error: required curve is not got"
}

12
tests/cr/base/A2 Normal file
View File

@ -0,0 +1,12 @@
beziercurve bz 3 0 0 0 .5 .5e-3 0 1 0 0
mkedge e bz
getanacurve c e cir 1.e-3
if {[isdraw c]} {
set log [dump c]
if { [regexp {Circle} $log ] != 1 } {
puts "Error: curve is not a circle"
}
} else {
puts "Error: required curve is not got"
}

13
tests/cr/base/A3 Normal file
View File

@ -0,0 +1,13 @@
ellipse bz 0 0 0 0 0 1 1 .5
convert bz bz
mkedge e bz
getanacurve c e ell 1.e-7
if {[isdraw c]} {
set log [dump c]
if { [regexp {Ellipse} $log ] != 1 } {
puts "Error: curve is not an ellipse"
}
} else {
puts "Error: required curve is not got"
}

15
tests/cr/base/A4 Normal file
View File

@ -0,0 +1,15 @@
beziercurve bz 3 0 0 0 .5 .5e-6 0 1 0 0
mkedge e1 bz 0 .3
mkedge e2 bz .3 0.7
mkedge e3 bz .7 1.
wire w e1 e2 e3
getanacurve c w lin 1.e-3
if {[isdraw c]} {
set log [dump c]
if { [regexp {Line} $log ] != 1 } {
puts "Error: curve is not a line"
}
} else {
puts "Error: required curve is not got"
}

15
tests/cr/base/A5 Normal file
View File

@ -0,0 +1,15 @@
circle bz 0 0 0 0 0 1 1
convert bz bz
mkedge e1 bz 0 1
mkedge e2 bz 1 2.5
mkedge e3 bz 2.5 6
wire w e1 e2 e3
getanacurve c w cir 1.e-7
if {[isdraw c]} {
set log [dump c]
if { [regexp {Circle} $log ] != 1 } {
puts "Error: curve is not a circle"
}
} else {
puts "Error: required curve is not got"
}

15
tests/cr/base/A6 Normal file
View File

@ -0,0 +1,15 @@
ellipse bz 0 0 0 0 0 1 1 .5
convert bz bz
mkedge e1 bz 0 1
mkedge e2 bz 1 2.5
mkedge e3 bz 2.5 6
wire w e1 e2 e3
getanacurve c w ell 1.e-7
if {[isdraw c]} {
set log [dump c]
if { [regexp {Ellipse} $log ] != 1 } {
puts "Error: curve is not an ellipse"
}
} else {
puts "Error: required curve is not got"
}

15
tests/cr/base/B1 Normal file
View File

@ -0,0 +1,15 @@
plane surf
trim surf surf -1 1 -1 1
convert surf surf
mkface f surf
getanasurf asurf f pln 1.e-7
if {[isdraw asurf]} {
set log [dump asurf]
if { [regexp {Plane} $log ] != 1 } {
puts "Error: surface is not a plane"
}
} else {
puts "Error: required surface is not got"
}

14
tests/cr/base/B2 Normal file
View File

@ -0,0 +1,14 @@
cylinder surf 1
trimv surf surf -1 1
convert surf surf
mkface f surf
getanasurf asurf f cyl 1.e-7
if {[isdraw asurf]} {
set log [dump asurf]
if { [regexp {CylindricalSurface} $log ] != 1 } {
puts "Error: surface is not a cylindrical surface"
}
} else {
puts "Error: required surface is not got"
}

13
tests/cr/base/B3 Normal file
View File

@ -0,0 +1,13 @@
cone surf 30 0
trimv surf surf -1 0
convert surf surf
mkface f surf
getanasurf asurf f con 1.e-7
if {[isdraw asurf]} {
set log [dump asurf]
if { [regexp {ConicalSurface} $log ] != 1 } {
puts "Error: surface is not a conical surface"
}
} else {
puts "Error: required surface is not got"
}

12
tests/cr/base/B4 Normal file
View File

@ -0,0 +1,12 @@
sphere surf 1
convert surf surf
mkface f surf
getanasurf asurf f sph 1.e-7
if {[isdraw asurf]} {
set log [dump asurf]
if { [regexp {SphericalSurface} $log ] != 1 } {
puts "Error: surface is not a spherical surface"
}
} else {
puts "Error: required surface is not got"
}

25
tests/cr/base/B5 Normal file
View File

@ -0,0 +1,25 @@
plane surf
trim surf1 surf -1 0 -1 0
convert surf1 surf1
mkface f1 surf1
trim surf2 surf -1 0 0 1
convert surf2 surf2
mkface f2 surf2
trim surf3 surf 0 1 0 1
convert surf3 surf3
mkface f3 surf3
trim surf4 surf 0 1 -1 0
convert surf4 surf4
mkface f4 surf4
sewing sh f1 f2 f3 f4
getanasurf asurf sh pln 1.e-7
if {[isdraw asurf]} {
set log [dump asurf]
if { [regexp {Plane} $log ] != 1 } {
puts "Error: surface is not a plane"
}
} else {
puts "Error: required surface is not got"
}

25
tests/cr/base/B6 Normal file
View File

@ -0,0 +1,25 @@
cylinder surf 1
trim surf1 surf 0 3 -1 0
convert surf1 surf1
mkface f1 surf1
trim surf2 surf 0 3 0 1
convert surf2 surf2
mkface f2 surf2
trim surf3 surf 3 6 0 1
convert surf3 surf3
mkface f3 surf3
trim surf4 surf 3 6 -1 0
convert surf4 surf4
mkface f4 surf4
sewing sh f1 f2 f3 f4
getanasurf asurf sh cyl 1.e-7
if {[isdraw asurf]} {
set log [dump asurf]
if { [regexp {CylindricalSurface} $log ] != 1 } {
puts "Error: surface is not a cylindrical surface"
}
} else {
puts "Error: required surface is not got"
}

25
tests/cr/base/B7 Normal file
View File

@ -0,0 +1,25 @@
cone surf 30 0
trim surf1 surf 0 3 0 1
convert surf1 surf1
mkface f1 surf1
trim surf2 surf 0 3 1 2
convert surf2 surf2
mkface f2 surf2
trim surf3 surf 3 6 1 2
convert surf3 surf3
mkface f3 surf3
trim surf4 surf 3 6 0 1
convert surf4 surf4
mkface f4 surf4
sewing sh f1 f2 f3 f4
getanasurf asurf sh con 1.e-7
if {[isdraw asurf]} {
set log [dump asurf]
if { [regexp {ConicalSurface} $log ] != 1 } {
puts "Error: surface is not a conical surface"
}
} else {
puts "Error: required surface is not got"
}

25
tests/cr/base/B8 Normal file
View File

@ -0,0 +1,25 @@
sphere surf 1
trim surf1 surf 0 3 -1.5 0
convert surf1 surf1
mkface f1 surf1
trim surf2 surf 0 3 0 1.5
convert surf2 surf2
mkface f2 surf2
trim surf3 surf 3 6 0 1.5
convert surf3 surf3
mkface f3 surf3
trim surf4 surf 3 6 -1.5 0
convert surf4 surf4
mkface f4 surf4
sewing sh f1 f2 f3 f4
getanasurf asurf sh sph 1.e-7
if {[isdraw asurf]} {
set log [dump asurf]
if { [regexp {SphericalSurface} $log ] != 1 } {
puts "Error: surface is not a spherical surface"
}
} else {
puts "Error: required surface is not got"
}

40
tests/cr/base/B9 Normal file
View File

@ -0,0 +1,40 @@
cylinder surf 1
trim surf1 surf 0 1 -1 1
convert surf1 surf1
mkface f1 surf1
trim surf2 surf 1 2 -1 1
convert surf2 surf2
mkface f2 surf2
trim surf3 surf 2 3 -1 1
convert surf3 surf3
mkface f3 surf3
trim surf4 surf 3 4 -1 1
convert surf4 surf4
mkface f4 surf4
sewing sh f1 f2 f3 f4
cylinder cyl 0 0 -2.5 1 0 0 3
trimv cyl1 cyl -2 2
mkface fcyl cyl1
nurbsconvert fcyl fcyl
bsection ss fcyl sh
explode ss e
shape w w
add ss_1 w
add ss_2 w
add ss_3 w
add ss_4 w
add ss_5 w
getanasurf asurf w cyl 1.e-7 cyl
if {[isdraw asurf]} {
set log [dump asurf]
if { [regexp {CylindricalSurface} $log ] != 1 } {
puts "Error: surface is not a cylindrical surface"
}
if { [regexp {Radius :3} $log ] != 1 } {
puts "Error: surface is not a sample surface"
}
} else {
puts "Error: required surface is not got"
}

14
tests/cr/begin Normal file
View File

@ -0,0 +1,14 @@
if { [array get Draw_Groups "TOPOLOGY Check commands"] == "" } {
pload TOPTEST
}
# To prevent loops limit to 5 minutes
cpulimit 300
if { [info exists imagedir] == 0 } {
set imagedir .
}
if { [info exists test_image ] == 0 } {
set test_image photo
}

3
tests/cr/end Normal file
View File

@ -0,0 +1,3 @@
# to end a test script
puts "TEST COMPLETED"

2
tests/cr/grids.list Normal file
View File

@ -0,0 +1,2 @@
001 base
002 approx