1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-08 18:40:55 +03:00
occt/src/DBRep/DBRep_DrawableShape.cxx
oan 7bd071edb1 0026106: BRepMesh - revision of data model
Removed tight connections between data structures, auxiliary tools and algorithms in order to create extensible solution, easy for maintenance and improvements;
Code is separated on several functional units responsible for specific operation for the sake of simplification of debugging and readability;
Introduced new data structures enabling possibility to manipulate discrete model of particular entity (edge, wire, face) in order to perform computations locally instead of processing an entire model.

The workflow of updated component can be divided on six parts:
* Creation of model data structure: source TopoDS_Shape passed to algorithm is analyzed and exploded on faces and edges. For each topological entity corresponding reflection is created in data model. Note that underlying algorithms use data model as input and access it via common interface which allows user to create custom data model with necessary dependencies between particular entities;
* Discretize edges 3D & 2D curves: 3D curve as well as associated set of 2D curves of each model edge is discretized in order to create coherent skeleton used as a base in faces meshing process. In case if some edge of source shape already contains polygonal data which suites specified parameters, it is extracted from shape and stored to the model as is. Each edge is processed separately, adjacency is not taken into account;
* Heal discrete model: source TopoDS_Shape can contain problems, such as open-wire or self-intersections, introduced during design, exchange or modification of model. In addition, some problems like self-intersections can be introduced by roughly discretized edges. This stage is responsible for analysis of discrete model in order to detect and repair faced problems or refuse model’s part for further processing in case if problem cannot be solved;
* Preprocess discrete model: defines actions specific for implemented approach to be performed before meshing of faces. By default, iterates over model faces and checks consistency of existing triangulations. Cleans topological faces and its adjacent edges from polygonal data in case of inconsistency or marks face of discrete model as not required for computation;
* Discretize faces: represents core part performing mesh generation for particular face based on 2D discrete data related to processing face. Caches polygonal data associated with face’s edges in data model for further processing and stores generated mesh to TopoDS_Face;
* Postprocess discrete model: defines actions specific for implemented approach to be performed after meshing of faces. By default, stores polygonal data obtained on previous stage to TopoDS_Edge objects of source model.

Component is now spread over IMeshData, IMeshTools, BRepMeshData and BRepMesh units.

<!break>

1. Extend "tricheck" DRAW-command in order to find degenerated triangles.

2. Class BRepMesh_FastDiscret::Parameters has been declared as deprecated.

3. NURBS range splitter: do not split intervals without necessity. Intervals are split only in case if it is impossible to compute normals directly on intervals.

4. Default value of IMeshTools_Parameters::MinSize has been changed. New value is equal to 0.1*Deflection.

5. Correction of test scripts:

1) perf mesh bug27119: requested deflection is increased from 1e-6 to 1e-5 to keep reasonable performance (but still reproducing original issue)
2) bugs mesh bug26692_1, 2: make snapshot of triangulation instead of wireframe (irrelevant)

Correction in upgrade guide.
2018-11-02 17:06:40 +03:00

1283 lines
36 KiB
C++

// Created on: 1991-07-04
// Created by: Christophe MARION
// Copyright (c) 1991-1999 Matra Datavision
// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <Adaptor3d_HCurve.hxx>
#include <BRep_Tool.hxx>
#include <BRepAdaptor_Curve.hxx>
#include <BRepAdaptor_Surface.hxx>
#include <BRepMesh_IncrementalMesh.hxx>
#include <BRepTools.hxx>
#include <DBRep_DrawableShape.hxx>
#include <DBRep_Edge.hxx>
#include <DBRep_Face.hxx>
#include <DBRep_HideData.hxx>
#include <DBRep_IsoBuilder.hxx>
#include <DBRep_ListIteratorOfListOfEdge.hxx>
#include <DBRep_ListIteratorOfListOfFace.hxx>
#include <DBRep_ListIteratorOfListOfHideData.hxx>
#include <Draw_Appli.hxx>
#include <Draw_Color.hxx>
#include <Draw_Display.hxx>
#include <Draw_Drawable3D.hxx>
#include <Geom_BSplineCurve.hxx>
#include <Geom_BSplineSurface.hxx>
#include <GeomAdaptor_HSurface.hxx>
#include <GeomAdaptor_Surface.hxx>
#include <gp_Lin2d.hxx>
#include <gp_Trsf.hxx>
#include <HLRBRep.hxx>
#include <Poly_Connect.hxx>
#include <Poly_Polygon3D.hxx>
#include <Poly_PolygonOnTriangulation.hxx>
#include <Poly_Triangulation.hxx>
#include <Precision.hxx>
#include <Standard_DomainError.hxx>
#include <Standard_Type.hxx>
#include <TColgp_HArray1OfPnt.hxx>
#include <TColStd_DataMapIteratorOfDataMapOfIntegerInteger.hxx>
#include <TColStd_DataMapOfIntegerInteger.hxx>
#include <TColStd_HArray1OfInteger.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Shape.hxx>
#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
#include <TopTools_ListOfShape.hxx>
IMPLEMENT_STANDARD_RTTIEXT(DBRep_DrawableShape,Draw_Drawable3D)
static Standard_Real IsoRatio = 1.001;
static Standard_Integer MaxPlotCount = 5; // To avoid huge recursive calls in
static Standard_Integer PlotCount = 0; // PlotEdge and PlotIso for cases of "bad"
// curves and surfaces
// Set PlotCount = 0 before first call of
// PlotEdge or PlotIso
static TopoDS_Shape pickshape;
static Standard_Real upick,vpick;
#ifdef _WIN32
extern Draw_Viewer dout;
#endif
//=======================================================================
//function : DBRep_DrawableShape
//purpose : constructor
//=======================================================================
DBRep_DrawableShape::DBRep_DrawableShape
(const TopoDS_Shape& aShape,
const Draw_Color& FreeCol,
const Draw_Color& ConnCol,
const Draw_Color& EdgeCol,
const Draw_Color& IsosCol,
const Standard_Real size,
const Standard_Integer nbisos,
const Standard_Integer discret) :
mySize(size),
myDiscret(discret),
myFreeCol(FreeCol),
myConnCol(ConnCol),
myEdgeCol(EdgeCol),
myIsosCol(IsosCol),
myNbIsos(nbisos),
myDispOr(Standard_False),
mytriangulations(Standard_False),
mypolygons(Standard_False),
myHLR(Standard_False),
myRg1(Standard_False),
myRgN(Standard_False),
myHid(Standard_False)
{
myShape = aShape;
}
//=======================================================================
//function : updateDisplayData
//purpose :
//=======================================================================
void DBRep_DrawableShape::updateDisplayData () const
{
myFaces.Clear();
myEdges.Clear();
if (myShape.IsNull())
return;
//==============================================================
// Process the faces
//==============================================================
TopExp_Explorer ExpFace;
TopLoc_Location l;
for (ExpFace.Init (myShape,TopAbs_FACE);
ExpFace.More();
ExpFace.Next()) {
TopoDS_Face TopologicalFace = TopoDS::Face (ExpFace.Current());
if(myNbIsos != 0) {
const Handle(Geom_Surface)& S =
BRep_Tool::Surface(TopologicalFace,l);
if (!S.IsNull()) {
TopologicalFace.Orientation (TopAbs_FORWARD) ;
DBRep_IsoBuilder IsoBuild (TopologicalFace, mySize, myNbIsos) ;
myFaces.Append(new DBRep_Face (TopologicalFace,
IsoBuild.NbDomains(),
myIsosCol)) ;
IsoBuild.LoadIsos (myFaces.Last()) ;
}
else myFaces.Append(new DBRep_Face(TopologicalFace,0, myEdgeCol));
}
else myFaces.Append(new DBRep_Face(TopologicalFace,0, myEdgeCol));
}
//==============================================================
// process a 3D edge
//==============================================================
TopTools_IndexedDataMapOfShapeListOfShape edgemap;
TopExp::MapShapesAndAncestors(myShape,TopAbs_EDGE,TopAbs_FACE,edgemap);
Standard_Integer iedge;
for (iedge = 1; iedge <= edgemap.Extent(); iedge++) {
const TopoDS_Edge& theEdge = TopoDS::Edge(edgemap.FindKey(iedge));
// skip degenerated edges
if (BRep_Tool::Degenerated(theEdge)) continue;
// compute the number of faces
Standard_Integer nbf = edgemap(iedge).Extent();
Draw_Color EdgeColor;
switch (nbf) {
case 0 :
EdgeColor = myEdgeCol; // isolated edge
break;
case 1 :
EdgeColor = myFreeCol; // edge in only one face
break;
default :
EdgeColor = myConnCol; // edge shared by at least two faces
}
myEdges.Append(new DBRep_Edge (theEdge,EdgeColor));
}
}
//=======================================================================
//function : ChangeNbIsos
//purpose : Changes the number of isoparametric curves in a shape.
//=======================================================================
void DBRep_DrawableShape::ChangeNbIsos (const Standard_Integer NbIsos)
{
myFaces.Clear();
myNbIsos = NbIsos ;
TopExp_Explorer ExpFace;
TopLoc_Location l;
for (ExpFace.Init (myShape, TopAbs_FACE);
ExpFace.More();
ExpFace.Next()) {
TopoDS_Face TopologicalFace = TopoDS::Face (ExpFace.Current());
const Handle(Geom_Surface)& S =
BRep_Tool::Surface(TopologicalFace,l);
if (myNbIsos != 0) {
if (!S.IsNull()) {
TopologicalFace.Orientation (TopAbs_FORWARD) ;
DBRep_IsoBuilder IsoBuild (TopologicalFace, mySize, myNbIsos) ;
myFaces.Append
(new DBRep_Face
(TopologicalFace, IsoBuild.NbDomains(), myIsosCol)) ;
IsoBuild.LoadIsos (myFaces.Last()) ;
}
else myFaces.Append(new DBRep_Face(TopologicalFace,0, myEdgeCol));
}
else myFaces.Append(new DBRep_Face(TopologicalFace,0, myEdgeCol));
}
}
//=======================================================================
// Function : NbIsos
// Purpose : Returns the number of isoparametric curves in a shape.
//=======================================================================
Standard_Integer DBRep_DrawableShape::NbIsos () const
{
return myNbIsos ;
}
//=======================================================================
// Function : Discret
// Purpose :
//=======================================================================
Standard_Integer DBRep_DrawableShape::Discret () const
{
return myDiscret ;
}
Standard_EXPORT Draw_Color DBRep_ColorOrientation (const TopAbs_Orientation Or);
static void PlotIso (Draw_Display& dis,
Handle(DBRep_Face)& F,
BRepAdaptor_Surface& S,
GeomAbs_IsoType T,
Standard_Real& U,
Standard_Real& V,
Standard_Real Step,
Standard_Boolean& halt)
{
++PlotCount;
gp_Pnt Pl, Pr, Pm;
if (T == GeomAbs_IsoU) {
S.D0(U, V, Pl);
S.D0(U, V + Step/2., Pm);
S.D0(U, V + Step, Pr);
} else {
S.D0(U, V, Pl);
S.D0(U + Step/2., V, Pm);
S.D0(U + Step, V, Pr);
}
if (PlotCount > MaxPlotCount) {
dis.DrawTo(Pr);
if (dis.HasPicked()) {
pickshape = F->Face();
upick = (T == GeomAbs_IsoU) ? U : U + Step;
vpick = (T == GeomAbs_IsoU) ? V + Step : V;
halt = Standard_True;
};
return;
}
if (Pm.Distance(Pl) + Pm.Distance(Pr) <= IsoRatio*Pl.Distance(Pr)) {
dis.DrawTo(Pr);
if (dis.HasPicked()) {
pickshape = F->Face();
upick = (T == GeomAbs_IsoU) ? U : U + Step;
vpick = (T == GeomAbs_IsoU) ? V + Step : V;
halt = Standard_True;
};
} else
if (T == GeomAbs_IsoU) {
PlotIso (dis, F, S, T, U, V, Step/2, halt);
Standard_Real aLocalV = V + Step/2 ;
PlotIso (dis, F, S, T, U, aLocalV , Step/2, halt);
} else {
PlotIso (dis, F, S, T, U, V, Step/2, halt);
Standard_Real aLocalU = U + Step/2 ;
PlotIso (dis, F, S, T, aLocalU , V, Step/2, halt);
}
}
static void PlotEdge (Draw_Display& dis,
Handle(DBRep_Edge)& E,
const Adaptor3d_Curve& C,
Standard_Real& f,
Standard_Real step,
Standard_Boolean& halt)
{
++PlotCount;
gp_Pnt Pl, Pr, Pm;
C.D0(f, Pl);
C.D0(f + step/2., Pm);
C.D0(f + step, Pr);
if (PlotCount > MaxPlotCount) {
dis.DrawTo(Pr);
if (dis.HasPicked()) {
pickshape = E->Edge();
upick = f + step;
vpick = 0;
halt = Standard_True;
}
return;
}
if (Pm.Distance(Pl) + Pm.Distance(Pr) <= IsoRatio*Pl.Distance(Pr)) {
dis.DrawTo(Pr);
if (dis.HasPicked()) {
pickshape = E->Edge();
upick = f + step;
vpick = 0;
halt = Standard_True;
};
} else {
PlotEdge (dis, E, C, f, step/2, halt);
Standard_Real aLocalF = f + step/2 ;
PlotEdge (dis, E, C, aLocalF , step/2, halt);
}
}
//=======================================================================
//function : DrawOn
//purpose :
//=======================================================================
void DBRep_DrawableShape::DrawOn(Draw_Display& dis) const
{
Standard_Boolean halt = Standard_False;
if (myShape.IsNull()) {
dis.SetColor(myConnCol);
dis.DrawString(gp_Pnt(0,0,0),"Null Shape");
return;
}
if (myFaces.IsEmpty() || myEdges.IsEmpty())
updateDisplayData();
// hidden lines
if (myHLR) {
DBRep_DrawableShape* p = (DBRep_DrawableShape*) this;
p->DisplayHiddenLines(dis);
return;
}
GeomAbs_IsoType T;
Standard_Real Par,T1,T2;
Standard_Real U1,U2,V1,V2,stepU=0.,stepV=0.;
// gp_Pnt P, P1;
gp_Pnt P;
Standard_Integer i,j;
// Faces
Handle(Poly_Triangulation) Tr;
TopLoc_Location aTempLoc;
TopLoc_Location loc;
DBRep_ListIteratorOfListOfFace itf(myFaces);
while (itf.More() && !halt) {
const Handle(DBRep_Face)& F = itf.Value();
dis.SetColor(F->Color());
Handle(Geom_Surface) aSurf = BRep_Tool::Surface(F->Face(), aTempLoc);
if (!aSurf.IsNull()) {
Standard_Boolean restriction = Standard_False;
if(aSurf->IsUPeriodic() || aSurf->IsVPeriodic()) {
Standard_Real SU1 = 0., SU2 = 0., SV1 = 0., SV2 = 0.;
Standard_Real FU1 = 0., FU2 = 0., FV1 = 0., FV2 = 0.;
aSurf->Bounds(SU1,SU2,SV1,SV2);
BRepTools::UVBounds (F->Face(),FU1,FU2,FV1,FV2);
if(aSurf->IsUPeriodic()) {
if(FU1 < SU1 || FU1 > SU2)
restriction = Standard_True;
if(!restriction && (FU2 < SU1 || FU2 > SU2))
restriction = Standard_True;
}
if(!restriction && aSurf->IsVPeriodic()) {
if(FV1 < SV1 || FV1 > SV2)
restriction = Standard_True;
if(!restriction && (FV2 < SV1 || FV2 > SV2))
restriction = Standard_True;
}
Standard_Boolean zeroS = (fabs(SU2-SU1) <= 1.e-9 || fabs(SV2-SV1) <= 1.e-9);
Standard_Boolean zeroF = (fabs(FU2-FU1) <= 1.e-9 || fabs(FV2-FV1) <= 1.e-9);
if(restriction && (zeroS || zeroF))
restriction = Standard_False;
if(restriction && (FU1 >= FU2 || FV1 >= FV2))
restriction = Standard_False;
if(restriction && (fabs(FU2-FU1) > 4.1e+100 || fabs(FV2-FV1) > 4.1e+100))
restriction = Standard_False;
}
BRepAdaptor_Surface S(F->Face(),restriction);
//BRepAdaptor_Surface S(F->Face(),Standard_False);
GeomAbs_SurfaceType SurfType = S.GetType();
// If the type of the surface is GeomAbs_SurfaceOfExtrusion or GeomAbs_SurfaceOfRevolution
#ifdef OCCT_DEBUG
GeomAbs_CurveType CurvType;
#else
GeomAbs_CurveType CurvType = GeomAbs_OtherCurve;
#endif
Standard_Integer N = F->NbIsos();
Standard_Integer Intrv, nbIntv;
Standard_Integer nbUIntv = S.NbUIntervals(GeomAbs_CN);
Standard_Integer nbVIntv = S.NbVIntervals(GeomAbs_CN);
TColStd_Array1OfReal TI(1,Max(nbUIntv, nbVIntv)+1);
for (i = 1; i <= N; i++) {
F->GetIso(i,T,Par,T1,T2);
if (T == GeomAbs_IsoU) {
S.VIntervals(TI, GeomAbs_CN);
V1 = Max(T1, TI(1));
V2 = Min(T2, TI(2));
U1 = Par;
U2 = Par;
stepU = 0;
nbIntv = nbVIntv;
}
else {
S.UIntervals(TI, GeomAbs_CN);
U1 = Max(T1, TI(1));
U2 = Min(T2, TI(2));
V1 = Par;
V2 = Par;
stepV = 0;
nbIntv = nbUIntv;
}
S.D0(U1,V1,P);
dis.MoveTo(P);
for (Intrv = 1; Intrv <= nbIntv; Intrv++) {
if (TI(Intrv) <= T1 && TI(Intrv + 1) <= T1)
continue;
if (TI(Intrv) >= T2 && TI(Intrv + 1) >= T2)
continue;
if (T == GeomAbs_IsoU) {
V1 = Max(T1, TI(Intrv));
V2 = Min(T2, TI(Intrv + 1));
stepV = (V2 - V1) / myDiscret;
}
else {
U1 = Max(T1, TI(Intrv));
U2 = Min(T2, TI(Intrv + 1));
stepU = (U2 - U1) / myDiscret;
}
switch (SurfType) {
//-------------GeomAbs_Plane---------------
case GeomAbs_Plane :
break;
//----GeomAbs_Cylinder GeomAbs_Cone------
case GeomAbs_Cylinder :
case GeomAbs_Cone :
if (T == GeomAbs_IsoV) {
for (j = 1; j < myDiscret; j++) {
U1 += stepU;
V1 += stepV;
S.D0(U1,V1,P);
dis.DrawTo(P);
if (dis.HasPicked()) {
pickshape = F->Face();
upick = U1;
vpick = V1;
halt = Standard_True;
}
}
}
break;
//---GeomAbs_Sphere GeomAbs_Torus--------
//GeomAbs_BezierSurface GeomAbs_BezierSurface
case GeomAbs_Sphere :
case GeomAbs_Torus :
case GeomAbs_OffsetSurface :
case GeomAbs_OtherSurface :
for (j = 1; j < myDiscret; j++) {
U1 += stepU;
V1 += stepV;
S.D0(U1,V1,P);
dis.DrawTo(P);
if (dis.HasPicked()) {
pickshape = F->Face();
upick = U1;
vpick = V1;
halt = Standard_True;
}
}
break;
//-------------GeomAbs_BSplineSurface------
case GeomAbs_BezierSurface :
case GeomAbs_BSplineSurface :
for (j = 1; j <= myDiscret/2; j++) {
Handle(DBRep_Face) aLocalFace = F;
PlotCount = 0;
PlotIso (dis, aLocalFace , S, T, U1, V1, (T == GeomAbs_IsoV) ? stepU*2. : stepV*2., halt);
U1 += stepU*2.;
V1 += stepV*2.;
}
break;
//-------------GeomAbs_SurfaceOfExtrusion--
//-------------GeomAbs_SurfaceOfRevolution-
case GeomAbs_SurfaceOfExtrusion :
case GeomAbs_SurfaceOfRevolution :
if ((T == GeomAbs_IsoV && SurfType == GeomAbs_SurfaceOfRevolution) ||
(T == GeomAbs_IsoU && SurfType == GeomAbs_SurfaceOfExtrusion)) {
if (SurfType == GeomAbs_SurfaceOfExtrusion) break;
for (j = 1; j < myDiscret; j++) {
U1 += stepU;
V1 += stepV;
S.D0(U1,V1,P);
dis.DrawTo(P);
if (dis.HasPicked()) {
pickshape = F->Face();
upick = U1;
vpick = V1;
halt = Standard_True;
}
}
} else {
CurvType = (S.BasisCurve())->GetType();
switch (CurvType) {
case GeomAbs_Line :
break;
case GeomAbs_Circle :
case GeomAbs_Ellipse :
for (j = 1; j < myDiscret; j++) {
U1 += stepU;
V1 += stepV;
S.D0(U1,V1,P);
dis.DrawTo(P);
if (dis.HasPicked()) {
pickshape = F->Face();
upick = U1;
vpick = V1;
halt = Standard_True;
}
}
break;
case GeomAbs_Parabola :
case GeomAbs_Hyperbola :
case GeomAbs_BezierCurve :
case GeomAbs_BSplineCurve :
case GeomAbs_OffsetCurve :
case GeomAbs_OtherCurve :
for (j = 1; j <= myDiscret/2; j++) {
Handle(DBRep_Face) aLocalFace = F;
PlotCount = 0;
PlotIso (dis, aLocalFace, S, T, U1, V1,
(T == GeomAbs_IsoV) ? stepU*2. : stepV*2., halt);
U1 += stepU*2.;
V1 += stepV*2.;
}
break;
}
}
}
}
S.D0(U2,V2,P);
dis.DrawTo(P);
if (dis.HasPicked()) {
pickshape = F->Face();
upick = U2;
vpick = V2;
halt = Standard_True;
}
}
}
//=====================================
// trace des eventuelles triangulations.
//=====================================
if (aSurf.IsNull() || mytriangulations) {
Tr = BRep_Tool::Triangulation(F->Face(), loc);
if (!Tr.IsNull()) {
display(Tr, loc.Transformation(), dis);
}
}
itf.Next();
}
// Edges
DBRep_ListIteratorOfListOfEdge ite(myEdges);
while (ite.More() && !halt) {
const Handle(DBRep_Edge)& E = ite.Value();
if(myDispOr)
dis.SetColor(DBRep_ColorOrientation(E->Edge().Orientation()));
else
dis.SetColor(E->Color());
// display geometrical curve if exists.
Standard_Boolean isgeom = BRep_Tool::IsGeometric(E->Edge());
Standard_Real aCheckU1, aCheckU2;
if (isgeom) {
// check the range (to report bad edges)
BRep_Tool::Range(E->Edge(), aCheckU1, aCheckU2);
if (aCheckU2 < aCheckU1) {
// bad orientation
cout << "DBRep_DrawableShape : Bad parameters on edge."<<endl;
BRepTools::Dump(E->Edge(),cout);
ite.Next();
continue;
}
if (BRep_Tool::Degenerated(E->Edge())) {
ite.Next();
continue;
}
BRepAdaptor_Curve C(E->Edge());
Standard_Real f = C.FirstParameter();
Standard_Real l = C.LastParameter();
if (Precision::IsNegativeInfinite(f)) {
if (Precision::IsPositiveInfinite(l)) {
f = -mySize;
l = mySize;
}
else {
f = l - mySize;
}
}
else if (Precision::IsPositiveInfinite(l)) {
l = f + mySize;
}
Handle(Adaptor3d_HCurve) HC = C.Trim(f, l, Precision::Confusion());
GeomAbs_CurveType CurvType = HC->GetType();
Standard_Integer intrv, nbintv = HC->NbIntervals(GeomAbs_CN);
TColStd_Array1OfReal TI(1,nbintv+1);
HC->Intervals(TI,GeomAbs_CN);
HC->D0(HC->FirstParameter(), P);
dis.MoveTo(P);
for (intrv = 1; intrv <= nbintv; intrv++) {
Standard_Real t = TI(intrv);
Standard_Real step = (TI(intrv+1) - t) / myDiscret;
switch (CurvType) {
case GeomAbs_Line :
break;
case GeomAbs_Circle :
case GeomAbs_Ellipse :
for (j = 1; j < myDiscret; j++) {
t += step;
C.D0(t,P);
dis.DrawTo(P);
if (dis.HasPicked()) {
pickshape = E->Edge();
upick = t;
vpick = 0;
halt = Standard_True;
}
}
break;
case GeomAbs_Parabola :
case GeomAbs_Hyperbola :
case GeomAbs_BezierCurve :
case GeomAbs_BSplineCurve :
case GeomAbs_OffsetCurve :
case GeomAbs_OtherCurve :
for (j = 1; j <= myDiscret/2; j++) {
Handle(DBRep_Edge) aLocaLEdge(E);
PlotCount = 0;
PlotEdge (dis, aLocaLEdge , HC->Curve(), t, step*2., halt);
t += step*2.;
}
break;
}
}
C.D0(HC->LastParameter(),P);
dis.DrawTo(P);
if (dis.HasPicked()) {
pickshape = E->Edge();
upick = l;
vpick = 0;
halt = Standard_True;
}
if (myDispOr) {
// display an arrow at the end
gp_Pnt aPnt;
gp_Vec V;
C.D1(l, aPnt,V);
gp_Pnt2d p1,p2;
dis.Project(aPnt,p1);
aPnt.Translate(V);
dis.Project(aPnt,p2);
gp_Vec2d v(p1,p2);
if (v.Magnitude() > gp::Resolution()) {
Standard_Real L = 20 / dis.Zoom();
Standard_Real H = 10 / dis.Zoom();
gp_Dir2d d(v);
p2.SetCoord(p1.X() - L*d.X() - H*d.Y(), p1.Y() - L*d.Y() + H*d.X());
dis.MoveTo(p2);
p2.SetCoord(p1.X() - L*d.X() + H*d.Y(), p1.Y() - L*d.Y() - H*d.X());
dis.DrawTo(p1);
dis.DrawTo(p2);
}
// gp_Vec tang;
// C.D1(l,P,tang);
}
}
//======================================
// trace des representations polygonales:
//======================================
if (!isgeom || mypolygons) {
// Polygones 3d:
Handle(Poly_Polygon3D) Polyg = BRep_Tool::Polygon3D(E->Edge(), loc);
if (!Polyg.IsNull()) {
const TColgp_Array1OfPnt& Points = Polyg->Nodes();
Standard_Integer po;
for (po = Points.Lower()+1; po <= Points.Upper(); po++) {
dis.Draw((Points.Value(po-1)).Transformed(loc),
(Points.Value(po)).Transformed(loc));
if (dis.HasPicked()) {
pickshape = E->Edge();
upick = 0;
vpick = 0;
halt = Standard_True;
}
}
}
else {
// Polygone sur triangulation:
Handle(Poly_Triangulation) PolyTr;
Handle(Poly_PolygonOnTriangulation) Poly;
BRep_Tool::PolygonOnTriangulation(E->Edge(), Poly, PolyTr, loc);
if (!Poly.IsNull()) {
const TColStd_Array1OfInteger& Indices = Poly->Nodes();
const TColgp_Array1OfPnt& Nodes = PolyTr->Nodes();
for (i=Indices.Lower()+1; i<=Indices.Upper(); i++) {
dis.Draw(Nodes(Indices(i-1)).Transformed(loc),
Nodes(Indices(i)).Transformed(loc));
if (dis.HasPicked()) {
pickshape = E->Edge();
upick = 0;
vpick = 0;
halt = Standard_True;
}
}
}
}
}
ite.Next();
}
//Vertices
TopExp_Explorer exv;
dis.SetColor(myConnCol);
for (exv.Init(myShape,TopAbs_VERTEX,TopAbs_EDGE);
exv.More() && !halt;
exv.Next()){
if (myDispOr)
dis.SetColor(DBRep_ColorOrientation(exv.Current().Orientation()));
dis.DrawMarker(BRep_Tool::Pnt(TopoDS::Vertex(exv.Current())),
Draw_Losange);
if (dis.HasPicked()) {
pickshape = exv.Current();
upick = 0;
vpick = 0;
halt = Standard_True;
}
}
}
//=======================================================================
//function : DisplayHiddenLines
//purpose :
//=======================================================================
void DBRep_DrawableShape::DisplayHiddenLines(Draw_Display& dis)
{
Standard_Integer id = dis.ViewId();
// get the projection
gp_Trsf T;
dout.GetTrsf(id,T);
Standard_Real focal = -1;
if (!strcmp(dout.GetType(id),"PERS")) focal = dout.Focal(id);
Standard_Real Ang,Def;
HLRBRep::PolyHLRAngleAndDeflection(myAng,Ang,Def);
IMeshTools_Parameters aMeshParams;
aMeshParams.Relative = Standard_True;
aMeshParams.Deflection = Def;
aMeshParams.Angle = Ang;
BRepMesh_IncrementalMesh MESH(myShape, aMeshParams);
Standard_Boolean recompute = Standard_True;
// find if the view must be recomputed
DBRep_ListIteratorOfListOfHideData it(myHidData);
while (it.More()) {
if (it.Value().ViewId() == id) {
// we have the view
// but did we rotate it
Standard_Real ang = it.Value().Angle();
recompute = !it.Value().IsSame(T,focal) || myAng != ang;
if (recompute)
myHidData.Remove(it);
else {
it.Value().DrawOn(dis,myRg1,myRgN,myHid,
myConnCol,myIsosCol);
if (dis.HasPicked()) {
pickshape = it.Value().LastPick();
upick = 0;
vpick = 0;
}
}
break;
}
it.Next();
}
// recompute the hidden lines and display them
if (recompute) {
DBRep_HideData theData;
myHidData.Append(theData);
myHidData.Last().Set(id,T,focal,myShape,myAng);
myHidData.Last().DrawOn(dis,myRg1,myRgN,myHid,
myConnCol,myIsosCol);
if (dis.HasPicked()) {
pickshape = myHidData.Last().LastPick();
upick = 0;
vpick = 0;
}
}
}
//=======================================================================
//function : Shape
//purpose :
//=======================================================================
TopoDS_Shape DBRep_DrawableShape::Shape()const
{
return myShape;
}
//=======================================================================
//function : Copy
//purpose :
//=======================================================================
Handle(Draw_Drawable3D) DBRep_DrawableShape::Copy()const
{
Handle(DBRep_DrawableShape) D =
new DBRep_DrawableShape(myShape,
myFreeCol,
myConnCol,
myEdgeCol,
myIsosCol,
mySize,
myNbIsos,
myDiscret);
return D;
}
//=======================================================================
//function : DisplayOrientation
//purpose :
//=======================================================================
void DBRep_DrawableShape::DisplayOrientation(const Standard_Boolean D)
{
myDispOr = D;
}
//=======================================================================
//function : DisplayTriangulation
//purpose :
//=======================================================================
void DBRep_DrawableShape::DisplayTriangulation(const Standard_Boolean D)
{
mytriangulations = D;
}
//=======================================================================
//function : DisplayPolygons
//purpose :
//=======================================================================
void DBRep_DrawableShape::DisplayPolygons(const Standard_Boolean D)
{
mypolygons = D;
}
//=======================================================================
//function : DisplayHLR
//purpose :
//=======================================================================
void DBRep_DrawableShape::DisplayHLR(const Standard_Boolean withHLR,
const Standard_Boolean withRg1,
const Standard_Boolean withRgN,
const Standard_Boolean withHid,
const Standard_Real ang)
{
myHLR = withHLR;
myRg1 = withRg1;
myRgN = withRgN;
myHid = withHid;
myAng = ang;
}
//=======================================================================
//function : DisplayTriangulation
//purpose :
//=======================================================================
Standard_Boolean DBRep_DrawableShape::DisplayTriangulation() const
{
return mytriangulations;
}
//=======================================================================
//function : DisplayPolygons
//purpose :
//=======================================================================
Standard_Boolean DBRep_DrawableShape::DisplayPolygons()const
{
return mypolygons;
}
//=======================================================================
//function : GetDisplayHLR
//purpose :
//=======================================================================
void DBRep_DrawableShape::GetDisplayHLR(Standard_Boolean& withHLR,
Standard_Boolean& withRg1,
Standard_Boolean& withRgN,
Standard_Boolean& withHid,
Standard_Real& ang) const
{
withHLR = myHLR;
withRg1 = myRg1;
withRgN = myRgN;
withHid = myHid;
ang = myAng;
}
//=======================================================================
//function : Dump
//purpose :
//=======================================================================
void DBRep_DrawableShape::Dump(Standard_OStream& S)const
{
BRepTools::Dump(myShape,S);
}
//=======================================================================
//function : Whatis
//purpose :
//=======================================================================
void DBRep_DrawableShape::Whatis(Draw_Interpretor& s)const
{
if (myShape.IsNull())
{
return;
}
s << "shape " << TopAbs::ShapeTypeToString (myShape.ShapeType())
<< " " << TopAbs::ShapeOrientationToString(myShape.Orientation());
if (myShape.Free()) s <<" Free";
if (myShape.Modified()) s <<" Modified";
if (myShape.Orientable()) s <<" Orientable";
if (myShape.Closed()) s <<" Closed";
if (myShape.Infinite()) s <<" Infinite";
if (myShape.Convex()) s <<" Convex";
}
//=======================================================================
//function : LastPick
//purpose :
//=======================================================================
void DBRep_DrawableShape::LastPick(TopoDS_Shape& s,
Standard_Real& u, Standard_Real& v)
{
s = pickshape;
u = upick;
v = vpick;
}
//=======================================================================
//function : display
//purpose :
//=======================================================================
void DBRep_DrawableShape::display(const Handle(Poly_Triangulation)& T,
const gp_Trsf& tr,
Draw_Display& dis) const
{
// Build the connect tool
Poly_Connect pc(T);
Standard_Integer i,j, nFree, nbTriangles = T->NbTriangles();
Standard_Integer t[3];
// count the free edges
nFree = 0;
for (i = 1; i <= nbTriangles; i++) {
pc.Triangles(i,t[0],t[1],t[2]);
for (j = 0; j < 3; j++)
if (t[j] == 0) nFree++;
}
// allocate the arrays
TColStd_Array1OfInteger Free (1, Max (1, 2 * nFree));
NCollection_Vector< NCollection_Vec2<Standard_Integer> > anInternal;
Standard_Integer fr = 1;
const Poly_Array1OfTriangle& triangles = T->Triangles();
Standard_Integer n[3];
for (i = 1; i <= nbTriangles; i++) {
pc.Triangles(i,t[0],t[1],t[2]);
triangles(i).Get(n[0],n[1],n[2]);
for (j = 0; j < 3; j++) {
Standard_Integer k = (j+1) % 3;
if (t[j] == 0) {
Free(fr) = n[j];
Free(fr+1) = n[k];
fr += 2;
}
// internal edge if this triangle has a lower index than the adjacent
else if (i < t[j]) {
anInternal.Append (NCollection_Vec2<Standard_Integer> (n[j], n[k]));
}
}
}
// Display the edges
const TColgp_Array1OfPnt& Nodes = T->Nodes();
// cout<<"nb nodes = "<<Nodes.Length()<<endl;
// free edges
Standard_Integer nn;
dis.SetColor(Draw_rouge);
nn = Free.Length() / 2;
for (i = 1; i <= nn; i++) {
dis.Draw(Nodes(Free(2*i-1)).Transformed(tr),
Nodes(Free(2*i)).Transformed(tr));
}
// internal edges
dis.SetColor(Draw_bleu);
for (NCollection_Vector< NCollection_Vec2<Standard_Integer> >::Iterator anInterIter (anInternal); anInterIter.More(); anInterIter.Next())
{
const Standard_Integer n1 = anInterIter.Value()[0];
const Standard_Integer n2 = anInterIter.Value()[1];
dis.Draw (Nodes(n1).Transformed(tr), Nodes(n2).Transformed(tr));
}
}
//=======================================================================
//function : addMeshNormals
//purpose :
//=======================================================================
Standard_Boolean DBRep_DrawableShape::addMeshNormals (NCollection_Vector<std::pair<gp_Pnt, gp_Pnt> >& theNormals,
const TopoDS_Face& theFace,
const Standard_Real theLength)
{
TopLoc_Location aLoc;
const Handle(Poly_Triangulation)& aTriangulation = BRep_Tool::Triangulation (theFace, aLoc);
const Standard_Boolean hasNormals = aTriangulation->HasNormals();
if (aTriangulation.IsNull()
|| (!hasNormals && !aTriangulation->HasUVNodes()))
{
return Standard_False;
}
const TColgp_Array1OfPnt& aNodes = aTriangulation->Nodes();
BRepAdaptor_Surface aSurface (theFace);
for (Standard_Integer aNodeIter = aNodes.Lower(); aNodeIter <= aNodes.Upper(); ++aNodeIter)
{
gp_Pnt aP1 = aNodes (aNodeIter);
if (!aLoc.IsIdentity())
{
aP1.Transform (aLoc.Transformation());
}
gp_Vec aNormal;
if (hasNormals)
{
aNormal = aTriangulation->Normal (aNodeIter);
}
else
{
const gp_Pnt2d& aUVNode = aTriangulation->UVNode (aNodeIter);
gp_Pnt aDummyPnt;
gp_Vec aV1, aV2;
aSurface.D1 (aUVNode.X(), aUVNode.Y(), aDummyPnt, aV1, aV2);
aNormal = aV1.Crossed (aV2);
}
const Standard_Real aNormalLen = aNormal.Magnitude();
if (aNormalLen > 1.e-10)
{
aNormal.Multiply (theLength / aNormalLen);
}
else
{
aNormal.SetCoord (aNormalLen / 2.0, 0.0, 0.0);
std::cout << "Null normal at node X = " << aP1.X() << ", Y = " << aP1.Y() << ", Z = " << aP1.Z() << "\n";
}
const gp_Pnt aP2 = aP1.Translated (aNormal);
theNormals.Append (std::pair<gp_Pnt, gp_Pnt> (aP1, aP2));
}
return Standard_True;
}
//=======================================================================
//function : addMeshNormals
//purpose :
//=======================================================================
void DBRep_DrawableShape::addMeshNormals (NCollection_DataMap<TopoDS_Face, NCollection_Vector<std::pair<gp_Pnt, gp_Pnt> > > & theNormals,
const TopoDS_Shape& theShape,
const Standard_Real theLength)
{
TopLoc_Location aLoc;
for (TopExp_Explorer aFaceIt(theShape, TopAbs_FACE); aFaceIt.More(); aFaceIt.Next())
{
const TopoDS_Face& aFace = TopoDS::Face(aFaceIt.Current());
NCollection_Vector<std::pair<gp_Pnt, gp_Pnt> >* aFaceNormals = theNormals.ChangeSeek(aFace);
if (aFaceNormals == NULL)
{
aFaceNormals = theNormals.Bound(aFace, NCollection_Vector<std::pair<gp_Pnt, gp_Pnt> >());
}
addMeshNormals (*aFaceNormals, aFace, theLength);
}
}
//=======================================================================
//function : addSurfaceNormals
//purpose :
//=======================================================================
Standard_Boolean DBRep_DrawableShape::addSurfaceNormals (NCollection_Vector<std::pair<gp_Pnt, gp_Pnt> >& theNormals,
const TopoDS_Face& theFace,
const Standard_Real theLength,
const Standard_Integer theNbAlongU,
const Standard_Integer theNbAlongV)
{
{
TopLoc_Location aLoc;
const Handle(Geom_Surface)& aSurface = BRep_Tool::Surface (theFace, aLoc);
if (aSurface.IsNull())
{
return Standard_False;
}
}
Standard_Real aUmin = 0.0, aVmin = 0.0, aUmax = 0.0, aVmax = 0.0;
BRepTools::UVBounds (theFace, aUmin, aUmax, aVmin, aVmax);
const Standard_Boolean isUseMidU = (theNbAlongU == 1);
const Standard_Boolean isUseMidV = (theNbAlongV == 1);
const Standard_Real aDU = (aUmax - aUmin) / (isUseMidU ? 2 : (theNbAlongU - 1));
const Standard_Real aDV = (aVmax - aVmin) / (isUseMidV ? 2 : (theNbAlongV - 1));
BRepAdaptor_Surface aSurface (theFace);
for (Standard_Integer aUIter = 0; aUIter < theNbAlongU; ++aUIter)
{
const Standard_Real aU = aUmin + (isUseMidU ? 1 : aUIter) * aDU;
for (Standard_Integer aVIter = 0; aVIter < theNbAlongV; ++aVIter)
{
const Standard_Real aV = aVmin + (isUseMidV ? 1 : aVIter) * aDV;
gp_Pnt aP1;
gp_Vec aV1, aV2;
aSurface.D1 (aU, aV, aP1, aV1, aV2);
gp_Vec aVec = aV1.Crossed (aV2);
Standard_Real aNormalLen = aVec.Magnitude();
if (aNormalLen > 1.e-10)
{
aVec.Multiply (theLength / aNormalLen);
}
else
{
aVec.SetCoord (aNormalLen / 2.0, 0.0, 0.0);
std::cout << "Null normal at U = " << aU << ", V = " << aV << "\n";
}
const gp_Pnt aP2 = aP1.Translated(aVec);
theNormals.Append (std::pair<gp_Pnt, gp_Pnt> (aP1, aP2));
}
}
return Standard_True;
}
//=======================================================================
//function : addSurfaceNormals
//purpose :
//=======================================================================
void DBRep_DrawableShape::addSurfaceNormals (NCollection_DataMap<TopoDS_Face, NCollection_Vector<std::pair<gp_Pnt, gp_Pnt> > >& theNormals,
const TopoDS_Shape& theShape,
const Standard_Real theLength,
const Standard_Integer theNbAlongU,
const Standard_Integer theNbAlongV)
{
for (TopExp_Explorer aFaceIt (theShape, TopAbs_FACE); aFaceIt.More(); aFaceIt.Next())
{
const TopoDS_Face& aFace = TopoDS::Face (aFaceIt.Current());
NCollection_Vector<std::pair<gp_Pnt, gp_Pnt> >* aFaceNormals = theNormals.ChangeSeek (aFace);
if (aFaceNormals == NULL)
{
aFaceNormals = theNormals.Bound (aFace, NCollection_Vector<std::pair<gp_Pnt, gp_Pnt> >());
}
addSurfaceNormals (*aFaceNormals, aFace, theLength, theNbAlongU, theNbAlongV);
}
}