From 6a2c30cdbf7b816733f84b8a7cddec69dde824cf Mon Sep 17 00:00:00 2001 From: oan Date: Mon, 16 Jan 2023 14:57:12 +0300 Subject: [PATCH] Update BRepMesh component according to OCCT's 7.4.0 Includes #26106 patch --- adm/UDLIST | 3 + src/AIS/AIS_RubberBand.cxx | 8 +- src/BRepMesh/BRepMesh.hxx | 147 -- src/BRepMesh/BRepMesh_BaseMeshAlgo.cxx | 316 ++++ src/BRepMesh/BRepMesh_BaseMeshAlgo.hxx | 143 ++ .../BRepMesh_BoundaryParamsRangeSplitter.hxx | 54 + src/BRepMesh/BRepMesh_CircleInspector.hxx | 55 +- src/BRepMesh/BRepMesh_CircleTool.cxx | 76 +- src/BRepMesh/BRepMesh_CircleTool.hxx | 14 +- src/BRepMesh/BRepMesh_Classifier.cxx | 74 +- src/BRepMesh/BRepMesh_Classifier.hxx | 52 +- src/BRepMesh/BRepMesh_ConeRangeSplitter.cxx | 80 + src/BRepMesh/BRepMesh_ConeRangeSplitter.hxx | 50 + .../BRepMesh_ConstrainedBaseMeshAlgo.hxx | 60 + src/BRepMesh/BRepMesh_Context.cxx | 45 + ...epMesh_Status.hxx => BRepMesh_Context.hxx} | 32 +- src/BRepMesh/BRepMesh_CurveTessellator.cxx | 342 ++++ src/BRepMesh/BRepMesh_CurveTessellator.hxx | 110 ++ src/BRepMesh/BRepMesh_CustomBaseMeshAlgo.hxx | 70 + .../BRepMesh_CustomDelaunayBaseMeshAlgo.hxx | 53 + .../BRepMesh_CylinderRangeSplitter.cxx | 98 + .../BRepMesh_CylinderRangeSplitter.hxx | 59 + .../BRepMesh_DataStructureOfDelaun.cxx | 91 +- .../BRepMesh_DataStructureOfDelaun.hxx | 53 +- .../BRepMesh_DefaultRangeSplitter.cxx | 252 +++ .../BRepMesh_DefaultRangeSplitter.hxx | 150 ++ src/BRepMesh/BRepMesh_Deflection.cxx | 162 ++ src/BRepMesh/BRepMesh_Deflection.hxx | 64 + src/BRepMesh/BRepMesh_Delaun.cxx | 666 +++---- src/BRepMesh/BRepMesh_Delaun.hxx | 219 +-- .../BRepMesh_DelaunayBaseMeshAlgo.cxx | 57 + .../BRepMesh_DelaunayBaseMeshAlgo.hxx | 46 + ...Mesh_DelaunayDeflectionControlMeshAlgo.hxx | 452 +++++ ...BRepMesh_DelaunayNodeInsertionMeshAlgo.hxx | 159 ++ src/BRepMesh/BRepMesh_DiscretFactory.hxx | 4 +- src/BRepMesh/BRepMesh_DiscretRoot.hxx | 2 +- src/BRepMesh/BRepMesh_Edge.hxx | 11 +- src/BRepMesh/BRepMesh_EdgeDiscret.cxx | 333 ++++ src/BRepMesh/BRepMesh_EdgeDiscret.hxx | 98 + .../BRepMesh_EdgeParameterProvider.cxx | 89 - .../BRepMesh_EdgeParameterProvider.hxx | 115 +- .../BRepMesh_EdgeTessellationExtractor.cxx | 64 +- .../BRepMesh_EdgeTessellationExtractor.hxx | 68 +- src/BRepMesh/BRepMesh_EdgeTessellator.cxx | 264 --- src/BRepMesh/BRepMesh_EdgeTessellator.hxx | 93 - src/BRepMesh/BRepMesh_FaceAttribute.cxx | 257 --- src/BRepMesh/BRepMesh_FaceAttribute.hxx | 405 ----- src/BRepMesh/BRepMesh_FaceChecker.cxx | 312 ++++ src/BRepMesh/BRepMesh_FaceChecker.hxx | 122 ++ src/BRepMesh/BRepMesh_FaceDiscret.cxx | 95 + src/BRepMesh/BRepMesh_FaceDiscret.hxx | 65 + src/BRepMesh/BRepMesh_FastDiscret.cxx | 989 ---------- src/BRepMesh/BRepMesh_FastDiscret.hxx | 353 +--- src/BRepMesh/BRepMesh_FastDiscretFace.cxx | 1585 ----------------- src/BRepMesh/BRepMesh_FastDiscretFace.hxx | 201 --- src/BRepMesh/BRepMesh_GeomTool.cxx | 194 +- src/BRepMesh/BRepMesh_GeomTool.hxx | 74 +- src/BRepMesh/BRepMesh_IEdgeTool.cxx | 20 - src/BRepMesh/BRepMesh_IncrementalMesh.cxx | 602 +------ src/BRepMesh/BRepMesh_IncrementalMesh.hxx | 144 +- src/BRepMesh/BRepMesh_MeshAlgoFactory.cxx | 105 ++ src/BRepMesh/BRepMesh_MeshAlgoFactory.hxx | 44 + src/BRepMesh/BRepMesh_MeshTool.cxx | 368 ++++ src/BRepMesh/BRepMesh_MeshTool.hxx | 235 +++ src/BRepMesh/BRepMesh_ModelBuilder.cxx | 84 + src/BRepMesh/BRepMesh_ModelBuilder.hxx | 50 + src/BRepMesh/BRepMesh_ModelHealer.cxx | 499 ++++++ src/BRepMesh/BRepMesh_ModelHealer.hxx | 185 ++ src/BRepMesh/BRepMesh_ModelPostProcessor.cxx | 192 ++ src/BRepMesh/BRepMesh_ModelPostProcessor.hxx | 45 + src/BRepMesh/BRepMesh_ModelPreProcessor.cxx | 307 ++++ src/BRepMesh/BRepMesh_ModelPreProcessor.hxx | 46 + src/BRepMesh/BRepMesh_NURBSRangeSplitter.cxx | 583 ++++++ src/BRepMesh/BRepMesh_NURBSRangeSplitter.hxx | 91 + .../BRepMesh_NodeInsertionMeshAlgo.hxx | 237 +++ src/BRepMesh/BRepMesh_OrientedEdge.hxx | 25 +- src/BRepMesh/BRepMesh_PairOfPolygon.hxx | 81 - ...epMesh_SelectorOfDataStructureOfDelaun.cxx | 20 +- ...epMesh_SelectorOfDataStructureOfDelaun.hxx | 30 +- src/BRepMesh/BRepMesh_ShapeTool.cxx | 350 ++-- src/BRepMesh/BRepMesh_ShapeTool.hxx | 159 +- src/BRepMesh/BRepMesh_ShapeVisitor.cxx | 151 ++ src/BRepMesh/BRepMesh_ShapeVisitor.hxx | 67 + src/BRepMesh/BRepMesh_SphereRangeSplitter.cxx | 59 + src/BRepMesh/BRepMesh_SphereRangeSplitter.hxx | 56 + src/BRepMesh/BRepMesh_TorusRangeSplitter.cxx | 218 +++ src/BRepMesh/BRepMesh_TorusRangeSplitter.hxx | 57 + src/BRepMesh/BRepMesh_Triangle.hxx | 85 +- .../BRepMesh_UVParamRangeSplitter.hxx | 81 + src/BRepMesh/BRepMesh_Vertex.hxx | 25 +- src/BRepMesh/BRepMesh_VertexInspector.hxx | 41 +- src/BRepMesh/BRepMesh_VertexTool.cxx | 16 +- src/BRepMesh/BRepMesh_VertexTool.hxx | 33 +- src/BRepMesh/BRepMesh_WireChecker.cxx | 410 ----- src/BRepMesh/BRepMesh_WireChecker.hxx | 142 -- .../BRepMesh_WireInterferenceChecker.cxx | 134 -- .../BRepMesh_WireInterferenceChecker.hxx | 67 - src/BRepMesh/FILES | 67 +- src/BRepMeshData/BRepMeshData_Curve.cxx | 126 ++ src/BRepMeshData/BRepMeshData_Curve.hxx | 76 + src/BRepMeshData/BRepMeshData_Edge.cxx | 102 ++ src/BRepMeshData/BRepMeshData_Edge.hxx | 65 + src/BRepMeshData/BRepMeshData_Face.cxx | 72 + src/BRepMeshData/BRepMeshData_Face.hxx | 58 + src/BRepMeshData/BRepMeshData_Model.cxx | 102 ++ src/BRepMeshData/BRepMeshData_Model.hxx | 81 + src/BRepMeshData/BRepMeshData_PCurve.cxx | 155 ++ src/BRepMeshData/BRepMeshData_PCurve.hxx | 82 + src/BRepMeshData/BRepMeshData_Wire.cxx | 86 + src/BRepMeshData/BRepMeshData_Wire.hxx | 63 + src/BRepMeshData/FILES | 12 + src/DBRep/DBRep_DrawableShape.cxx | 2 +- src/IMeshData/FILES | 13 + src/IMeshData/IMeshData_Curve.hxx | 62 + src/IMeshData/IMeshData_Edge.hxx | 167 ++ src/IMeshData/IMeshData_Face.hxx | 93 + src/IMeshData/IMeshData_Model.hxx | 76 + src/IMeshData/IMeshData_PCurve.hxx | 99 + src/IMeshData/IMeshData_ParametersList.hxx | 54 + .../IMeshData_ParametersListArrayAdaptor.hxx | 70 + src/IMeshData/IMeshData_Shape.hxx | 66 + src/IMeshData/IMeshData_Status.hxx | 33 + src/IMeshData/IMeshData_StatusOwner.hxx | 76 + src/IMeshData/IMeshData_TessellatedShape.hxx | 67 + src/IMeshData/IMeshData_Types.hxx | 170 ++ src/IMeshData/IMeshData_Wire.hxx | 74 + src/IMeshTools/FILES | 12 + src/IMeshTools/IMeshTools_Context.hxx | 240 +++ .../IMeshTools_CurveTessellator.hxx} | 45 +- src/IMeshTools/IMeshTools_MeshAlgo.hxx | 50 + src/IMeshTools/IMeshTools_MeshAlgoFactory.hxx | 52 + src/IMeshTools/IMeshTools_MeshBuilder.cxx | 118 ++ src/IMeshTools/IMeshTools_MeshBuilder.hxx | 74 + src/IMeshTools/IMeshTools_ModelAlgo.hxx | 69 + src/IMeshTools/IMeshTools_ModelBuilder.hxx | 80 + src/IMeshTools/IMeshTools_Parameters.hxx | 88 + src/IMeshTools/IMeshTools_ShapeExplorer.cxx | 113 ++ src/IMeshTools/IMeshTools_ShapeExplorer.hxx | 41 + src/IMeshTools/IMeshTools_ShapeVisitor.hxx | 51 + src/MeshTest/MeshTest.cxx | 126 +- src/MeshTest/MeshTest_Debug.cxx | 35 +- src/MeshTest/MeshTest_DrawableMesh.cxx | 1 + src/QABugs/QABugs_11.cxx | 2 +- .../SelectMgr_TriangularFrustumSet.cxx | 8 +- src/StdPrs/StdPrs_HLRPolyShape.cxx | 2 +- src/TKMesh/EXTERNLIB | 13 +- src/TKMesh/PACKAGES | 3 + tests/bugs/grids.list | 2 +- tests/lowalgos/grids.list | 5 +- 149 files changed, 12507 insertions(+), 7241 deletions(-) delete mode 100644 src/BRepMesh/BRepMesh.hxx create mode 100644 src/BRepMesh/BRepMesh_BaseMeshAlgo.cxx create mode 100644 src/BRepMesh/BRepMesh_BaseMeshAlgo.hxx create mode 100644 src/BRepMesh/BRepMesh_BoundaryParamsRangeSplitter.hxx create mode 100644 src/BRepMesh/BRepMesh_ConeRangeSplitter.cxx create mode 100644 src/BRepMesh/BRepMesh_ConeRangeSplitter.hxx create mode 100644 src/BRepMesh/BRepMesh_ConstrainedBaseMeshAlgo.hxx create mode 100644 src/BRepMesh/BRepMesh_Context.cxx rename src/BRepMesh/{BRepMesh_Status.hxx => BRepMesh_Context.hxx} (53%) create mode 100644 src/BRepMesh/BRepMesh_CurveTessellator.cxx create mode 100644 src/BRepMesh/BRepMesh_CurveTessellator.hxx create mode 100644 src/BRepMesh/BRepMesh_CustomBaseMeshAlgo.hxx create mode 100644 src/BRepMesh/BRepMesh_CustomDelaunayBaseMeshAlgo.hxx create mode 100644 src/BRepMesh/BRepMesh_CylinderRangeSplitter.cxx create mode 100644 src/BRepMesh/BRepMesh_CylinderRangeSplitter.hxx create mode 100644 src/BRepMesh/BRepMesh_DefaultRangeSplitter.cxx create mode 100644 src/BRepMesh/BRepMesh_DefaultRangeSplitter.hxx create mode 100644 src/BRepMesh/BRepMesh_Deflection.cxx create mode 100644 src/BRepMesh/BRepMesh_Deflection.hxx create mode 100644 src/BRepMesh/BRepMesh_DelaunayBaseMeshAlgo.cxx create mode 100644 src/BRepMesh/BRepMesh_DelaunayBaseMeshAlgo.hxx create mode 100644 src/BRepMesh/BRepMesh_DelaunayDeflectionControlMeshAlgo.hxx create mode 100644 src/BRepMesh/BRepMesh_DelaunayNodeInsertionMeshAlgo.hxx create mode 100644 src/BRepMesh/BRepMesh_EdgeDiscret.cxx create mode 100644 src/BRepMesh/BRepMesh_EdgeDiscret.hxx delete mode 100644 src/BRepMesh/BRepMesh_EdgeParameterProvider.cxx delete mode 100644 src/BRepMesh/BRepMesh_EdgeTessellator.cxx delete mode 100644 src/BRepMesh/BRepMesh_EdgeTessellator.hxx delete mode 100644 src/BRepMesh/BRepMesh_FaceAttribute.cxx delete mode 100644 src/BRepMesh/BRepMesh_FaceAttribute.hxx create mode 100644 src/BRepMesh/BRepMesh_FaceChecker.cxx create mode 100644 src/BRepMesh/BRepMesh_FaceChecker.hxx create mode 100644 src/BRepMesh/BRepMesh_FaceDiscret.cxx create mode 100644 src/BRepMesh/BRepMesh_FaceDiscret.hxx delete mode 100644 src/BRepMesh/BRepMesh_FastDiscret.cxx delete mode 100644 src/BRepMesh/BRepMesh_FastDiscretFace.cxx delete mode 100644 src/BRepMesh/BRepMesh_FastDiscretFace.hxx delete mode 100644 src/BRepMesh/BRepMesh_IEdgeTool.cxx create mode 100644 src/BRepMesh/BRepMesh_MeshAlgoFactory.cxx create mode 100644 src/BRepMesh/BRepMesh_MeshAlgoFactory.hxx create mode 100644 src/BRepMesh/BRepMesh_MeshTool.cxx create mode 100644 src/BRepMesh/BRepMesh_MeshTool.hxx create mode 100644 src/BRepMesh/BRepMesh_ModelBuilder.cxx create mode 100644 src/BRepMesh/BRepMesh_ModelBuilder.hxx create mode 100644 src/BRepMesh/BRepMesh_ModelHealer.cxx create mode 100644 src/BRepMesh/BRepMesh_ModelHealer.hxx create mode 100644 src/BRepMesh/BRepMesh_ModelPostProcessor.cxx create mode 100644 src/BRepMesh/BRepMesh_ModelPostProcessor.hxx create mode 100644 src/BRepMesh/BRepMesh_ModelPreProcessor.cxx create mode 100644 src/BRepMesh/BRepMesh_ModelPreProcessor.hxx create mode 100644 src/BRepMesh/BRepMesh_NURBSRangeSplitter.cxx create mode 100644 src/BRepMesh/BRepMesh_NURBSRangeSplitter.hxx create mode 100644 src/BRepMesh/BRepMesh_NodeInsertionMeshAlgo.hxx delete mode 100644 src/BRepMesh/BRepMesh_PairOfPolygon.hxx create mode 100644 src/BRepMesh/BRepMesh_ShapeVisitor.cxx create mode 100644 src/BRepMesh/BRepMesh_ShapeVisitor.hxx create mode 100644 src/BRepMesh/BRepMesh_SphereRangeSplitter.cxx create mode 100644 src/BRepMesh/BRepMesh_SphereRangeSplitter.hxx create mode 100644 src/BRepMesh/BRepMesh_TorusRangeSplitter.cxx create mode 100644 src/BRepMesh/BRepMesh_TorusRangeSplitter.hxx create mode 100644 src/BRepMesh/BRepMesh_UVParamRangeSplitter.hxx delete mode 100644 src/BRepMesh/BRepMesh_WireChecker.cxx delete mode 100644 src/BRepMesh/BRepMesh_WireChecker.hxx delete mode 100644 src/BRepMesh/BRepMesh_WireInterferenceChecker.cxx delete mode 100644 src/BRepMesh/BRepMesh_WireInterferenceChecker.hxx create mode 100644 src/BRepMeshData/BRepMeshData_Curve.cxx create mode 100644 src/BRepMeshData/BRepMeshData_Curve.hxx create mode 100644 src/BRepMeshData/BRepMeshData_Edge.cxx create mode 100644 src/BRepMeshData/BRepMeshData_Edge.hxx create mode 100644 src/BRepMeshData/BRepMeshData_Face.cxx create mode 100644 src/BRepMeshData/BRepMeshData_Face.hxx create mode 100644 src/BRepMeshData/BRepMeshData_Model.cxx create mode 100644 src/BRepMeshData/BRepMeshData_Model.hxx create mode 100644 src/BRepMeshData/BRepMeshData_PCurve.cxx create mode 100644 src/BRepMeshData/BRepMeshData_PCurve.hxx create mode 100644 src/BRepMeshData/BRepMeshData_Wire.cxx create mode 100644 src/BRepMeshData/BRepMeshData_Wire.hxx create mode 100644 src/BRepMeshData/FILES create mode 100644 src/IMeshData/FILES create mode 100644 src/IMeshData/IMeshData_Curve.hxx create mode 100644 src/IMeshData/IMeshData_Edge.hxx create mode 100644 src/IMeshData/IMeshData_Face.hxx create mode 100644 src/IMeshData/IMeshData_Model.hxx create mode 100644 src/IMeshData/IMeshData_PCurve.hxx create mode 100644 src/IMeshData/IMeshData_ParametersList.hxx create mode 100644 src/IMeshData/IMeshData_ParametersListArrayAdaptor.hxx create mode 100644 src/IMeshData/IMeshData_Shape.hxx create mode 100644 src/IMeshData/IMeshData_Status.hxx create mode 100644 src/IMeshData/IMeshData_StatusOwner.hxx create mode 100644 src/IMeshData/IMeshData_TessellatedShape.hxx create mode 100644 src/IMeshData/IMeshData_Types.hxx create mode 100644 src/IMeshData/IMeshData_Wire.hxx create mode 100644 src/IMeshTools/FILES create mode 100644 src/IMeshTools/IMeshTools_Context.hxx rename src/{BRepMesh/BRepMesh_IEdgeTool.hxx => IMeshTools/IMeshTools_CurveTessellator.hxx} (62%) create mode 100644 src/IMeshTools/IMeshTools_MeshAlgo.hxx create mode 100644 src/IMeshTools/IMeshTools_MeshAlgoFactory.hxx create mode 100644 src/IMeshTools/IMeshTools_MeshBuilder.cxx create mode 100644 src/IMeshTools/IMeshTools_MeshBuilder.hxx create mode 100644 src/IMeshTools/IMeshTools_ModelAlgo.hxx create mode 100644 src/IMeshTools/IMeshTools_ModelBuilder.hxx create mode 100644 src/IMeshTools/IMeshTools_Parameters.hxx create mode 100644 src/IMeshTools/IMeshTools_ShapeExplorer.cxx create mode 100644 src/IMeshTools/IMeshTools_ShapeExplorer.hxx create mode 100644 src/IMeshTools/IMeshTools_ShapeVisitor.hxx diff --git a/adm/UDLIST b/adm/UDLIST index 39ffb0ba8a..42d740c06a 100644 --- a/adm/UDLIST +++ b/adm/UDLIST @@ -105,6 +105,7 @@ n BRepIntCurveSurface n BRepLib n BRepMAT2d n BRepMesh +n BRepMeshData n BRepOffset n BRepOffsetAPI n BRepPrim @@ -141,6 +142,8 @@ n HLRTopoBRep n HLRAppli n Hatch n HatchGen +n IMeshData +n IMeshTools n IntCurve n IntCurveSurface n IntCurvesFace diff --git a/src/AIS/AIS_RubberBand.cxx b/src/AIS/AIS_RubberBand.cxx index 1d7f1ab9d1..6de1394d36 100644 --- a/src/AIS/AIS_RubberBand.cxx +++ b/src/AIS/AIS_RubberBand.cxx @@ -296,13 +296,13 @@ Standard_Boolean AIS_RubberBand::fillTriangles() Handle(BRepMesh_DataStructureOfDelaun) aMeshStructure = new BRepMesh_DataStructureOfDelaun(anAllocator); Standard_Integer aPtsLower = myPoints.Lower(); Standard_Integer aPtsUpper = myPoints.Upper(); - BRepMesh::Array1OfInteger anIndexes (0, myPoints.Length() - 1); + IMeshData::VectorOfInteger anIndexes (myPoints.Length()); for (Standard_Integer aPtIdx = aPtsLower; aPtIdx <= aPtsUpper; ++aPtIdx) { gp_XY aP ((Standard_Real)myPoints.Value (aPtIdx).x(), (Standard_Real)myPoints.Value (aPtIdx).y()); BRepMesh_Vertex aVertex (aP, aPtIdx, BRepMesh_Frontier); - anIndexes.ChangeValue (aPtIdx - aPtsLower) = aMeshStructure->AddNode (aVertex); + anIndexes.Append (aMeshStructure->AddNode (aVertex)); } Standard_Real aPtSum = 0; @@ -325,7 +325,7 @@ Standard_Boolean AIS_RubberBand::fillTriangles() } BRepMesh_Delaun aTriangulation (aMeshStructure, anIndexes); - const BRepMesh::MapOfInteger& aTriangles = aMeshStructure->ElementsOfDomain(); + const IMeshData::MapOfInteger& aTriangles = aMeshStructure->ElementsOfDomain(); if (aTriangles.Extent() < 1) return Standard_False; @@ -338,7 +338,7 @@ Standard_Boolean AIS_RubberBand::fillTriangles() } Standard_Integer aVertexIndex = 1; - BRepMesh::MapOfInteger::Iterator aTriangleIt (aTriangles); + IMeshData::IteratorOfMapOfInteger aTriangleIt (aTriangles); for (; aTriangleIt.More(); aTriangleIt.Next()) { const Standard_Integer aTriangleId = aTriangleIt.Key(); diff --git a/src/BRepMesh/BRepMesh.hxx b/src/BRepMesh/BRepMesh.hxx deleted file mode 100644 index 8d503f6770..0000000000 --- a/src/BRepMesh/BRepMesh.hxx +++ /dev/null @@ -1,147 +0,0 @@ -// 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. - -#ifndef _BRepMesh_HeaderFile -#define _BRepMesh_HeaderFile - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -class BRepMesh_Vertex; -class TopoDS_Edge; -class TopoDS_Vertex; -class BRepMesh_FaceAttribute; -class BRepMesh_VertexInspector; -class BRepMesh_CircleInspector; -class BRepMesh_Classifier; -class Poly_Triangulation; -class BRepMesh_VertexTool; - -namespace BRepMesh -{ - //! Default size for memory block allocated by IncAllocator. - /** - * The idea here is that blocks of the given size are returned to the system - * rather than retained in the malloc heap, at least on WIN32 and WIN64 platforms. - */ -#ifdef _WIN64 - const size_t MEMORY_BLOCK_SIZE_HUGE = 1024 * 1024; -#else - const size_t MEMORY_BLOCK_SIZE_HUGE = 512 * 1024; -#endif - - //! Structure keeping parameters of segment. - struct Segment - { - gp_XY StartPnt; - gp_XY EndPnt; - }; - - //! Sequences - typedef NCollection_Sequence SequenceOfBndB2d; - typedef NCollection_Sequence SequenceOfInteger; - typedef NCollection_Sequence SequenceOfReal; - - //! Vectors - typedef NCollection_Vector VectorOfVertex; - typedef NCollection_Vector VectorOfInteger; - typedef NCollection_Vector VectorOfCircle; - - //! Trees - typedef NCollection_EBTree BndBox2dTree; - typedef NCollection_UBTreeFiller BndBox2dTreeFiller; - - //! Arrays - typedef NCollection_Array1 Array1OfVertexOfDelaun; - typedef NCollection_Array1 Array1OfInteger; - typedef NCollection_Array1 Array1OfReal; - typedef NCollection_Array1 Array1OfSegments; - - //! Lists - typedef NCollection_List ListOfXY; - typedef NCollection_List ListOfVertex; - typedef NCollection_List ListOfInteger; - - //! Maps - typedef NCollection_Map MapOfReal; - typedef NCollection_Map MapOfInteger; - typedef NCollection_DataMap DMapOfTriangulationBool; - typedef NCollection_Map MapOfShape; - - typedef NCollection_DataMap MapOfIntegerInteger; - typedef NCollection_DataMap DMapOfVertexInteger; - typedef NCollection_DataMap DMapOfFaceAttribute; - typedef NCollection_DataMap DMapOfShapePairOfPolygon; - typedef NCollection_DataMap DMapOfIntegerPnt; - typedef NCollection_DataMap DMapOfIntegerListOfXY; - typedef NCollection_DataMap DMapOfIntegerListOfInteger; - typedef NCollection_DataMap DMapOfEdgeListOfTriangulationBool; - - typedef NCollection_IndexedMap IMapOfInteger; - typedef NCollection_IndexedMap IMapOfReal; - typedef NCollection_IndexedMap IMapOfElement; - typedef NCollection_IndexedDataMap IDMapOfLink; - - //! CellFilters - typedef NCollection_CellFilter CircleCellFilter; - typedef NCollection_CellFilter VertexCellFilter; - - //! Handles - typedef NCollection_Handle HVectorOfVertex; - typedef NCollection_Handle HMapOfInteger; - typedef NCollection_Handle HIMapOfInteger; - typedef NCollection_Handle HDMapOfShapePairOfPolygon; - typedef NCollection_Handle HDMapOfIntegerPnt; - typedef NCollection_Handle HClassifier; - typedef NCollection_Handle HBndBox2dTree; - typedef NCollection_Handle HArray1OfSegments; - typedef NCollection_Handle HDMapOfVertexInteger; - typedef NCollection_Handle HDMapOfIntegerListOfXY; - typedef NCollection_Handle HVertexTool; - typedef NCollection_Handle HSequenceOfBndB2d; - typedef NCollection_Handle HSequenceOfInteger; - - //! Other data structures - typedef std::pair SegmentsTree; - typedef NCollection_Array1 Array1OfSegmentsTree; - -} // namespace BRepMesh - -#endif diff --git a/src/BRepMesh/BRepMesh_BaseMeshAlgo.cxx b/src/BRepMesh/BRepMesh_BaseMeshAlgo.cxx new file mode 100644 index 0000000000..dce927a2c4 --- /dev/null +++ b/src/BRepMesh/BRepMesh_BaseMeshAlgo.cxx @@ -0,0 +1,316 @@ +// Created on: 2016-04-19 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//======================================================================= +// Function: Constructor +// Purpose : +//======================================================================= +BRepMesh_BaseMeshAlgo::BRepMesh_BaseMeshAlgo() +{ +} + +//======================================================================= +// Function: Destructor +// Purpose : +//======================================================================= +BRepMesh_BaseMeshAlgo::~BRepMesh_BaseMeshAlgo() +{ +} + +//======================================================================= +// Function: Perform +// Purpose : +//======================================================================= +void BRepMesh_BaseMeshAlgo::Perform( + const IMeshData::IFaceHandle& theDFace, + const IMeshTools_Parameters& theParameters) +{ + try + { + OCC_CATCH_SIGNALS + + myDFace = theDFace; + myParameters = theParameters; + myAllocator = new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE); + myStructure = new BRepMesh_DataStructureOfDelaun(myAllocator); + myNodesMap = new VectorOfPnt(256, myAllocator); + myUsedNodes = new DMapOfIntegerInteger(1, myAllocator); + + if (initDataStructure()) + { + generateMesh(); + commitSurfaceTriangulation(); + } + } + catch (Standard_Failure const& /*theExeption*/) + { + } + + myDFace.Nullify(); // Do not hold link to face. + myStructure.Nullify(); + myNodesMap .Nullify(); + myUsedNodes.Nullify(); + myAllocator.Nullify(); +} + +//======================================================================= +//function : initDataStructure +//purpose : +//======================================================================= +Standard_Boolean BRepMesh_BaseMeshAlgo::initDataStructure() +{ + for (Standard_Integer aWireIt = 0; aWireIt < myDFace->WiresNb(); ++aWireIt) + { + const IMeshData::IWireHandle& aDWire = myDFace->GetWire(aWireIt); + if (aDWire->IsSet(IMeshData_SelfIntersectingWire)) + { + // TODO: here we can add points of self-intersecting wire as fixed points + // in order to keep consistency of nodes with adjacent faces. + continue; + } + + for (Standard_Integer aEdgeIt = 0; aEdgeIt < aDWire->EdgesNb(); ++aEdgeIt) + { + const IMeshData::IEdgeHandle aDEdge = aDWire->GetEdge(aEdgeIt); + const IMeshData::ICurveHandle& aCurve = aDEdge->GetCurve(); + const IMeshData::IPCurveHandle& aPCurve = aDEdge->GetPCurve( + myDFace.get(), aDWire->GetEdgeOrientation(aEdgeIt)); + + const TopAbs_Orientation aOri = fixSeamEdgeOrientation(aDEdge, aPCurve); + + Standard_Integer aPrevNodeIndex = -1; + const Standard_Integer aLastPoint = aPCurve->ParametersNb() - 1; + for (Standard_Integer aPointIt = 0; aPointIt <= aLastPoint; ++aPointIt) + { + const Standard_Integer aNodeIndex = registerNode( + aCurve ->GetPoint(aPointIt), + aPCurve->GetPoint(aPointIt), + BRepMesh_Frontier, Standard_False/*aPointIt > 0 && aPointIt < aLastPoint*/); + + aPCurve->GetIndex(aPointIt) = aNodeIndex; + myUsedNodes->Bind(aNodeIndex, aNodeIndex); + + if (aPrevNodeIndex != -1 && aPrevNodeIndex != aNodeIndex) + { + const Standard_Integer aLinksNb = myStructure->NbLinks(); + const Standard_Integer aLinkIndex = addLinkToMesh(aPrevNodeIndex, aNodeIndex, aOri); + if (aWireIt != 0 && aLinkIndex <= aLinksNb) + { + // Prevent holes around wire of zero area. + BRepMesh_Edge& aLink = const_cast(myStructure->GetLink(aLinkIndex)); + aLink.SetMovability(BRepMesh_Fixed); + } + } + + aPrevNodeIndex = aNodeIndex; + } + } + } + + return Standard_True; +} + +//======================================================================= +// Function: registerNode +// Purpose : +//======================================================================= +Standard_Integer BRepMesh_BaseMeshAlgo::registerNode( + const gp_Pnt& thePoint, + const gp_Pnt2d& thePoint2d, + const BRepMesh_DegreeOfFreedom theMovability, + const Standard_Boolean isForceAdd) +{ + const Standard_Integer aNodeIndex = addNodeToStructure( + thePoint2d, myNodesMap->Size(), theMovability, isForceAdd); + + if (aNodeIndex > myNodesMap->Size()) + { + myNodesMap->Append(thePoint); + } + + return aNodeIndex; +} + +//======================================================================= +// Function: addNode +// Purpose : +//======================================================================= +Standard_Integer BRepMesh_BaseMeshAlgo::addNodeToStructure( + const gp_Pnt2d& thePoint, + const Standard_Integer theLocation3d, + const BRepMesh_DegreeOfFreedom theMovability, + const Standard_Boolean isForceAdd) +{ + BRepMesh_Vertex aNode(thePoint.XY(), theLocation3d, theMovability); + return myStructure->AddNode(aNode, isForceAdd); +} + +//======================================================================= +//function : addLinkToMesh +//purpose : +//======================================================================= +Standard_Integer BRepMesh_BaseMeshAlgo::addLinkToMesh( + const Standard_Integer theFirstNodeId, + const Standard_Integer theLastNodeId, + const TopAbs_Orientation theOrientation) +{ + Standard_Integer aLinkIndex; + if (theOrientation == TopAbs_REVERSED) + aLinkIndex = myStructure->AddLink(BRepMesh_Edge(theLastNodeId, theFirstNodeId, BRepMesh_Frontier)); + else if (theOrientation == TopAbs_INTERNAL) + aLinkIndex = myStructure->AddLink(BRepMesh_Edge(theFirstNodeId, theLastNodeId, BRepMesh_Fixed)); + else + aLinkIndex = myStructure->AddLink(BRepMesh_Edge(theFirstNodeId, theLastNodeId, BRepMesh_Frontier)); + + return Abs(aLinkIndex); +} + +//======================================================================= +//function : fixSeamEdgeOrientation +//purpose : +//======================================================================= +TopAbs_Orientation BRepMesh_BaseMeshAlgo::fixSeamEdgeOrientation( + const IMeshData::IEdgeHandle& theDEdge, + const IMeshData::IPCurveHandle& thePCurve) const +{ + for (Standard_Integer aPCurveIt = 0; aPCurveIt < theDEdge->PCurvesNb(); ++aPCurveIt) + { + const IMeshData::IPCurveHandle& aPCurve = theDEdge->GetPCurve(aPCurveIt); + if (aPCurve->GetFace() == myDFace && thePCurve != aPCurve) + { + // Simple check that another pcurve of seam edge does not coincide with reference one. + const gp_Pnt2d& aPnt1_1 = thePCurve->GetPoint(0); + const gp_Pnt2d& aPnt2_1 = thePCurve->GetPoint(thePCurve->ParametersNb() - 1); + + const gp_Pnt2d& aPnt1_2 = aPCurve->GetPoint(0); + const gp_Pnt2d& aPnt2_2 = aPCurve->GetPoint(aPCurve->ParametersNb() - 1); + + const Standard_Real aSqDist1 = Min(aPnt1_1.SquareDistance(aPnt1_2), aPnt1_1.SquareDistance(aPnt2_2)); + const Standard_Real aSqDist2 = Min(aPnt2_1.SquareDistance(aPnt1_2), aPnt2_1.SquareDistance(aPnt2_2)); + if (aSqDist1 < Precision::SquareConfusion() && + aSqDist2 < Precision::SquareConfusion()) + { + return TopAbs_INTERNAL; + } + } + } + + return thePCurve->GetOrientation(); +} + +//======================================================================= +//function : commitSurfaceTriangulation +//purpose : +//======================================================================= +void BRepMesh_BaseMeshAlgo::commitSurfaceTriangulation() +{ + Handle(Poly_Triangulation) aTriangulation = collectTriangles(); + if (aTriangulation.IsNull()) + { + myDFace->SetStatus(IMeshData_Failure); + return; + } + + collectNodes(aTriangulation); + + aTriangulation->Deflection(myDFace->GetDeflection()); + BRepMesh_ShapeTool::AddInFace(myDFace->GetFace(), aTriangulation); +} + +//======================================================================= +//function : collectTriangles +//purpose : +//======================================================================= +Handle(Poly_Triangulation) BRepMesh_BaseMeshAlgo::collectTriangles() +{ + const IMeshData::MapOfInteger& aTriangles = myStructure->ElementsOfDomain(); + if (aTriangles.IsEmpty()) + { + return Handle(Poly_Triangulation)(); + } + + Poly_Array1OfTriangle aPolyTrianges(1, aTriangles.Extent()); + IMeshData::IteratorOfMapOfInteger aTriIt(aTriangles); + for (Standard_Integer aTriangeId = 1; aTriIt.More(); aTriIt.Next(), ++aTriangeId) + { + const BRepMesh_Triangle& aCurElem = myStructure->GetElement(aTriIt.Key()); + + Standard_Integer aNode[3]; + myStructure->ElementNodes(aCurElem, aNode); + + for (Standard_Integer i = 0; i < 3; ++i) + { + if (!myUsedNodes->IsBound(aNode[i])) + { + myUsedNodes->Bind(aNode[i], myUsedNodes->Size() + 1); + } + + aNode[i] = myUsedNodes->Find(aNode[i]); + } + + aPolyTrianges(aTriangeId).Set(aNode[0], aNode[1], aNode[2]); + } + + Handle(Poly_Triangulation) aTriangulation = new Poly_Triangulation( + myUsedNodes->Extent(), aTriangles.Extent(), Standard_True); + + aTriangulation->ChangeTriangles() = aPolyTrianges; + return aTriangulation; +} + +//======================================================================= +//function : collectNodes +//purpose : +//======================================================================= +void BRepMesh_BaseMeshAlgo::collectNodes( + const Handle(Poly_Triangulation)& theTriangulation) +{ + // Store mesh nodes + TColgp_Array1OfPnt& aNodes = theTriangulation->ChangeNodes(); + TColgp_Array1OfPnt2d& aNodes2d = theTriangulation->ChangeUVNodes(); + + for (Standard_Integer i = 1; i <= myNodesMap->Size(); ++i) + { + if (myUsedNodes->IsBound(i)) + { + const BRepMesh_Vertex& aVertex = myStructure->GetNode(i); + + const Standard_Integer aNodeIndex = myUsedNodes->Find(i); + aNodes(aNodeIndex) = myNodesMap->Value(aVertex.Location3d()); + aNodes2d(aNodeIndex) = getNodePoint2d(aVertex); + } + } +} + +//======================================================================= +// Function: getNodePoint2d +// Purpose : +//======================================================================= +gp_Pnt2d BRepMesh_BaseMeshAlgo::getNodePoint2d( + const BRepMesh_Vertex& theVertex) const +{ + return theVertex.Coord(); +} diff --git a/src/BRepMesh/BRepMesh_BaseMeshAlgo.hxx b/src/BRepMesh/BRepMesh_BaseMeshAlgo.hxx new file mode 100644 index 0000000000..56c03b2e8a --- /dev/null +++ b/src/BRepMesh/BRepMesh_BaseMeshAlgo.hxx @@ -0,0 +1,143 @@ +// Created on: 2016-07-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _BRepMesh_BaseMeshAlgo_HeaderFile +#define _BRepMesh_BaseMeshAlgo_HeaderFile + +#include +#include +#include +#include +#include + +class BRepMesh_DataStructureOfDelaun; +class BRepMesh_Delaun; + +//! Class provides base fuctionality for algorithms building face triangulation. +//! Performs initialization of BRepMesh_DataStructureOfDelaun and nodes map structures. +class BRepMesh_BaseMeshAlgo : public IMeshTools_MeshAlgo +{ +public: + + typedef NCollection_Shared > VectorOfPnt; + + //! Constructor. + Standard_EXPORT BRepMesh_BaseMeshAlgo(); + + //! Destructor. + Standard_EXPORT virtual ~BRepMesh_BaseMeshAlgo(); + + //! Performs processing of the given face. + Standard_EXPORT virtual void Perform( + const IMeshData::IFaceHandle& theDFace, + const IMeshTools_Parameters& theParameters) Standard_OVERRIDE; + + DEFINE_STANDARD_RTTI_INLINE(BRepMesh_BaseMeshAlgo, IMeshTools_MeshAlgo) + +protected: + + //! Gets discrete face. + inline const IMeshData::IFaceHandle& getDFace() const + { + return myDFace; + } + + //! Gets meshing parameters. + inline const IMeshTools_Parameters& getParameters() const + { + return myParameters; + } + + //! Gets common allocator. + inline const Handle(NCollection_IncAllocator)& getAllocator() const + { + return myAllocator; + } + + //! Gets mesh structure. + inline const Handle(BRepMesh_DataStructureOfDelaun)& getStructure() const + { + return myStructure; + } + + //! Gets 3d nodes map. + inline const Handle(VectorOfPnt)& getNodesMap() const + { + return myNodesMap; + } + +protected: + + //! Registers the given point in vertex map and adds 2d point to mesh data structure. + //! Returns index of node in the structure. + Standard_EXPORT virtual Standard_Integer registerNode( + const gp_Pnt& thePoint, + const gp_Pnt2d& thePoint2d, + const BRepMesh_DegreeOfFreedom theMovability, + const Standard_Boolean isForceAdd); + + //! Adds the given 2d point to mesh data structure. + //! Returns index of node in the structure. + Standard_EXPORT virtual Standard_Integer addNodeToStructure( + const gp_Pnt2d& thePoint, + const Standard_Integer theLocation3d, + const BRepMesh_DegreeOfFreedom theMovability, + const Standard_Boolean isForceAdd); + + //! Returns 2d point associated to the given vertex. + Standard_EXPORT virtual gp_Pnt2d getNodePoint2d(const BRepMesh_Vertex& theVertex) const; + + //! Performs initialization of data structure using existing model data. + Standard_EXPORT virtual Standard_Boolean initDataStructure(); + + //! Generates mesh for the contour stored in data structure. + Standard_EXPORT virtual void generateMesh() = 0; + +private: + + //! If the given edge has another pcurve for current face coinsiding with specified one, + //! returns TopAbs_INTERNAL flag. Elsewhere returns orientation of specified pcurve. + TopAbs_Orientation fixSeamEdgeOrientation( + const IMeshData::IEdgeHandle& theDEdge, + const IMeshData::IPCurveHandle& thePCurve) const; + + //! Adds new link to the mesh data structure. + //! Movability of the link and order of nodes depend on orientation parameter. + Standard_Integer addLinkToMesh( + const Standard_Integer theFirstNodeId, + const Standard_Integer theLastNodeId, + const TopAbs_Orientation theOrientation); + + //! Commits generated triangulation to TopoDS face. + void commitSurfaceTriangulation(); + + //! Collects triangles to output data. + Handle(Poly_Triangulation) collectTriangles(); + + //! Collects nodes to output data. + void collectNodes(const Handle(Poly_Triangulation)& theTriangulation); + +private: + typedef NCollection_Shared > DMapOfIntegerInteger; + + IMeshData::IFaceHandle myDFace; + IMeshTools_Parameters myParameters; + Handle(NCollection_IncAllocator) myAllocator; + Handle(BRepMesh_DataStructureOfDelaun) myStructure; + Handle(VectorOfPnt) myNodesMap; + Handle(DMapOfIntegerInteger) myUsedNodes; +}; + +#endif \ No newline at end of file diff --git a/src/BRepMesh/BRepMesh_BoundaryParamsRangeSplitter.hxx b/src/BRepMesh/BRepMesh_BoundaryParamsRangeSplitter.hxx new file mode 100644 index 0000000000..5006e1b65a --- /dev/null +++ b/src/BRepMesh/BRepMesh_BoundaryParamsRangeSplitter.hxx @@ -0,0 +1,54 @@ +// Created on: 2016-07-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _BRepMesh_BoundaryParamsRangeSplitter_HeaderFile +#define _BRepMesh_BoundaryParamsRangeSplitter_HeaderFile + +#include + +//! Auxiliary class extending UV range splitter in order to generate +//! internal nodes for NURBS surface. +class BRepMesh_BoundaryParamsRangeSplitter : public BRepMesh_NURBSRangeSplitter +{ +public: + + //! Constructor. + BRepMesh_BoundaryParamsRangeSplitter() + { + } + + //! Destructor. + virtual ~BRepMesh_BoundaryParamsRangeSplitter() + { + } + + //! Registers border point. + virtual void AddPoint(const gp_Pnt2d& thePoint) Standard_OVERRIDE + { + BRepMesh_NURBSRangeSplitter::AddPoint(thePoint); + GetParametersU().Add(thePoint.X()); + GetParametersV().Add(thePoint.Y()); + } + +protected: + + //! Initializes U and V parameters lists using CN continuity intervals. + virtual Standard_Boolean initParameters() const Standard_OVERRIDE + { + return Standard_True; + } +}; + +#endif diff --git a/src/BRepMesh/BRepMesh_CircleInspector.hxx b/src/BRepMesh/BRepMesh_CircleInspector.hxx index 509f376826..c954d7d50c 100644 --- a/src/BRepMesh/BRepMesh_CircleInspector.hxx +++ b/src/BRepMesh/BRepMesh_CircleInspector.hxx @@ -16,7 +16,7 @@ #ifndef BRepMesh_CircleInspector_Header #define BRepMesh_CircleInspector_Header -#include +#include #include #include #include @@ -37,9 +37,9 @@ public: const Standard_Real theTolerance, const Standard_Integer theReservedSize, const Handle(NCollection_IncAllocator)& theAllocator) - : myTolerance(theTolerance*theTolerance), + : mySqTolerance(theTolerance*theTolerance), myResIndices(theAllocator), - myCircles(theReservedSize) + myCircles(theReservedSize, theAllocator) { } @@ -53,7 +53,7 @@ public: } //! Resutns vector of registered circles. - inline const BRepMesh::VectorOfCircle& Circles() const + inline const IMeshData::VectorOfCircle& Circles() const { return myCircles; } @@ -75,7 +75,7 @@ public: } //! Returns list of circles shot by the reference point. - inline BRepMesh::ListOfInteger& GetShotCircles() + inline IMeshData::ListOfInteger& GetShotCircles() { return myResIndices; } @@ -83,8 +83,41 @@ public: //! Performs inspection of a circle with the given index. //! @param theTargetIndex index of a circle to be checked. //! @return status of the check. - Standard_EXPORT NCollection_CellFilter_Action Inspect( - const Standard_Integer theTargetIndex); + inline NCollection_CellFilter_Action Inspect( + const Standard_Integer theTargetIndex) + { + BRepMesh_Circle& aCircle = myCircles(theTargetIndex); + const Standard_Real& aRadius = aCircle.Radius(); + if (aRadius < 0.) + return CellFilter_Purge; + + gp_XY& aLoc = const_cast(aCircle.Location()); + + const Standard_Real aDX = myPoint.ChangeCoord(1) - aLoc.ChangeCoord(1); + const Standard_Real aDY = myPoint.ChangeCoord(2) - aLoc.ChangeCoord(2); + + //This check is wrong. It is better to use + // + // const Standard_Real aR = aRadius + aToler; + // if ((aDX * aDX + aDY * aDY) <= aR * aR) + // { + // ... + // } + + //where aToler = sqrt(mySqTolerance). Taking into account the fact + //that the input parameter of the class (see constructor) is linear + //(not quadratic) tolerance there is no point in square root computation. + //Simply, we do not need to compute square of the input tolerance and to + //assign it to mySqTolerance. The input linear tolerance is needed to be used. + + //However, this change leads to hangs the test case "perf mesh bug27119". + //So, this correction is better to be implemented in the future. + + if ((aDX * aDX + aDY * aDY) - (aRadius * aRadius) <= mySqTolerance) + myResIndices.Append(theTargetIndex); + + return CellFilter_Keep; + } //! Checks indices for equlity. static Standard_Boolean IsEqual( @@ -95,10 +128,10 @@ public: } private: - Standard_Real myTolerance; - BRepMesh::ListOfInteger myResIndices; - BRepMesh::VectorOfCircle myCircles; - gp_XY myPoint; + Standard_Real mySqTolerance; + IMeshData::ListOfInteger myResIndices; + IMeshData::VectorOfCircle myCircles; + gp_XY myPoint; }; #endif diff --git a/src/BRepMesh/BRepMesh_CircleTool.cxx b/src/BRepMesh/BRepMesh_CircleTool.cxx index e0f76003d9..67aa20ee60 100644 --- a/src/BRepMesh/BRepMesh_CircleTool.cxx +++ b/src/BRepMesh/BRepMesh_CircleTool.cxx @@ -21,34 +21,13 @@ #include #include -//======================================================================= -//function : Inspect -//purpose : -//======================================================================= -NCollection_CellFilter_Action BRepMesh_CircleInspector::Inspect( - const Standard_Integer theTargetIndex) -{ - const BRepMesh_Circle& aCircle = myCircles(theTargetIndex); - Standard_Real aRadius = aCircle.Radius(); - if(aRadius < 0.) - return CellFilter_Purge; - - const gp_XY& aLoc = aCircle.Location(); - - if ((myPoint - aLoc).SquareModulus() - (aRadius * aRadius) <= myTolerance) - myResIndices.Append(theTargetIndex); - - return CellFilter_Keep; -} - - //======================================================================= //function : BRepMesh_CircleTool //purpose : //======================================================================= BRepMesh_CircleTool::BRepMesh_CircleTool( const Handle(NCollection_IncAllocator)& theAllocator) -: myTolerance (Precision::PConfusion() * Precision::PConfusion()), +: myTolerance (Precision::PConfusion()), myAllocator (theAllocator), myCellFilter(10.0, theAllocator), mySelector (myTolerance, 64, theAllocator) @@ -62,7 +41,7 @@ BRepMesh_CircleTool::BRepMesh_CircleTool( BRepMesh_CircleTool::BRepMesh_CircleTool( const Standard_Integer theReservedSize, const Handle(NCollection_IncAllocator)& theAllocator) -: myTolerance (Precision::PConfusion() * Precision::PConfusion()), +: myTolerance (Precision::PConfusion()), myAllocator (theAllocator), myCellFilter(10.0, theAllocator), mySelector (myTolerance, Max(theReservedSize, 64), theAllocator) @@ -117,42 +96,43 @@ Standard_Boolean BRepMesh_CircleTool::MakeCircle(const gp_XY& thePoint1, static const Standard_Real aPrecision = Precision::PConfusion(); static const Standard_Real aSqPrecision = aPrecision * aPrecision; - if ((thePoint1 - thePoint3).SquareModulus() < aSqPrecision) - return Standard_False; - - gp_XY aLink1(thePoint2 - thePoint1); + gp_XY aLink1(const_cast(thePoint3).ChangeCoord(1) - const_cast(thePoint2).ChangeCoord(1), + const_cast(thePoint2).ChangeCoord(2) - const_cast(thePoint3).ChangeCoord(2)); if (aLink1.SquareModulus() < aSqPrecision) return Standard_False; - gp_XY aLink2(thePoint3 - thePoint2); + gp_XY aLink2(const_cast(thePoint1).ChangeCoord(1) - const_cast(thePoint3).ChangeCoord(1), + const_cast(thePoint3).ChangeCoord(2) - const_cast(thePoint1).ChangeCoord(2)); if (aLink2.SquareModulus() < aSqPrecision) return Standard_False; - gp_XY aMidPnt1 = (thePoint1 + thePoint2) / 2.; - gp_XY aNorm1 = gp_XY(aLink1.Y(), -aLink1.X()); - aNorm1.Add(aMidPnt1); - - if (aLink2.SquareModulus() < aSqPrecision) + gp_XY aLink3(const_cast(thePoint2).ChangeCoord(1) - const_cast(thePoint1).ChangeCoord(1), + const_cast(thePoint1).ChangeCoord(2) - const_cast(thePoint2).ChangeCoord(2)); + if (aLink3.SquareModulus() < aSqPrecision) return Standard_False; - gp_XY aMidPnt2 = (thePoint2 + thePoint3) / 2.; - gp_XY aNorm2 = gp_XY(aLink2.Y(), -aLink2.X()); - aNorm2.Add(aMidPnt2); + const Standard_Real aD = 2 * (const_cast(thePoint1).ChangeCoord(1) * aLink1.Y() + + const_cast(thePoint2).ChangeCoord(1) * aLink2.Y() + + const_cast(thePoint3).ChangeCoord(1) * aLink3.Y()); - gp_XY aIntPnt; - Standard_Real aParam[2]; - BRepMesh_GeomTool::IntFlag aIntFlag = - BRepMesh_GeomTool::IntLinLin(aMidPnt1, aNorm1, - aMidPnt2, aNorm2, aIntPnt, aParam); - - if (aIntFlag != BRepMesh_GeomTool::Cross) + if (Abs(aD) < gp::Resolution()) return Standard_False; - theLocation = aIntPnt; + const Standard_Real aInvD = 1. / aD; + const Standard_Real aSqMod1 = thePoint1.SquareModulus(); + const Standard_Real aSqMod2 = thePoint2.SquareModulus(); + const Standard_Real aSqMod3 = thePoint3.SquareModulus(); + theLocation.ChangeCoord(1) = (aSqMod1 * aLink1.Y() + + aSqMod2 * aLink2.Y() + + aSqMod3 * aLink3.Y()) * aInvD; + + theLocation.ChangeCoord(2) = (aSqMod1 * aLink1.X() + + aSqMod2 * aLink2.X() + + aSqMod3 * aLink3.X()) * aInvD; - theRadius = Sqrt(Max(Max((thePoint1 - aIntPnt).SquareModulus(), - (thePoint2 - aIntPnt).SquareModulus()), - (thePoint3 - aIntPnt).SquareModulus())) + 2 * RealEpsilon(); + theRadius = Sqrt(Max(Max((thePoint1 - theLocation).SquareModulus(), + (thePoint2 - theLocation).SquareModulus()), + (thePoint3 - theLocation).SquareModulus())) + 2 * RealEpsilon(); return Standard_True; } @@ -190,7 +170,7 @@ void BRepMesh_CircleTool::Delete(const Standard_Integer theIndex) //function : Select //purpose : //======================================================================= -BRepMesh::ListOfInteger& BRepMesh_CircleTool::Select(const gp_XY& thePoint) +IMeshData::ListOfInteger& BRepMesh_CircleTool::Select(const gp_XY& thePoint) { mySelector.SetPoint(thePoint); myCellFilter.Inspect(thePoint, mySelector); diff --git a/src/BRepMesh/BRepMesh_CircleTool.hxx b/src/BRepMesh/BRepMesh_CircleTool.hxx index a81e739b63..3f5701d63d 100644 --- a/src/BRepMesh/BRepMesh_CircleTool.hxx +++ b/src/BRepMesh/BRepMesh_CircleTool.hxx @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include class gp_Circ2d; @@ -52,7 +52,7 @@ public: //! @param theReservedSize size to be reserved for vector of circles. inline void Init(const Standard_Integer /*theReservedSize*/) { - myTolerance = Precision::PConfusion() * Precision::PConfusion(); + myTolerance = Precision::PConfusion(); } //! Sets new size for cell filter. @@ -83,6 +83,12 @@ public: myFaceMax = theMax; } + //! Retruns true if cell filter contains no circle. + inline Standard_Boolean IsEmpty () const + { + return mySelector.Circles ().IsEmpty (); + } + //! Binds the circle to the tool. //! @param theIndex index a circle should be bound with. //! @param theCircle circle to be bound. @@ -125,7 +131,7 @@ public: //! Select the circles shot by the given point. //! @param thePoint bullet point. - Standard_EXPORT BRepMesh::ListOfInteger& Select(const gp_XY& thePoint); + Standard_EXPORT IMeshData::ListOfInteger& Select(const gp_XY& thePoint); private: @@ -141,7 +147,7 @@ private: Standard_Real myTolerance; Handle(NCollection_IncAllocator) myAllocator; - BRepMesh::CircleCellFilter myCellFilter; + IMeshData::CircleCellFilter myCellFilter; BRepMesh_CircleInspector mySelector; gp_XY myFaceMax; gp_XY myFaceMin; diff --git a/src/BRepMesh/BRepMesh_Classifier.cxx b/src/BRepMesh/BRepMesh_Classifier.cxx index 09545b49ed..9ec0ca51dd 100644 --- a/src/BRepMesh/BRepMesh_Classifier.cxx +++ b/src/BRepMesh/BRepMesh_Classifier.cxx @@ -1,7 +1,6 @@ -// Created on: 1997-06-26 -// Created by: Laurent PAINNOT -// Copyright (c) 1997-1999 Matra Datavision -// Copyright (c) 1999-2014 OPEN CASCADE SAS +// Created on: 2016-07-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN // // This file is part of Open CASCADE Technology software library. // @@ -29,6 +28,14 @@ BRepMesh_Classifier::BRepMesh_Classifier() { } +//======================================================================= +//function : Destructor +//purpose : +//======================================================================= +BRepMesh_Classifier::~BRepMesh_Classifier() +{ +} + //======================================================================= //function : Perform //purpose : @@ -38,19 +45,23 @@ TopAbs_State BRepMesh_Classifier::Perform(const gp_Pnt2d& thePoint) const Standard_Boolean isOut = Standard_False; Standard_Integer aNb = myTabClass.Length(); - for (Standard_Integer i = 1; i <= aNb; i++) + for (Standard_Integer i = 0; i < aNb; i++) { - Standard_Integer aCur = ((CSLib_Class2d*)myTabClass(i))->SiDans(thePoint); + const Standard_Integer aCur = myTabClass(i)->SiDans(thePoint); if (aCur == 0) { // Point is ON, but mark it as OUT isOut = Standard_True; } else + { isOut = myTabOrient(i) ? (aCur == -1) : (aCur == 1); + } if (isOut) + { return TopAbs_OUT; + } } return TopAbs_IN; @@ -61,23 +72,23 @@ TopAbs_State BRepMesh_Classifier::Perform(const gp_Pnt2d& thePoint) const //purpose : //======================================================================= void BRepMesh_Classifier::RegisterWire( - const NCollection_Sequence& theWire, - const Standard_Real theTolUV, - const Standard_Real theUmin, - const Standard_Real theUmax, - const Standard_Real theVmin, - const Standard_Real theVmax) + const NCollection_Sequence& theWire, + const std::pair& theTolUV, + const std::pair& theRangeU, + const std::pair& theRangeV) { const Standard_Integer aNbPnts = theWire.Length(); if (aNbPnts < 2) + { return; + } // Accumulate angle TColgp_Array1OfPnt2d aPClass(1, aNbPnts); Standard_Real anAngle = 0.0; - gp_Pnt2d p1 = theWire(1), p2 = theWire(2), p3; - aPClass(1) = p1; - aPClass(2) = p2; + const gp_Pnt2d *p1 = theWire(1), *p2 = theWire(2), *p3; + aPClass(1) = *p1; + aPClass(2) = *p2; const Standard_Real aAngTol = Precision::Angular(); const Standard_Real aSqConfusion = @@ -88,15 +99,15 @@ void BRepMesh_Classifier::RegisterWire( Standard_Integer ii = i + 2; if (ii > aNbPnts) { - p3 = aPClass(ii - aNbPnts); + p3 = &aPClass(ii - aNbPnts); } else { p3 = theWire.Value(ii); - aPClass(ii) = p3; + aPClass(ii) = *p3; } - gp_Vec2d A(p1,p2), B(p2,p3); + const gp_Vec2d A(*p1,*p2), B(*p2,*p3); if (A.SquareMagnitude() > aSqConfusion && B.SquareMagnitude() > aSqConfusion) { @@ -115,27 +126,10 @@ void BRepMesh_Classifier::RegisterWire( if (Abs(anAngle) < aAngTol) anAngle = 0.0; - myTabClass.Append( (void *)new CSLib_Class2d(aPClass, - theTolUV, theTolUV, theUmin, theVmin, theUmax, theVmax) ); - myTabOrient.Append( !(anAngle < 0.0) ); -} - -//======================================================================= -//function : Destroy -//purpose : -//======================================================================= -void BRepMesh_Classifier::Destroy() -{ - Standard_Integer aNb = myTabClass.Length(); - for (Standard_Integer i = 1; i <= aNb; i++) - { - if (myTabClass(i)) - { - delete ((CSLib_Class2d*)myTabClass(i)); - myTabClass(i) = NULL; - } - } + myTabClass.Append(new CSLib_Class2d( + aPClass, theTolUV.first, theTolUV.second, + theRangeU.first, theRangeV.first, + theRangeU.second, theRangeV.second)); - myTabClass.Clear(); - myTabOrient.Clear(); + myTabOrient.Append( !(anAngle < 0.0) ); } diff --git a/src/BRepMesh/BRepMesh_Classifier.hxx b/src/BRepMesh/BRepMesh_Classifier.hxx index 4a87b84b61..d7ee6f57e5 100644 --- a/src/BRepMesh/BRepMesh_Classifier.hxx +++ b/src/BRepMesh/BRepMesh_Classifier.hxx @@ -1,7 +1,6 @@ -// Created on: 2014-06-03 +// Created on: 2016-07-07 +// Copyright (c) 2016 OPEN CASCADE SAS // Created by: Oleg AGASHIN -// Copyright (c) 1997-1999 Matra Datavision -// Copyright (c) 1999-2014 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. // @@ -18,38 +17,31 @@ #define _BRepMesh_Classifier_HeaderFile #include -#include #include -#include -#include #include -#include -#include +#include +#include -//! Auxilary class contains information about correctness of discretized -//! face and used for classification of points regarding face internals. -class BRepMesh_Classifier +#include + +class gp_Pnt2d; +class CSLib_Class2d; + +//! Auxilary class intended for classification of points +//! regarding internals of discrete face. +class BRepMesh_Classifier : public Standard_Transient { public: - DEFINE_STANDARD_ALLOC - //! Constructor. Standard_EXPORT BRepMesh_Classifier(); //! Destructor. - Standard_EXPORT virtual ~BRepMesh_Classifier() - { - Destroy(); - } - - //! Method is called on destruction. - //! Clears internal data structures. - Standard_EXPORT void Destroy(); + Standard_EXPORT virtual ~BRepMesh_Classifier(); //! Performs classification of the given point regarding to face internals. //! @param thePoint Point in parametric space to be classified. - //! @return + //! @return TopAbs_IN if point lies within face boundaries and TopAbs_OUT elsewhere. Standard_EXPORT TopAbs_State Perform(const gp_Pnt2d& thePoint) const; //! Registers wire specified by sequence of points for @@ -61,17 +53,17 @@ public: //! @param theVmin Lower V boundary of the face in parametric space. //! @param theVmax Upper V boundary of the face in parametric space. Standard_EXPORT void RegisterWire( - const NCollection_Sequence& theWire, - const Standard_Real theTolUV, - const Standard_Real theUmin, - const Standard_Real theUmax, - const Standard_Real theVmin, - const Standard_Real theVmax); + const NCollection_Sequence& theWire, + const std::pair& theTolUV, + const std::pair& theRangeU, + const std::pair& theRangeV); + + DEFINE_STANDARD_RTTI_INLINE (BRepMesh_Classifier, Standard_Transient) private: - BRepTopAdaptor_SeqOfPtr myTabClass; - TColStd_SequenceOfBoolean myTabOrient; + NCollection_Vector > myTabClass; + IMeshData::VectorOfBoolean myTabOrient; }; #endif diff --git a/src/BRepMesh/BRepMesh_ConeRangeSplitter.cxx b/src/BRepMesh/BRepMesh_ConeRangeSplitter.cxx new file mode 100644 index 0000000000..da28dd093c --- /dev/null +++ b/src/BRepMesh/BRepMesh_ConeRangeSplitter.cxx @@ -0,0 +1,80 @@ +// Created on: 2016-07-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 +#include + +//======================================================================= +// Function: GetSplitSteps +// Purpose : +//======================================================================= +std::pair BRepMesh_ConeRangeSplitter::GetSplitSteps( + const IMeshTools_Parameters& theParameters, + std::pair& theStepsNb) const +{ + const std::pair& aRangeU = GetRangeU(); + const std::pair& aRangeV = GetRangeV(); + + gp_Cone aCone = GetDFace()->GetSurface()->Cone(); + Standard_Real aRefR = aCone.RefRadius(); + Standard_Real aSAng = aCone.SemiAngle(); + Standard_Real aRadius = Max(Abs(aRefR + aRangeV.first * Sin(aSAng)), + Abs(aRefR + aRangeV.second * Sin(aSAng))); + + Standard_Real Dv, Du = GCPnts_TangentialDeflection::ArcAngularStep( + aRadius, GetDFace()->GetDeflection(), + theParameters.Angle, theParameters.MinSize); + + const Standard_Real aDiffU = aRangeU.second - aRangeU.first; + const Standard_Real aDiffV = aRangeV.second - aRangeV.first; + Standard_Integer nbU = (Standard_Integer) (aDiffU / Du); + Standard_Integer nbV = (Standard_Integer) (nbU * (aDiffV) / (aDiffU * aRadius)); + Du = aDiffU / (nbU + 1); + Dv = aDiffV / (nbV + 1); + + theStepsNb.first = nbU; + theStepsNb.second = nbV; + return std::make_pair (Du, Dv); +} + +//======================================================================= +// Function: GenerateSurfaceNodes +// Purpose : +//======================================================================= +Handle(IMeshData::ListOfPnt2d) BRepMesh_ConeRangeSplitter::GenerateSurfaceNodes( + const IMeshTools_Parameters& theParameters) const +{ + const std::pair& aRangeU = GetRangeU(); + const std::pair& aRangeV = GetRangeV(); + + std::pair aStepsNb; + std::pair aSteps = GetSplitSteps (theParameters, aStepsNb); + + const Handle(NCollection_IncAllocator) aTmpAlloc = + new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE); + Handle(IMeshData::ListOfPnt2d) aNodes = new IMeshData::ListOfPnt2d(aTmpAlloc); + + const Standard_Real aPasMaxV = aRangeV.second - aSteps.second*0.5; + const Standard_Real aPasMaxU = aRangeU.second - aSteps.first *0.5; + for (Standard_Real aPasV = aRangeV.first + aSteps.second; aPasV < aPasMaxV; aPasV += aSteps.second) + { + for (Standard_Real aPasU = aRangeU.first + aSteps.first; aPasU < aPasMaxU; aPasU += aSteps.first) + { + aNodes->Append(gp_Pnt2d(aPasU, aPasV)); + } + } + + return aNodes; +} diff --git a/src/BRepMesh/BRepMesh_ConeRangeSplitter.hxx b/src/BRepMesh/BRepMesh_ConeRangeSplitter.hxx new file mode 100644 index 0000000000..e9abf42fec --- /dev/null +++ b/src/BRepMesh/BRepMesh_ConeRangeSplitter.hxx @@ -0,0 +1,50 @@ +// Created on: 2016-07-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _BRepMesh_ConeRangeSplitter_HeaderFile +#define _BRepMesh_ConeRangeSplitter_HeaderFile + +#include +#include + +//! Auxiliary class extending default range splitter in +//! order to generate internal nodes for conical surface. +class BRepMesh_ConeRangeSplitter : public BRepMesh_DefaultRangeSplitter +{ +public: + + //! Constructor. + BRepMesh_ConeRangeSplitter() + { + } + + //! Destructor. + virtual ~BRepMesh_ConeRangeSplitter() + { + } + + //! Returns split intervals along U and V direction. + //! @param theParameters meshing parameters. + //! @param[out] theStepsNb number of steps along corresponding direction. + std::pair GetSplitSteps( + const IMeshTools_Parameters& theParameters, + std::pair& theStepsNb) const; + + //! Returns list of nodes generated using surface data and specified parameters. + Standard_EXPORT virtual Handle(IMeshData::ListOfPnt2d) GenerateSurfaceNodes( + const IMeshTools_Parameters& theParameters) const Standard_OVERRIDE; +}; + +#endif diff --git a/src/BRepMesh/BRepMesh_ConstrainedBaseMeshAlgo.hxx b/src/BRepMesh/BRepMesh_ConstrainedBaseMeshAlgo.hxx new file mode 100644 index 0000000000..7edd4aac23 --- /dev/null +++ b/src/BRepMesh/BRepMesh_ConstrainedBaseMeshAlgo.hxx @@ -0,0 +1,60 @@ +// Created on: 2019-07-08 +// Copyright (c) 2019 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _BRepMesh_ConstrainedBaseMeshAlgo_HeaderFile +#define _BRepMesh_ConstrainedBaseMeshAlgo_HeaderFile + +#include +#include +#include + +class BRepMesh_DataStructureOfDelaun; +class BRepMesh_Delaun; + +//! Class provides base fuctionality to build face triangulation using Dealunay approach. +//! Performs generation of mesh using raw data from model. +class BRepMesh_ConstrainedBaseMeshAlgo : public BRepMesh_BaseMeshAlgo +{ +public: + + //! Constructor. + BRepMesh_ConstrainedBaseMeshAlgo () + { + } + + //! Destructor. + virtual ~BRepMesh_ConstrainedBaseMeshAlgo () + { + } + + DEFINE_STANDARD_RTTI_INLINE(BRepMesh_ConstrainedBaseMeshAlgo, BRepMesh_BaseMeshAlgo) + +protected: + + //! Returns size of cell to be used by acceleration circles grid structure. + virtual std::pair getCellsCount (const Standard_Integer /*theVerticesNb*/) + { + return std::pair (-1, -1); + } + + //! Perfroms processing of generated mesh. + //! By default does nothing. + //! Expected to be called from method generateMesh() in successor classes. + virtual void postProcessMesh (BRepMesh_Delaun& /*theMesher*/) + { + } +}; + +#endif diff --git a/src/BRepMesh/BRepMesh_Context.cxx b/src/BRepMesh/BRepMesh_Context.cxx new file mode 100644 index 0000000000..e48d038467 --- /dev/null +++ b/src/BRepMesh/BRepMesh_Context.cxx @@ -0,0 +1,45 @@ +// Created on: 2016-04-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 +#include +#include +#include +#include +#include +#include +#include + +//======================================================================= +// Function: Constructor +// Purpose : +//======================================================================= +BRepMesh_Context::BRepMesh_Context () +{ + SetModelBuilder (new BRepMesh_ModelBuilder); + SetEdgeDiscret (new BRepMesh_EdgeDiscret); + SetModelHealer (new BRepMesh_ModelHealer); + SetPreProcessor (new BRepMesh_ModelPreProcessor); + SetFaceDiscret (new BRepMesh_FaceDiscret(new BRepMesh_MeshAlgoFactory)); + SetPostProcessor(new BRepMesh_ModelPostProcessor); +} + +//======================================================================= +// Function: Destructor +// Purpose : +//======================================================================= +BRepMesh_Context::~BRepMesh_Context () +{ +} diff --git a/src/BRepMesh/BRepMesh_Status.hxx b/src/BRepMesh/BRepMesh_Context.hxx similarity index 53% rename from src/BRepMesh/BRepMesh_Status.hxx rename to src/BRepMesh/BRepMesh_Context.hxx index 0c4ce44179..a802a6b44b 100644 --- a/src/BRepMesh/BRepMesh_Status.hxx +++ b/src/BRepMesh/BRepMesh_Context.hxx @@ -1,6 +1,6 @@ -// Created on: 2011-05-17 +// Created on: 2016-04-07 +// Copyright (c) 2016 OPEN CASCADE SAS // Created by: Oleg AGASHIN -// Copyright (c) 2011-2014 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. // @@ -13,18 +13,24 @@ // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. -#ifndef _BRepMesh_Status_HeaderFile -#define _BRepMesh_Status_HeaderFile +#ifndef _BRepMesh_Context_HeaderFile +#define _BRepMesh_Context_HeaderFile -//! Discribes the wires discretisation. -enum BRepMesh_Status +#include + +//! Class implemeting default context of BRepMesh algorithm. +//! Initializes context by default algorithms. +class BRepMesh_Context : public IMeshTools_Context { - BRepMesh_NoError = 0x0, - BRepMesh_OpenWire = 0x1, - BRepMesh_SelfIntersectingWire = 0x2, - BRepMesh_Failure = 0x4, - BRepMesh_ReMesh = 0x8, - BRepMesh_UserBreak = 0x16 +public: + + //! Constructor. + Standard_EXPORT BRepMesh_Context (); + + //! Destructor. + Standard_EXPORT virtual ~BRepMesh_Context (); + + DEFINE_STANDARD_RTTI_INLINE(BRepMesh_Context, IMeshTools_Context) }; -#endif +#endif \ No newline at end of file diff --git a/src/BRepMesh/BRepMesh_CurveTessellator.cxx b/src/BRepMesh/BRepMesh_CurveTessellator.cxx new file mode 100644 index 0000000000..bb780d27e0 --- /dev/null +++ b/src/BRepMesh/BRepMesh_CurveTessellator.cxx @@ -0,0 +1,342 @@ +// Created on: 2016-04-19 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//======================================================================= +//function : Constructor +//purpose : +//======================================================================= +BRepMesh_CurveTessellator::BRepMesh_CurveTessellator( + const IMeshData::IEdgeHandle& theEdge, + const IMeshTools_Parameters& theParameters) + : myDEdge(theEdge), + myParameters(theParameters), + myEdge(theEdge->GetEdge()), + myCurve(myEdge) +{ + init(); +} + +//======================================================================= +//function : Constructor +//purpose : +//======================================================================= +BRepMesh_CurveTessellator::BRepMesh_CurveTessellator ( + const IMeshData::IEdgeHandle& theEdge, + const TopAbs_Orientation theOrientation, + const IMeshData::IFaceHandle& theFace, + const IMeshTools_Parameters& theParameters) + : myDEdge(theEdge), + myParameters(theParameters), + myEdge(TopoDS::Edge(theEdge->GetEdge().Oriented(theOrientation))), + myCurve(myEdge, theFace->GetFace()) +{ + init(); +} + +//======================================================================= +//function : init +//purpose : +//======================================================================= +void BRepMesh_CurveTessellator::init() +{ + if (myParameters.MinSize <= 0.0) + { + Standard_Failure::Raise ("The structure \"myParameters\" is not initialized"); + } + + TopExp::Vertices(myEdge, myFirstVertex, myLastVertex); + + Standard_Real aPreciseAngDef = 0.5 * myDEdge->GetAngularDeflection(); + Standard_Real aPreciseLinDef = 0.5 * myDEdge->GetDeflection(); + if (myEdge.Orientation() == TopAbs_INTERNAL) + { + aPreciseLinDef *= 0.5; + } + + aPreciseLinDef = Max (aPreciseLinDef, Precision::Confusion()); + aPreciseAngDef = Max (aPreciseAngDef, Precision::Angular()); + + Standard_Real aMinSize = myParameters.MinSize; + if (myParameters.AdjustMinSize) + { + aMinSize = Min (aMinSize, myParameters.RelMinSize() * GCPnts_AbscissaPoint::Length ( + myCurve, myCurve.FirstParameter(), myCurve.LastParameter(), aPreciseLinDef)); + } + + mySquareEdgeDef = aPreciseLinDef * aPreciseLinDef; + mySquareMinSize = Max (mySquareEdgeDef, aMinSize * aMinSize); + + myEdgeSqTol = BRep_Tool::Tolerance (myEdge); + myEdgeSqTol *= myEdgeSqTol; + + const Standard_Integer aMinPntNb = (myCurve.GetType() == GeomAbs_Circle) ? 4 : 2; //OCC287 + + myDiscretTool.Initialize (myCurve, + myCurve.FirstParameter(), myCurve.LastParameter(), + aPreciseAngDef, aPreciseLinDef, aMinPntNb, + Precision::PConfusion(), aMinSize); + + if (myCurve.IsCurveOnSurface()) + { + const Adaptor3d_CurveOnSurface& aCurve = myCurve.CurveOnSurface(); + const Handle(Adaptor3d_HSurface)& aSurface = aCurve.GetSurface(); + + const Standard_Real aTol = Precision::Confusion(); + const Standard_Real aDu = aSurface->UResolution(aTol); + const Standard_Real aDv = aSurface->VResolution(aTol); + + myFaceRangeU[0] = aSurface->FirstUParameter() - aDu; + myFaceRangeU[1] = aSurface->LastUParameter() + aDu; + + myFaceRangeV[0] = aSurface->FirstVParameter() - aDv; + myFaceRangeV[1] = aSurface->LastVParameter() + aDv; + } + + addInternalVertices(); + splitByDeflection2d(); +} + +//======================================================================= +//function : Destructor +//purpose : +//======================================================================= +BRepMesh_CurveTessellator::~BRepMesh_CurveTessellator () +{ +} + +//======================================================================= +//function : NbPoints +//purpose : +//======================================================================= +Standard_Integer BRepMesh_CurveTessellator::PointsNb () const +{ + return myDiscretTool.NbPoints (); +} + +//======================================================================= +//function : splitByDeflection2d +//purpose : +//======================================================================= +void BRepMesh_CurveTessellator::splitByDeflection2d () +{ + const Standard_Integer aNodesNb = myDiscretTool.NbPoints (); + if (!myDEdge->IsFree () && + myDEdge->GetSameParam () && + myDEdge->GetSameRange () && + aNodesNb > 1) + { + for (Standard_Integer aPCurveIt = 0; aPCurveIt < myDEdge->PCurvesNb (); ++aPCurveIt) + { + TopLoc_Location aLoc; + const IMeshData::IPCurveHandle& aPCurve = myDEdge->GetPCurve(aPCurveIt); + const TopoDS_Face& aFace = aPCurve->GetFace ()->GetFace (); + const Handle (Geom_Surface)& aSurface = BRep_Tool::Surface (aFace, aLoc); + if (aSurface->IsInstance(STANDARD_TYPE(Geom_Plane))) + { + continue; + } + + const TopoDS_Edge aCurrEdge = TopoDS::Edge(myEdge.Oriented(aPCurve->GetOrientation())); + + Standard_Real aF, aL; + Handle (Geom2d_Curve) aCurve2d = BRep_Tool::CurveOnSurface (aCurrEdge, aFace, aF, aL); + TColStd_Array1OfReal aParamArray (1, aNodesNb); + for (Standard_Integer i = 1; i <= aNodesNb; ++i) + aParamArray.SetValue (i, myDiscretTool.Parameter (i)); + + for (Standard_Integer i = 1; i < aNodesNb; ++i) + splitSegment (aSurface, aCurve2d, aParamArray (i), aParamArray (i + 1), 1); + } + } +} + +//======================================================================= +//function : addInternalVertices +//purpose : +//======================================================================= +void BRepMesh_CurveTessellator::addInternalVertices () +{ + // PTv, chl/922/G9, Take into account internal vertices + // it is necessary for internal edges, which do not split other edges, by their vertex + TopExp_Explorer aVertexIt (myEdge, TopAbs_VERTEX); + for (; aVertexIt.More (); aVertexIt.Next ()) + { + const TopoDS_Vertex& aVertex = TopoDS::Vertex (aVertexIt.Current ()); + if (aVertex.Orientation() != TopAbs_INTERNAL) + { + continue; + } + + myDiscretTool.AddPoint (BRep_Tool::Pnt (aVertex), + BRep_Tool::Parameter (aVertex, myEdge), Standard_True); + } +} + +//======================================================================= +//function : isInToleranceOfVertex +//purpose : +//======================================================================= +Standard_Boolean BRepMesh_CurveTessellator::isInToleranceOfVertex ( + const gp_Pnt& thePoint, + const TopoDS_Vertex& theVertex) const +{ + const gp_Pnt aPoint = BRep_Tool::Pnt(theVertex); + const Standard_Real aTolerance = BRep_Tool::Tolerance(theVertex); + + return (thePoint.SquareDistance (aPoint) < aTolerance * aTolerance); +} + +//======================================================================= +//function : Value +//purpose : +//======================================================================= +Standard_Boolean BRepMesh_CurveTessellator::Value ( + const Standard_Integer theIndex, + gp_Pnt& thePoint, + Standard_Real& theParameter) const +{ + thePoint = myDiscretTool.Value (theIndex); + theParameter = myDiscretTool.Parameter (theIndex); + + /*if (!isInToleranceOfVertex(thePoint, myFirstVertex) && + !isInToleranceOfVertex(thePoint, myLastVertex)) + {*/ + if (!myCurve.IsCurveOnSurface()) + { + return Standard_True; + } + + // If point coordinates are out of surface range, + // it is necessary to re-project point. + const Adaptor3d_CurveOnSurface& aCurve = myCurve.CurveOnSurface(); + const Handle(Adaptor3d_HSurface)& aSurface = aCurve.GetSurface(); + if (aSurface->GetType() != GeomAbs_BSplineSurface && + aSurface->GetType() != GeomAbs_BezierSurface && + aSurface->GetType() != GeomAbs_OtherSurface) + { + return Standard_True; + } + + // Let skip periodic case. + if (aSurface->IsUPeriodic() || aSurface->IsVPeriodic()) + { + return Standard_True; + } + + gp_Pnt2d aUV; + aCurve.GetCurve()->D0(theParameter, aUV); + // Point lies within the surface range - nothing to do. + if (aUV.X() > myFaceRangeU[0] && aUV.X() < myFaceRangeU[1] && + aUV.Y() > myFaceRangeV[0] && aUV.Y() < myFaceRangeV[1]) + { + return Standard_True; + } + + gp_Pnt aPntOnSurf; + aSurface->D0(aUV.X(), aUV.Y(), aPntOnSurf); + + return (thePoint.SquareDistance(aPntOnSurf) < myEdgeSqTol); + /*} + + return Standard_False;*/ +} + +//======================================================================= +//function : splitSegment +//purpose : +//======================================================================= +void BRepMesh_CurveTessellator::splitSegment ( + const Handle (Geom_Surface)& theSurf, + const Handle (Geom2d_Curve)& theCurve2d, + const Standard_Real theFirst, + const Standard_Real theLast, + const Standard_Integer theNbIter) +{ + // limit iteration depth + if (theNbIter > 10) + { + return; + } + + gp_Pnt2d uvf, uvl, uvm; + gp_Pnt P3dF, P3dL, midP3d, midP3dFromSurf; + Standard_Real midpar; + + if (Abs(theLast - theFirst) < 2 * Precision::PConfusion()) + { + return; + } + + if ((theCurve2d->FirstParameter() - theFirst > Precision::PConfusion()) || + (theLast - theCurve2d->LastParameter() > Precision::PConfusion())) + { + // E.g. test bugs moddata_3 bug30133 + return; + } + + theCurve2d->D0 (theFirst, uvf); + theCurve2d->D0 (theLast, uvl); + + P3dF = theSurf->Value (uvf.X (), uvf.Y ()); + P3dL = theSurf->Value (uvl.X (), uvl.Y ()); + + if (P3dF.SquareDistance(P3dL) < mySquareMinSize) + { + return; + } + + uvm = gp_Pnt2d ((uvf.XY () + uvl.XY ())*0.5); + midP3dFromSurf = theSurf->Value (uvm.X (), uvm.Y ()); + + gp_XYZ Vec1 = midP3dFromSurf.XYZ () - P3dF.XYZ (); + if (Vec1.SquareModulus() < mySquareMinSize) + { + return; + } + + gp_XYZ aVec = P3dL.XYZ () - P3dF.XYZ (); + aVec.Normalize (); + + Standard_Real aModulus = Vec1.Dot (aVec); + gp_XYZ aProj = aVec * aModulus; + gp_XYZ aDist = Vec1 - aProj; + + if (aDist.SquareModulus() < mySquareEdgeDef) + { + return; + } + + midpar = (theFirst + theLast) * 0.5; + myCurve.D0 (midpar, midP3d); + myDiscretTool.AddPoint (midP3d, midpar, Standard_False); + + splitSegment (theSurf, theCurve2d, theFirst, midpar, theNbIter + 1); + splitSegment (theSurf, theCurve2d, midpar, theLast, theNbIter + 1); +} diff --git a/src/BRepMesh/BRepMesh_CurveTessellator.hxx b/src/BRepMesh/BRepMesh_CurveTessellator.hxx new file mode 100644 index 0000000000..4a666be6b8 --- /dev/null +++ b/src/BRepMesh/BRepMesh_CurveTessellator.hxx @@ -0,0 +1,110 @@ +// Created on: 2016-04-19 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _BRepMesh_EdgeTessellator_HeaderFile +#define _BRepMesh_EdgeTessellator_HeaderFile + +#include +#include +#include +#include +#include + +class TopoDS_Face; +class Geom_Surface; +class Geom2d_Curve; +struct IMeshTools_Parameters; + +//! Auxiliary class performing tessellation of passed edge according to specified parameters. +class BRepMesh_CurveTessellator : public IMeshTools_CurveTessellator +{ +public: + + //! Constructor. + Standard_EXPORT BRepMesh_CurveTessellator( + const IMeshData::IEdgeHandle& theEdge, + const IMeshTools_Parameters& theParameters); + + //! Constructor. + Standard_EXPORT BRepMesh_CurveTessellator ( + const IMeshData::IEdgeHandle& theEdge, + const TopAbs_Orientation theOrientation, + const IMeshData::IFaceHandle& theFace, + const IMeshTools_Parameters& theParameters); + + //! Destructor. + Standard_EXPORT virtual ~BRepMesh_CurveTessellator (); + + //! Returns number of tessellation points. + Standard_EXPORT virtual Standard_Integer PointsNb () const Standard_OVERRIDE; + + //! Returns parameters of solution with the given index. + //! @param theIndex index of tessellation point. + //! @param theParameter parameters on PCurve corresponded to the solution. + //! @param thePoint tessellation point. + //! @return True in case of valid result, false elewhere. + Standard_EXPORT virtual Standard_Boolean Value ( + const Standard_Integer theIndex, + gp_Pnt& thePoint, + Standard_Real& theParameter) const Standard_OVERRIDE; + + DEFINE_STANDARD_RTTI_INLINE(BRepMesh_CurveTessellator, IMeshTools_CurveTessellator) + +private: + + //! Performs initialization of this tool. + void init(); + + //! Adds internal vertices to discrete polygon. + void addInternalVertices (); + + //Check deflection in 2d space for improvement of edge tesselation. + void splitByDeflection2d (); + + void splitSegment ( + const Handle (Geom_Surface)& theSurf, + const Handle (Geom2d_Curve)& theCurve2d, + const Standard_Real theFirst, + const Standard_Real theLast, + const Standard_Integer theNbIter); + + //! Checks whether the given point lies within tolerance of the vertex. + Standard_Boolean isInToleranceOfVertex ( + const gp_Pnt& thePoint, + const TopoDS_Vertex& theVertex) const; + +private: + + BRepMesh_CurveTessellator (const BRepMesh_CurveTessellator& theOther); + + void operator=(const BRepMesh_CurveTessellator& theOther); + +private: + + const IMeshData::IEdgeHandle& myDEdge; + const IMeshTools_Parameters& myParameters; + TopoDS_Edge myEdge; + BRepAdaptor_Curve myCurve; + GCPnts_TangentialDeflection myDiscretTool; + TopoDS_Vertex myFirstVertex; + TopoDS_Vertex myLastVertex; + Standard_Real mySquareEdgeDef; + Standard_Real mySquareMinSize; + Standard_Real myEdgeSqTol; + Standard_Real myFaceRangeU[2]; + Standard_Real myFaceRangeV[2]; +}; + +#endif \ No newline at end of file diff --git a/src/BRepMesh/BRepMesh_CustomBaseMeshAlgo.hxx b/src/BRepMesh/BRepMesh_CustomBaseMeshAlgo.hxx new file mode 100644 index 0000000000..e175091de9 --- /dev/null +++ b/src/BRepMesh/BRepMesh_CustomBaseMeshAlgo.hxx @@ -0,0 +1,70 @@ +// Created on: 2019-06-07 +// Copyright (c) 2019 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _BRepMesh_CustomBaseMeshAlgo_HeaderFile +#define _BRepMesh_CustomBaseMeshAlgo_HeaderFile + +#include +#include +#include + +#include +#include + +class BRepMesh_DataStructureOfDelaun; + +//! Class provides base fuctionality to build face triangulation using custom triangulation algorithm. +//! Performs generation of mesh using raw data from model. +class BRepMesh_CustomBaseMeshAlgo : public BRepMesh_ConstrainedBaseMeshAlgo +{ +public: + + //! Constructor. + Standard_EXPORT BRepMesh_CustomBaseMeshAlgo () + { + } + + //! Destructor. + Standard_EXPORT virtual ~BRepMesh_CustomBaseMeshAlgo () + { + } + + DEFINE_STANDARD_RTTI_INLINE(BRepMesh_CustomBaseMeshAlgo, BRepMesh_ConstrainedBaseMeshAlgo) + +protected: + + //! Generates mesh for the contour stored in data structure. + Standard_EXPORT virtual void generateMesh () Standard_OVERRIDE + { + const Handle (BRepMesh_DataStructureOfDelaun)& aStructure = this->getStructure (); + buildBaseTriangulation (); + + std::pair aCellsCount = this->getCellsCount (aStructure->NbNodes ()); + BRepMesh_Delaun aMesher (aStructure, aCellsCount.first, aCellsCount.second, Standard_False); + aMesher.ProcessConstraints (); + + BRepMesh_MeshTool aCleaner (aStructure); + aCleaner.EraseFreeLinks (); + + postProcessMesh (aMesher); + } + +protected: + + //! Builds base triangulation using custom triangulation algorithm. + Standard_EXPORT virtual void buildBaseTriangulation() = 0; +}; + +#endif diff --git a/src/BRepMesh/BRepMesh_CustomDelaunayBaseMeshAlgo.hxx b/src/BRepMesh/BRepMesh_CustomDelaunayBaseMeshAlgo.hxx new file mode 100644 index 0000000000..6bde7b90a8 --- /dev/null +++ b/src/BRepMesh/BRepMesh_CustomDelaunayBaseMeshAlgo.hxx @@ -0,0 +1,53 @@ +// Created on: 2019-06-07 +// Copyright (c) 2019 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _BRepMesh_CustomDelaunayBaseMeshAlgo_HeaderFile +#define _BRepMesh_CustomDelaunayBaseMeshAlgo_HeaderFile + +class BRepMesh_DataStructureOfDelaun; +class BRepMesh_Delaun; + +//! Class provides base fuctionality to build face triangulation using custom +//! triangulation algorithm with possibility to modify final mesh. +//! Performs generation of mesh using raw data from model. +template +class BRepMesh_CustomDelaunayBaseMeshAlgo : public BaseAlgo +{ +public: + + //! Constructor. + BRepMesh_CustomDelaunayBaseMeshAlgo () + { + } + + //! Destructor. + virtual ~BRepMesh_CustomDelaunayBaseMeshAlgo () + { + } + +protected: + + //! Perfroms processing of generated mesh. + virtual void postProcessMesh(BRepMesh_Delaun& theMesher) + { + BaseAlgo::postProcessMesh (theMesher); + + const Handle(BRepMesh_DataStructureOfDelaun)& aStructure = this->getStructure(); + std::pair aCellsCount = this->getCellsCount (aStructure->NbNodes()); + theMesher.InitCirclesTool (aCellsCount.first, aCellsCount.second); + } +}; + +#endif diff --git a/src/BRepMesh/BRepMesh_CylinderRangeSplitter.cxx b/src/BRepMesh/BRepMesh_CylinderRangeSplitter.cxx new file mode 100644 index 0000000000..7016ad86c8 --- /dev/null +++ b/src/BRepMesh/BRepMesh_CylinderRangeSplitter.cxx @@ -0,0 +1,98 @@ +// Created on: 2016-07-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 +#include + +//======================================================================= +// Function: Reset +// Purpose : +//======================================================================= +void BRepMesh_CylinderRangeSplitter::Reset(const IMeshData::IFaceHandle& theDFace, + const IMeshTools_Parameters& theParameters) +{ + BRepMesh_DefaultRangeSplitter::Reset(theDFace, theParameters); + + const Standard_Real aRadius = GetDFace()->GetSurface()->Cylinder().Radius(); + myDu = GCPnts_TangentialDeflection::ArcAngularStep( + aRadius, GetDFace()->GetDeflection(), + theParameters.Angle, theParameters.MinSize); +} + +//======================================================================= +// Function: GenerateSurfaceNodes +// Purpose : +//======================================================================= +Handle(IMeshData::ListOfPnt2d) BRepMesh_CylinderRangeSplitter::GenerateSurfaceNodes( + const IMeshTools_Parameters& /*theParameters*/) const +{ + const std::pair& aRangeU = GetRangeU(); + const std::pair& aRangeV = GetRangeV(); + + const Standard_Real aRadius = GetDFace()->GetSurface()->Cylinder().Radius(); + + Standard_Integer nbU = 0; + Standard_Integer nbV = 0; + const Standard_Real su = aRangeU.second - aRangeU.first; + const Standard_Real sv = aRangeV.second - aRangeV.first; + const Standard_Real aArcLen = su * aRadius; + if (aArcLen > GetDFace()->GetDeflection()) + { + // Calculate parameters for iteration in U direction + nbU = (Standard_Integer) (su / myDu); + + /* + // Calculate parameters for iteration in V direction + const Standard_Real aDv = nbU*sv / aArcLen; + // Protection against overflow during casting to int in case + // of long cylinder with small radius. + nbV = aDv > static_cast (IntegerLast()) ? + 0 : (Standard_Integer) (aDv); + nbV = Min(nbV, 100 * nbU); + */ + } + + const Standard_Real Du = su / (nbU + 1); + const Standard_Real Dv = sv / (nbV + 1); + + const Handle(NCollection_IncAllocator) aTmpAlloc = + new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE); + Handle(IMeshData::ListOfPnt2d) aNodes = new IMeshData::ListOfPnt2d(aTmpAlloc); + + const Standard_Real aPasMaxV = aRangeV.second - Dv*0.5; + const Standard_Real aPasMaxU = aRangeU.second - Du*0.5; + for (Standard_Real aPasV = aRangeV.first + Dv; aPasV < aPasMaxV; aPasV += Dv) + { + for (Standard_Real aPasU = aRangeU.first + Du; aPasU < aPasMaxU; aPasU += Du) + { + aNodes->Append(gp_Pnt2d(aPasU, aPasV)); + } + } + + return aNodes; +} + +//======================================================================= +// Function: computeDelta +// Purpose : +//======================================================================= +void BRepMesh_CylinderRangeSplitter::computeDelta( + const Standard_Real /*theLengthU*/, + const Standard_Real theLengthV) +{ + const std::pair& aRangeV = GetRangeV(); + myDelta.first = myDu / Max(theLengthV, aRangeV.second - aRangeV.first); + myDelta.second = 1.; +} diff --git a/src/BRepMesh/BRepMesh_CylinderRangeSplitter.hxx b/src/BRepMesh/BRepMesh_CylinderRangeSplitter.hxx new file mode 100644 index 0000000000..87a94574f6 --- /dev/null +++ b/src/BRepMesh/BRepMesh_CylinderRangeSplitter.hxx @@ -0,0 +1,59 @@ +// Created on: 2016-07-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _BRepMesh_CylinderRangeSplitter_HeaderFile +#define _BRepMesh_CylinderRangeSplitter_HeaderFile + +#include +#include + +//! Auxiliary class extending default range splitter in +//! order to generate internal nodes for cylindrical surface. +class BRepMesh_CylinderRangeSplitter : public BRepMesh_DefaultRangeSplitter +{ +public: + + //! Constructor. + BRepMesh_CylinderRangeSplitter() + : myDu(1.) + { + } + + //! Destructor. + virtual ~BRepMesh_CylinderRangeSplitter() + { + } + + //! Resets this splitter. Must be called before first use. + Standard_EXPORT virtual void Reset(const IMeshData::IFaceHandle& theDFace, + const IMeshTools_Parameters& theParameters) Standard_OVERRIDE; + + //! Returns list of nodes generated using surface data and specified parameters. + Standard_EXPORT virtual Handle(IMeshData::ListOfPnt2d) GenerateSurfaceNodes( + const IMeshTools_Parameters& theParameters) const Standard_OVERRIDE; + +protected: + + //! Computes parametric delta taking length along U and V into account. + Standard_EXPORT virtual void computeDelta( + const Standard_Real theLengthU, + const Standard_Real theLengthV) Standard_OVERRIDE; + +private: + + Standard_Real myDu; +}; + +#endif diff --git a/src/BRepMesh/BRepMesh_DataStructureOfDelaun.cxx b/src/BRepMesh/BRepMesh_DataStructureOfDelaun.cxx index b7d2adb1e0..7a49413c95 100644 --- a/src/BRepMesh/BRepMesh_DataStructureOfDelaun.cxx +++ b/src/BRepMesh/BRepMesh_DataStructureOfDelaun.cxx @@ -15,18 +15,15 @@ // commercial license or contractual agreement. #include -#include #include #include +#include #include #include #include #include - -IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_DataStructureOfDelaun,Standard_Transient) - //======================================================================= //function : BRepMesh_DataStructureOfDelaun //purpose : @@ -39,9 +36,7 @@ BRepMesh_DataStructureOfDelaun::BRepMesh_DataStructureOfDelaun( myNodeLinks (theReservedNodeSize * 3, myAllocator), myLinks (theReservedNodeSize * 3, myAllocator), myDelLinks (myAllocator), - myElements (theReservedNodeSize * 2, myAllocator), - myElementsOfDomain(theReservedNodeSize * 2, myAllocator), - myLinksOfDomain (theReservedNodeSize * 2, myAllocator) + myElements (theReservedNodeSize * 2, myAllocator) { } @@ -55,7 +50,7 @@ Standard_Integer BRepMesh_DataStructureOfDelaun::AddNode( { const Standard_Integer aNodeId = myNodes->Add(theNode, isForceAdd); if (!myNodeLinks.IsBound(aNodeId)) - myNodeLinks.Bind(aNodeId, BRepMesh::ListOfInteger(myAllocator)); + myNodeLinks.Bind(aNodeId, IMeshData::ListOfInteger(myAllocator)); return aNodeId; } @@ -174,8 +169,8 @@ void BRepMesh_DataStructureOfDelaun::cleanLink( const Standard_Integer aNodeId = (i == 0) ? theLink.FirstNode() : theLink.LastNode(); - BRepMesh::ListOfInteger& aLinkList = linksConnectedTo(aNodeId); - BRepMesh::ListOfInteger::Iterator aLinkIt(aLinkList); + IMeshData::ListOfInteger& aLinkList = linksConnectedTo(aNodeId); + IMeshData::ListOfInteger::Iterator aLinkIt(aLinkList); for(; aLinkIt.More(); aLinkIt.Next()) { if (aLinkIt.Value() == theIndex) @@ -194,16 +189,11 @@ void BRepMesh_DataStructureOfDelaun::cleanLink( Standard_Integer BRepMesh_DataStructureOfDelaun::AddElement( const BRepMesh_Triangle& theElement) { - Standard_Integer aElementIndex = IndexOf(theElement); - if (aElementIndex > 0) - return aElementIndex; - - aElementIndex = myElements.Add(theElement); + myElements.Append(theElement); + Standard_Integer aElementIndex = myElements.Size(); myElementsOfDomain.Add(aElementIndex); - Standard_Integer e[3]; - Standard_Boolean o[3]; - theElement.Edges(e, o); + const Standard_Integer (&e)[3] = theElement.myEdges; for (Standard_Integer i = 0; i < 3; ++i) myLinks(e[i]).Append(aElementIndex); @@ -237,10 +227,7 @@ void BRepMesh_DataStructureOfDelaun::cleanElement( if (theElement.Movability() != BRepMesh_Free) return; - Standard_Integer e[3]; - Standard_Boolean o[3]; - theElement.Edges(e, o); - + const Standard_Integer(&e)[3] = theElement.myEdges; for (Standard_Integer i = 0; i < 3; ++i) removeElementIndex(theIndex, myLinks(e[i])); } @@ -274,20 +261,15 @@ Standard_Boolean BRepMesh_DataStructureOfDelaun::SubstituteElement( const BRepMesh_Triangle& aElement = GetElement(theIndex); if (aElement.Movability() == BRepMesh_Deleted) { - myElements.Substitute(theIndex, theNewElement); + myElements(theIndex) = theNewElement; return Standard_True; } - if (IndexOf(theNewElement) != 0) - return Standard_False; - cleanElement(theIndex, aElement); // Warning: here new element and old element should have different Hash code - myElements.Substitute(theIndex, theNewElement); + myElements(theIndex) = theNewElement; - Standard_Integer e[3]; - Standard_Boolean o[3]; - theNewElement.Edges(e, o); + const Standard_Integer(&e)[3] = theNewElement.myEdges; for (Standard_Integer i = 0; i < 3; ++i) myLinks(e[i]).Append(theIndex); @@ -302,9 +284,8 @@ void BRepMesh_DataStructureOfDelaun::ElementNodes( const BRepMesh_Triangle& theElement, Standard_Integer (&theNodes)[3]) { - Standard_Integer e[3]; - Standard_Boolean o[3]; - theElement.Edges(e, o); + const Standard_Integer(&e)[3] = theElement.myEdges; + const Standard_Boolean(&o)[3] = theElement.myOrientations; const BRepMesh_Edge& aLink1 = GetLink(e[0]); if (o[0]) @@ -331,16 +312,14 @@ void BRepMesh_DataStructureOfDelaun::ElementNodes( //======================================================================= void BRepMesh_DataStructureOfDelaun::ClearDomain() { - BRepMesh::MapOfInteger aFreeEdges; - BRepMesh::MapOfInteger::Iterator aElementIt(myElementsOfDomain); + IMeshData::MapOfInteger aFreeEdges; + IMeshData::IteratorOfMapOfInteger aElementIt(myElementsOfDomain); for (; aElementIt.More(); aElementIt.Next()) { const Standard_Integer aElementId = aElementIt.Key(); BRepMesh_Triangle& aElement = (BRepMesh_Triangle&)GetElement(aElementId); - Standard_Integer e[3]; - Standard_Boolean o[3]; - aElement.Edges(e, o); + const Standard_Integer(&e)[3] = aElement.myEdges; for (Standard_Integer i = 0; i < 3; ++i) aFreeEdges.Add(e[i]); @@ -350,7 +329,7 @@ void BRepMesh_DataStructureOfDelaun::ClearDomain() } myElementsOfDomain.Clear(); - BRepMesh::MapOfInteger::Iterator aEdgeIt(aFreeEdges); + IMeshData::IteratorOfMapOfInteger aEdgeIt(aFreeEdges); for (; aEdgeIt.More(); aEdgeIt.Next()) RemoveLink(aEdgeIt.Key()); } @@ -390,7 +369,7 @@ void BRepMesh_DataStructureOfDelaun::clearDeletedLinks() --aLastLiveItem; const Standard_Integer aLastLiveItemId = aLastLiveItem + 1; - BRepMesh::ListOfInteger::Iterator aLinkIt; + IMeshData::ListOfInteger::Iterator aLinkIt; // update link references for (Standard_Integer i = 0; i < 2; ++i) { @@ -411,10 +390,9 @@ void BRepMesh_DataStructureOfDelaun::clearDeletedLinks() // update elements references for(Standard_Integer j = 1, jn = aPair.Extent(); j <= jn; ++j) { - const BRepMesh_Triangle& aElement = GetElement(aPair.Index(j)); - Standard_Integer e[3]; Standard_Boolean o[3]; + const BRepMesh_Triangle& aElement = GetElement(aPair.Index(j)); aElement.Edges(e, o); for (Standard_Integer i = 0; i < 3; ++i) { @@ -425,8 +403,7 @@ void BRepMesh_DataStructureOfDelaun::clearDeletedLinks() } } - myElements.Substitute(aLinkIt.Value(), - BRepMesh_Triangle(e, o, aElement.Movability())); + myElements(aLinkIt.Value()) = BRepMesh_Triangle(e, o, aElement.Movability()); } } } @@ -437,8 +414,8 @@ void BRepMesh_DataStructureOfDelaun::clearDeletedLinks() //======================================================================= void BRepMesh_DataStructureOfDelaun::clearDeletedNodes() { - BRepMesh::ListOfInteger& aDelNodes = - (BRepMesh::ListOfInteger&)myNodes->GetListOfDelNodes(); + IMeshData::ListOfInteger& aDelNodes = + (IMeshData::ListOfInteger&)myNodes->GetListOfDelNodes(); Standard_Integer aLastLiveItem = NbNodes(); while (!aDelNodes.IsEmpty()) @@ -459,7 +436,7 @@ void BRepMesh_DataStructureOfDelaun::clearDeletedNodes() continue; BRepMesh_Vertex aNode = GetNode(aLastLiveItem); - BRepMesh::ListOfInteger& aLinkList = linksConnectedTo(aLastLiveItem); + IMeshData::ListOfInteger& aLinkList = linksConnectedTo(aLastLiveItem); myNodes->RemoveLast(); --aLastLiveItem; @@ -468,7 +445,7 @@ void BRepMesh_DataStructureOfDelaun::clearDeletedNodes() myNodeLinks.ChangeFind(aDelItem) = aLinkList; const Standard_Integer aLastLiveItemId = aLastLiveItem + 1; - BRepMesh::ListOfInteger::Iterator aLinkIt(aLinkList); + IMeshData::ListOfInteger::Iterator aLinkIt(aLinkList); for (; aLinkIt.More(); aLinkIt.Next()) { const Standard_Integer aLinkId = aLinkIt.Value(); @@ -495,14 +472,14 @@ void BRepMesh_DataStructureOfDelaun::Statistics(Standard_OStream& theStream) con { theStream << " Map of nodes : \n"; myNodes->Statistics(theStream); - theStream << "\n Deleted nodes : " << myNodes->GetListOfDelNodes().Extent() << endl; + theStream << "\n Deleted nodes : " << myNodes->GetListOfDelNodes().Extent() << std::endl; theStream << "\n\n Map of Links : \n"; myLinks.Statistics(theStream); - theStream << "\n Deleted links : " << myDelLinks.Extent() << endl; + theStream << "\n Deleted links : " << myDelLinks.Extent() << std::endl; theStream << "\n\n Map of elements : \n"; - myElements.Statistics(theStream); + theStream << "\n Elements : " << myElements.Size() << std::endl; } //======================================================================= @@ -521,7 +498,7 @@ Standard_CString BRepMesh_Dump(void* theMeshHandlePtr, return "Error: file name or mesh data is null"; } - Handle(BRepMesh_DataStructureOfDelaun) aMeshData = + Handle(BRepMesh_DataStructureOfDelaun) aMeshData = *(Handle(BRepMesh_DataStructureOfDelaun)*)theMeshHandlePtr; if (aMeshData.IsNull()) @@ -547,10 +524,10 @@ Standard_CString BRepMesh_Dump(void* theMeshHandlePtr, } else { - BRepMesh::MapOfInteger::Iterator aLinksIt(aMeshData->LinksOfDomain()); + IMeshData::IteratorOfMapOfInteger aLinksIt(aMeshData->LinksOfDomain()); for (; aLinksIt.More(); aLinksIt.Next()) { - const BRepMesh_Edge& aLink = aMeshData->GetLink(aLinksIt.Value()); + const BRepMesh_Edge& aLink = aMeshData->GetLink(aLinksIt.Key()); gp_Pnt aPnt[2]; for (Standard_Integer i = 0; i < 2; ++i) { @@ -578,3 +555,9 @@ Standard_CString BRepMesh_Dump(void* theMeshHandlePtr, return theFileNameStr; } + +void BRepMesh_DataStructureOfDelaun::Dump(Standard_CString theFileNameStr) +{ + Handle(BRepMesh_DataStructureOfDelaun) aMeshData (this); + BRepMesh_Dump((void*)&aMeshData, theFileNameStr); +} diff --git a/src/BRepMesh/BRepMesh_DataStructureOfDelaun.hxx b/src/BRepMesh/BRepMesh_DataStructureOfDelaun.hxx index 60b98f230b..cc6b714153 100644 --- a/src/BRepMesh/BRepMesh_DataStructureOfDelaun.hxx +++ b/src/BRepMesh/BRepMesh_DataStructureOfDelaun.hxx @@ -14,17 +14,14 @@ #ifndef _BRepMesh_DataStructureOfDelaun_HeaderFile #define _BRepMesh_DataStructureOfDelaun_HeaderFile -#include -#include -#include #include #include #include #include -#include +#include +#include class BRepMesh_Vertex; -class BRepMesh_VertexTool; class BRepMesh_Edge; //! Describes the data structure necessary for the mesh algorithms in @@ -101,14 +98,14 @@ public: //! @name API for accessing mesh nodes. if (isForce || myNodes->FindKey(theIndex).Movability() == BRepMesh_Free) { if (LinksConnectedTo(theIndex).Extent()==0) - myNodes->Delete(theIndex); + myNodes->DeleteVertex(theIndex); } } //! Get list of links attached to the node with the given index. //! @param theIndex index of node whose links should be retrieved. //! @return list of links attached to the node. - inline const BRepMesh::ListOfInteger& LinksConnectedTo( + inline const IMeshData::ListOfInteger& LinksConnectedTo( const Standard_Integer theIndex) const { return linksConnectedTo(theIndex); @@ -145,7 +142,7 @@ public: //! @name API for accessing mesh links. } //! Returns map of indices of links registered in mesh. - inline const BRepMesh::MapOfInteger& LinksOfDomain() const + inline const IMeshData::MapOfInteger& LinksOfDomain() const { return myLinksOfDomain; } @@ -181,7 +178,7 @@ public: //! @name API for accessing mesh elements. //! Returns number of links. inline Standard_Integer NbElements() const { - return myElements.Extent(); + return myElements.Size(); } //! Adds element to the mesh if it is not already in the mesh. @@ -189,24 +186,16 @@ public: //! @name API for accessing mesh elements. //! @return index of the element in the structure. Standard_EXPORT Standard_Integer AddElement(const BRepMesh_Triangle& theElement); - //! Finds the index of the given element. - //! @param theElement element to find. - //! @return index of the given element of zero if element is not in the mesh. - Standard_Integer IndexOf(const BRepMesh_Triangle& theElement) const - { - return myElements.FindIndex(theElement); - } - //! Get element by the index. //! @param theIndex index of an element. //! @return element with the given index. const BRepMesh_Triangle& GetElement(const Standard_Integer theIndex) { - return myElements.FindKey(theIndex); + return myElements.ChangeValue(theIndex - 1); } //! Returns map of indices of elements registered in mesh. - inline const BRepMesh::MapOfInteger& ElementsOfDomain() const + inline const IMeshData::MapOfInteger& ElementsOfDomain() const { return myElementsOfDomain; } @@ -229,6 +218,8 @@ public: //! @name API for accessing mesh elements. const BRepMesh_Triangle& theElement, Standard_Integer (&theNodes)[3]); + Standard_EXPORT void Dump(Standard_CString theFileNameStr); + public: //! @name Auxilary API @@ -244,7 +235,7 @@ public: //! @name Auxilary API } //! Gives the data structure for initialization of cell size and tolerance. - inline BRepMesh::HVertexTool& Data() + inline const Handle(BRepMesh_VertexTool)& Data() { return myNodes; } @@ -260,17 +251,17 @@ public: //! @name Auxilary API clearDeletedNodes(); } - DEFINE_STANDARD_RTTIEXT(BRepMesh_DataStructureOfDelaun,Standard_Transient) + DEFINE_STANDARD_RTTI_INLINE(BRepMesh_DataStructureOfDelaun, Standard_Transient) private: //! Get list of links attached to the node with the given index. //! @param theIndex index of node whose links should be retrieved. //! @return list of links attached to the node. - inline BRepMesh::ListOfInteger& linksConnectedTo( + inline IMeshData::ListOfInteger& linksConnectedTo( const Standard_Integer theIndex) const { - return (BRepMesh::ListOfInteger&)myNodeLinks.Find(theIndex); + return (IMeshData::ListOfInteger&)myNodeLinks.Find(theIndex); } //! Substitutes deleted links by the last one from corresponding map @@ -305,15 +296,13 @@ private: private: Handle(NCollection_IncAllocator) myAllocator; - BRepMesh::HVertexTool myNodes; - BRepMesh::DMapOfIntegerListOfInteger myNodeLinks; - BRepMesh::IDMapOfLink myLinks; - BRepMesh::ListOfInteger myDelLinks; - BRepMesh::IMapOfElement myElements; - BRepMesh::MapOfInteger myElementsOfDomain; - BRepMesh::MapOfInteger myLinksOfDomain; + Handle(BRepMesh_VertexTool) myNodes; + IMeshData::DMapOfIntegerListOfInteger myNodeLinks; + IMeshData::IDMapOfLink myLinks; + IMeshData::ListOfInteger myDelLinks; + IMeshData::VectorOfElements myElements; + IMeshData::MapOfInteger myElementsOfDomain; + IMeshData::MapOfInteger myLinksOfDomain; }; -DEFINE_STANDARD_HANDLE(BRepMesh_DataStructureOfDelaun,Standard_Transient) - #endif diff --git a/src/BRepMesh/BRepMesh_DefaultRangeSplitter.cxx b/src/BRepMesh/BRepMesh_DefaultRangeSplitter.cxx new file mode 100644 index 0000000000..a72cdfec2d --- /dev/null +++ b/src/BRepMesh/BRepMesh_DefaultRangeSplitter.cxx @@ -0,0 +1,252 @@ +// Created on: 2016-07-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 + +#include +#include +#include + +//======================================================================= +// Function: Reset +// Purpose : +//======================================================================= +void BRepMesh_DefaultRangeSplitter::Reset(const IMeshData::IFaceHandle& theDFace, + const IMeshTools_Parameters& /*theParameters*/) +{ + myDFace = theDFace; + myRangeU.first = myRangeV.first = 1.e100; + myRangeU.second = myRangeV.second = -1.e100; + myDelta.first = myDelta.second = 1.; + myTolerance.first = myTolerance.second = Precision::Confusion(); +} + +//======================================================================= +// Function: AddPoint +// Purpose : +//======================================================================= +void BRepMesh_DefaultRangeSplitter::AddPoint(const gp_Pnt2d& thePoint) +{ + myRangeU.first = Min(thePoint.X(), myRangeU.first); + myRangeU.second = Max(thePoint.X(), myRangeU.second); + myRangeV.first = Min(thePoint.Y(), myRangeV.first); + myRangeV.second = Max(thePoint.Y(), myRangeV.second); +} + +//======================================================================= +// Function: AdjustRange +// Purpose : +//======================================================================= +void BRepMesh_DefaultRangeSplitter::AdjustRange() +{ + const Handle(BRepAdaptor_HSurface)& aSurface = GetSurface(); + updateRange(aSurface->FirstUParameter(), aSurface->LastUParameter(), + aSurface->IsUPeriodic(), myRangeU.first, myRangeU.second); + + if (myRangeU.second < myRangeU.first) + { + myIsValid = Standard_False; + return; + } + + updateRange(aSurface->FirstVParameter(), aSurface->LastVParameter(), + aSurface->IsVPeriodic(), myRangeV.first, myRangeV.second); + + if (myRangeV.second < myRangeV.first) + { + myIsValid = Standard_False; + return; + } + + const Standard_Real aLengthU = computeLengthU(); + const Standard_Real aLengthV = computeLengthV(); + myIsValid = aLengthU > Precision::PConfusion () && aLengthV > Precision::PConfusion (); + + if (myIsValid) + { + computeTolerance(aLengthU, aLengthV); + computeDelta (aLengthU, aLengthV); + } +} + +//======================================================================= +// Function: IsValid +// Purpose : +//======================================================================= +Standard_Boolean BRepMesh_DefaultRangeSplitter::IsValid() +{ + return myIsValid; +} + +//======================================================================= +// Function: Scale +// Purpose : +//======================================================================= +gp_Pnt2d BRepMesh_DefaultRangeSplitter::Scale(const gp_Pnt2d& thePoint, + const Standard_Boolean isToFaceBasis) const +{ + return isToFaceBasis ? + gp_Pnt2d ((thePoint.X () - myRangeU.first) / myDelta.first, + (thePoint.Y () - myRangeV.first) / myDelta.second) : + gp_Pnt2d (thePoint.X () * myDelta.first + myRangeU.first, + thePoint.Y () * myDelta.second + myRangeV.first); +} + +//======================================================================= +// Function: GenerateSurfaceNodes +// Purpose : +//======================================================================= +Handle(IMeshData::ListOfPnt2d) BRepMesh_DefaultRangeSplitter::GenerateSurfaceNodes( + const IMeshTools_Parameters& /*theParameters*/) const +{ + return Handle(IMeshData::ListOfPnt2d)(); +} + +//======================================================================= +// Function: computeTolerance +// Purpose : +//======================================================================= +void BRepMesh_DefaultRangeSplitter::computeTolerance( + const Standard_Real /*theLenU*/, + const Standard_Real /*theLenV*/) +{ + const Standard_Real aDiffU = myRangeU.second - myRangeU.first; + const Standard_Real aDiffV = myRangeV.second - myRangeV.first; + + const Standard_Real aDeflectionUV = 1.e-05; + myTolerance.first = Max(Min(aDeflectionUV, 0.1 * aDiffU), 1e-7 * aDiffU); + myTolerance.second = Max(Min(aDeflectionUV, 0.1 * aDiffV), 1e-7 * aDiffV); +} + +//======================================================================= +// Function: computeDelta +// Purpose : +//======================================================================= +void BRepMesh_DefaultRangeSplitter::computeDelta( + const Standard_Real theLengthU, + const Standard_Real theLengthV) +{ + const Standard_Real aDiffU = myRangeU.second - myRangeU.first; + const Standard_Real aDiffV = myRangeV.second - myRangeV.first; + + myDelta.first = aDiffU / (theLengthU < myTolerance.first ? 1. : theLengthU); + myDelta.second = aDiffV / (theLengthV < myTolerance.second ? 1. : theLengthV); +} + +//======================================================================= +// Function: computeLengthU +// Purpose : +//======================================================================= +Standard_Real BRepMesh_DefaultRangeSplitter::computeLengthU() +{ + Standard_Real longu = 0.0; + gp_Pnt P11, P12, P21, P22, P31, P32; + + Standard_Real du = 0.05 * (myRangeU.second - myRangeU.first); + Standard_Real dfvave = 0.5 * (myRangeV.second + myRangeV.first); + Standard_Real dfucur; + Standard_Integer i1; + + const Handle(BRepAdaptor_HSurface)& gFace = GetSurface(); + gFace->D0(myRangeU.first, myRangeV.first, P11); + gFace->D0(myRangeU.first, dfvave, P21); + gFace->D0(myRangeU.first, myRangeV.second, P31); + for (i1 = 1, dfucur = myRangeU.first + du; i1 <= 20; i1++, dfucur += du) + { + gFace->D0(dfucur, myRangeV.first, P12); + gFace->D0(dfucur, dfvave, P22); + gFace->D0(dfucur, myRangeV.second, P32); + longu += (P11.Distance(P12) + P21.Distance(P22) + P31.Distance(P32)); + P11 = P12; + P21 = P22; + P31 = P32; + } + + return longu / 3.; +} + +//======================================================================= +// Function: computeLengthV +// Purpose : +//======================================================================= +Standard_Real BRepMesh_DefaultRangeSplitter::computeLengthV() +{ + Standard_Real longv = 0.0; + gp_Pnt P11, P12, P21, P22, P31, P32; + + Standard_Real dv = 0.05 * (myRangeV.second - myRangeV.first); + Standard_Real dfuave = 0.5 * (myRangeU.second + myRangeU.first); + Standard_Real dfvcur; + Standard_Integer i1; + + const Handle(BRepAdaptor_HSurface)& gFace = GetSurface(); + gFace->D0(myRangeU.first, myRangeV.first, P11); + gFace->D0(dfuave, myRangeV.first, P21); + gFace->D0(myRangeU.second, myRangeV.first, P31); + for (i1 = 1, dfvcur = myRangeV.first + dv; i1 <= 20; i1++, dfvcur += dv) + { + gFace->D0(myRangeU.first, dfvcur, P12); + gFace->D0(dfuave, dfvcur, P22); + gFace->D0(myRangeU.second, dfvcur, P32); + longv += (P11.Distance(P12) + P21.Distance(P22) + P31.Distance(P32)); + P11 = P12; + P21 = P22; + P31 = P32; + } + + return longv / 3.; +} + +//======================================================================= +// Function: updateRange +// Purpose : +//======================================================================= +void BRepMesh_DefaultRangeSplitter::updateRange( + const Standard_Real theGeomFirst, + const Standard_Real theGeomLast, + const Standard_Boolean isPeriodic, + Standard_Real& theDiscreteFirst, + Standard_Real& theDiscreteLast) +{ + if (theDiscreteFirst < theGeomFirst || + theDiscreteLast > theGeomLast) + { + if (isPeriodic) + { + if ((theDiscreteLast - theDiscreteFirst) > (theGeomLast - theGeomFirst)) + { + theDiscreteLast = theDiscreteFirst + (theGeomLast - theGeomFirst); + } + } + else + { + if ((theDiscreteFirst < theGeomLast) && (theDiscreteLast > theGeomFirst)) + { + //Protection against the faces whose pcurve is out of the surface's domain + //(see issue #23675 and test cases "bugs iges buc60820*") + + if (theGeomFirst > theDiscreteFirst) + { + theDiscreteFirst = theGeomFirst; + } + + if (theGeomLast < theDiscreteLast) + { + theDiscreteLast = theGeomLast; + } + } + } + } +} diff --git a/src/BRepMesh/BRepMesh_DefaultRangeSplitter.hxx b/src/BRepMesh/BRepMesh_DefaultRangeSplitter.hxx new file mode 100644 index 0000000000..db9229ae86 --- /dev/null +++ b/src/BRepMesh/BRepMesh_DefaultRangeSplitter.hxx @@ -0,0 +1,150 @@ +// Created on: 2016-07-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _BRepMesh_DefaultRangeSplitter_HeaderFile +#define _BRepMesh_DefaultRangeSplitter_HeaderFile + +#include +#include +#include +#include +#include + +struct IMeshTools_Parameters; + +//! Default tool to define range of discrete face model and +//! obtain grid points distributed within this range. +class BRepMesh_DefaultRangeSplitter +{ +public: + + //! Constructor. + BRepMesh_DefaultRangeSplitter() + : myIsValid (Standard_True) + { + } + + //! Destructor. + virtual ~BRepMesh_DefaultRangeSplitter() + { + } + + //! Resets this splitter. Must be called before first use. + Standard_EXPORT virtual void Reset(const IMeshData::IFaceHandle& theDFace, + const IMeshTools_Parameters& theParameters); + + //! Registers border point. + Standard_EXPORT virtual void AddPoint(const gp_Pnt2d& thePoint); + + //! Updates discrete range of surface according to its geometric range. + Standard_EXPORT virtual void AdjustRange(); + + //! Returns True if computed range is valid. + Standard_EXPORT virtual Standard_Boolean IsValid(); + + //! Scales the given point from real parametric space + //! to face basis and otherwise. + //! @param thePoint point to be scaled. + //! @param isToFaceBasis if TRUE converts point to face basis, + //! otherwise performs reverse conversion. + //! @return scaled point. + Standard_EXPORT gp_Pnt2d Scale(const gp_Pnt2d& thePoint, + const Standard_Boolean isToFaceBasis) const; + + //! Returns list of nodes generated using surface data and specified parameters. + //! By default returns null ptr. + Standard_EXPORT virtual Handle(IMeshData::ListOfPnt2d) GenerateSurfaceNodes( + const IMeshTools_Parameters& theParameters) const; + + //! Returns point in 3d space corresponded to the given + //! point defined in parameteric space of surface. + inline gp_Pnt Point(const gp_Pnt2d& thePoint2d) const + { + return GetSurface()->Value(thePoint2d.X(), thePoint2d.Y()); + } + +protected: + + //! Computes parametric tolerance taking length along U and V into account. + virtual void computeTolerance( + const Standard_Real theLenU, + const Standard_Real theLenV); + + //! Computes parametric delta taking length along U and V and value of tolerance into account. + virtual void computeDelta( + const Standard_Real theLengthU, + const Standard_Real theLengthV); + +public: + //! Returns face model. + inline const IMeshData::IFaceHandle& GetDFace() const + { + return myDFace; + } + + //! Returns surface. + inline const Handle(BRepAdaptor_HSurface)& GetSurface() const + { + return myDFace->GetSurface(); + } + + //! Returns U range. + inline const std::pair& GetRangeU() const + { + return myRangeU; + } + + //! Returns V range. + inline const std::pair& GetRangeV() const + { + return myRangeV; + } + + //! Returns delta. + inline const std::pair& GetDelta () const + { + return myDelta; + } + + inline const std::pair& GetToleranceUV() const + { + return myTolerance; + } + +private: + + //! Computes length along U direction. + Standard_Real computeLengthU(); + + //! Computes length along V direction. + Standard_Real computeLengthV(); + + //! Updates discrete range of surface according to its geometric range. + void updateRange(const Standard_Real theGeomFirst, + const Standard_Real theGeomLast, + const Standard_Boolean isPeriodic, + Standard_Real& theDiscreteFirst, + Standard_Real& theDiscreteLast); + +protected: + IMeshData::IFaceHandle myDFace; + std::pair myRangeU; + std::pair myRangeV; + std::pair myDelta; + std::pair myTolerance; + Standard_Boolean myIsValid; +}; + +#endif \ No newline at end of file diff --git a/src/BRepMesh/BRepMesh_Deflection.cxx b/src/BRepMesh/BRepMesh_Deflection.cxx new file mode 100644 index 0000000000..9110114056 --- /dev/null +++ b/src/BRepMesh/BRepMesh_Deflection.cxx @@ -0,0 +1,162 @@ +// Created on: 2016-04-19 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 + +#include +#include +#include +#include +#include +#include +#include +#include + +//======================================================================= +//function : RelativeEdgeDeflection +//purpose : +//======================================================================= +Standard_Real BRepMesh_Deflection::ComputeAbsoluteDeflection( + const TopoDS_Shape& theShape, + const Standard_Real theRelativeDeflection, + const Standard_Real theMaxShapeSize) +{ + if (theShape.IsNull()) + { + return theRelativeDeflection; + } + + Bnd_Box aBox; + BRepBndLib::Add (theShape, aBox, Standard_False); + + Standard_Real aShapeSize = theRelativeDeflection; + BRepMesh_ShapeTool::BoxMaxDimension (aBox, aShapeSize); + + // Adjust resulting value in relation to the total size + + Standard_Real aX1, aY1, aZ1, aX2, aY2, aZ2; + aBox.Get(aX1, aY1, aZ1, aX2, aY2, aZ2); + const Standard_Real aMaxShapeSize = (theMaxShapeSize > 0.0) ? theMaxShapeSize : + Max(aX2 - aX1, Max(aY2 - aY1, aZ2 - aZ1)); + + Standard_Real anAdjustmentCoefficient = aMaxShapeSize / (2 * aShapeSize); + if (anAdjustmentCoefficient < 0.5) + { + anAdjustmentCoefficient = 0.5; + } + else if (anAdjustmentCoefficient > 2.) + { + anAdjustmentCoefficient = 2.; + } + + return (anAdjustmentCoefficient * aShapeSize * theRelativeDeflection); +} + +//======================================================================= +// Function: ComputeDeflection (edge) +// Purpose : +//======================================================================= +void BRepMesh_Deflection::ComputeDeflection ( + const IMeshData::IEdgeHandle& theDEdge, + const Standard_Real theMaxShapeSize, + const IMeshTools_Parameters& theParameters) +{ + const Standard_Real aAngDeflection = theParameters.Angle; + Standard_Real aLinDeflection = + !theParameters.Relative ? theParameters.Deflection : + ComputeAbsoluteDeflection(theDEdge->GetEdge(), + theParameters.Deflection, + theMaxShapeSize); + + const TopoDS_Edge& anEdge = theDEdge->GetEdge(); + + TopoDS_Vertex aFirstVertex, aLastVertex; + TopExp::Vertices(anEdge, aFirstVertex, aLastVertex); + + Handle(Geom_Curve) aCurve; + Standard_Real aFirstParam, aLastParam; + if (BRepMesh_ShapeTool::Range(anEdge, aCurve, aFirstParam, aLastParam)) + { + const Standard_Real aDistF = aFirstVertex.IsNull() ? -1.0 : + BRep_Tool::Pnt(aFirstVertex).Distance(aCurve->Value(aFirstParam)); + const Standard_Real aDistL = aLastVertex.IsNull() ? -1.0 : + BRep_Tool::Pnt(aLastVertex).Distance(aCurve->Value(aLastParam)); + + const Standard_Real aVertexAdjustDistance = Max(aDistF, aDistL); + + aLinDeflection = Max(aVertexAdjustDistance, aLinDeflection); + } + + theDEdge->SetDeflection (aLinDeflection); + theDEdge->SetAngularDeflection (aAngDeflection); +} + +//======================================================================= +// Function: ComputeDeflection (wire) +// Purpose : +//======================================================================= +void BRepMesh_Deflection::ComputeDeflection ( + const IMeshData::IWireHandle& theDWire, + const IMeshTools_Parameters& theParameters) +{ + Standard_Real aWireDeflection = 0.; + if (theDWire->EdgesNb () > 0) + { + for (Standard_Integer aEdgeIt = 0; aEdgeIt < theDWire->EdgesNb(); ++aEdgeIt) + { + aWireDeflection += theDWire->GetEdge(aEdgeIt)->GetDeflection(); + } + + aWireDeflection /= theDWire->EdgesNb (); + } + else + { + aWireDeflection = theParameters.Deflection; + } + + theDWire->SetDeflection (aWireDeflection); +} + +//======================================================================= +// Function: ComputeDeflection (face) +// Purpose : +//======================================================================= +void BRepMesh_Deflection::ComputeDeflection ( + const IMeshData::IFaceHandle& theDFace, + const IMeshTools_Parameters& theParameters) +{ + Standard_Real aDeflection = theParameters.DeflectionInterior; + if (theParameters.Relative) + { + aDeflection = ComputeAbsoluteDeflection(theDFace->GetFace(), + aDeflection, -1.0); + } + + Standard_Real aFaceDeflection = 0.0; + if (theDFace->WiresNb () > 0) + { + for (Standard_Integer aWireIt = 0; aWireIt < theDFace->WiresNb(); ++aWireIt) + { + aFaceDeflection += theDFace->GetWire(aWireIt)->GetDeflection(); + } + + aFaceDeflection /= theDFace->WiresNb (); + } + + aFaceDeflection = Max(aDeflection, aFaceDeflection); + + theDFace->SetDeflection (Max(2.* BRepMesh_ShapeTool::MaxFaceTolerance( + theDFace->GetFace()), aFaceDeflection)); +} diff --git a/src/BRepMesh/BRepMesh_Deflection.hxx b/src/BRepMesh/BRepMesh_Deflection.hxx new file mode 100644 index 0000000000..35998a839b --- /dev/null +++ b/src/BRepMesh/BRepMesh_Deflection.hxx @@ -0,0 +1,64 @@ +// Created on: 2016-04-19 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _BRepMesh_Deflection_HeaderFile +#define _BRepMesh_Deflection_HeaderFile + +#include +#include +#include +#include + +class Bnd_Box; +class TopoDS_Face; +class TopoDS_Edge; +struct IMeshTools_Parameters; + +//! Auxiliary tool encompassing methods to compute deflection of shapes. +class BRepMesh_Deflection : public Standard_Transient +{ +public: + + //! Returns absolute deflection for theShape with respect to the + //! relative deflection and theMaxShapeSize. + //! @param theShape shape for that the deflection should be computed. + //! @param theRelativeDeflection relative deflection. + //! @param theMaxShapeSize maximum size of the whole shape. + //! @return absolute deflection for the shape. + Standard_EXPORT static Standard_Real ComputeAbsoluteDeflection ( + const TopoDS_Shape& theShape, + const Standard_Real theRelativeDeflection, + const Standard_Real theMaxShapeSize); + + //! Computes and updates deflection of the given discrete edge. + Standard_EXPORT static void ComputeDeflection ( + const IMeshData::IEdgeHandle& theDEdge, + const Standard_Real theMaxShapeSize, + const IMeshTools_Parameters& theParameters); + + //! Computes and updates deflection of the given discrete wire. + Standard_EXPORT static void ComputeDeflection ( + const IMeshData::IWireHandle& theDWire, + const IMeshTools_Parameters& theParameters); + + //! Computes and updates deflection of the given discrete face. + Standard_EXPORT static void ComputeDeflection ( + const IMeshData::IFaceHandle& theDFace, + const IMeshTools_Parameters& theParameters); + + DEFINE_STANDARD_RTTI_INLINE(BRepMesh_Deflection, Standard_Transient) +}; + +#endif \ No newline at end of file diff --git a/src/BRepMesh/BRepMesh_Delaun.cxx b/src/BRepMesh/BRepMesh_Delaun.cxx index 26d3fce6ea..c87bc6ce62 100644 --- a/src/BRepMesh/BRepMesh_Delaun.cxx +++ b/src/BRepMesh/BRepMesh_Delaun.cxx @@ -31,7 +31,6 @@ #include #include -#include #include #include @@ -79,18 +78,37 @@ namespace { } } // anonymous namespace +//======================================================================= +//function : BRepMesh_Delaun +//purpose : +//======================================================================= +BRepMesh_Delaun::BRepMesh_Delaun ( + const Handle(BRepMesh_DataStructureOfDelaun)& theOldMesh, + const Standard_Integer theCellsCountU, + const Standard_Integer theCellsCountV, + const Standard_Boolean isFillCircles) +: myMeshData ( theOldMesh ), + myCircles (new NCollection_IncAllocator( + IMeshData::MEMORY_BLOCK_SIZE_HUGE)) +{ + if (isFillCircles) + { + InitCirclesTool (theCellsCountU, theCellsCountV); + } +} + //======================================================================= //function : BRepMesh_Delaun //purpose : Creates the triangulation with an empty Mesh data structure //======================================================================= -BRepMesh_Delaun::BRepMesh_Delaun(BRepMesh::Array1OfVertexOfDelaun& theVertices) +BRepMesh_Delaun::BRepMesh_Delaun(IMeshData::Array1OfVertexOfDelaun& theVertices) : myCircles (theVertices.Length(), new NCollection_IncAllocator( - BRepMesh::MEMORY_BLOCK_SIZE_HUGE)) + IMeshData::MEMORY_BLOCK_SIZE_HUGE)) { if ( theVertices.Length() > 2 ) { myMeshData = new BRepMesh_DataStructureOfDelaun( - new NCollection_IncAllocator(BRepMesh::MEMORY_BLOCK_SIZE_HUGE), + new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE), theVertices.Length() ); Init( theVertices ); } @@ -101,13 +119,16 @@ BRepMesh_Delaun::BRepMesh_Delaun(BRepMesh::Array1OfVertexOfDelaun& theVertices) //purpose : Creates the triangulation with and existent Mesh data structure //======================================================================= BRepMesh_Delaun::BRepMesh_Delaun( - const Handle( BRepMesh_DataStructureOfDelaun )& theOldMesh, - BRepMesh::Array1OfVertexOfDelaun& theVertices) + const Handle(BRepMesh_DataStructureOfDelaun)& theOldMesh, + IMeshData::Array1OfVertexOfDelaun& theVertices) : myMeshData( theOldMesh ), - myCircles ( theVertices.Length(), theOldMesh->Allocator() ) + myCircles ( theVertices.Length(), new NCollection_IncAllocator( + IMeshData::MEMORY_BLOCK_SIZE_HUGE)) { if ( theVertices.Length() > 2 ) + { Init( theVertices ); + } } //======================================================================= @@ -115,93 +136,160 @@ BRepMesh_Delaun::BRepMesh_Delaun( //purpose : Creates the triangulation with and existent Mesh data structure //======================================================================= BRepMesh_Delaun::BRepMesh_Delaun( - const Handle( BRepMesh_DataStructureOfDelaun )& theOldMesh, - BRepMesh::Array1OfInteger& theVertexIndices) + const Handle(BRepMesh_DataStructureOfDelaun)& theOldMesh, + IMeshData::VectorOfInteger& theVertexIndices) : myMeshData( theOldMesh ), - myCircles ( theVertexIndices.Length(), theOldMesh->Allocator() ) + myCircles ( theVertexIndices.Length(), new NCollection_IncAllocator( + IMeshData::MEMORY_BLOCK_SIZE_HUGE)) { - if ( theVertexIndices.Length() > 2 ) - { - Bnd_Box2d aBox; - Standard_Integer anIndex = theVertexIndices.Lower(); - Standard_Integer anUpper = theVertexIndices.Upper(); - for ( ; anIndex <= anUpper; ++anIndex ) - aBox.Add( gp_Pnt2d( GetVertex( theVertexIndices( anIndex) ).Coord() ) ); + perform(theVertexIndices); +} - perform( aBox, theVertexIndices ); - } +//======================================================================= +//function : BRepMesh_Delaun +//purpose : Creates the triangulation with and existent Mesh data structure +//======================================================================= +BRepMesh_Delaun::BRepMesh_Delaun (const Handle (BRepMesh_DataStructureOfDelaun)& theOldMesh, + IMeshData::VectorOfInteger& theVertexIndices, + const Standard_Integer theCellsCountU, + const Standard_Integer theCellsCountV) +: myMeshData (theOldMesh), + myCircles (theVertexIndices.Length (), new NCollection_IncAllocator( + IMeshData::MEMORY_BLOCK_SIZE_HUGE)) +{ + perform (theVertexIndices, theCellsCountU, theCellsCountV); } //======================================================================= //function : Init //purpose : Initializes the triangulation with an Array of Vertex //======================================================================= -void BRepMesh_Delaun::Init(BRepMesh::Array1OfVertexOfDelaun& theVertices) +void BRepMesh_Delaun::Init(IMeshData::Array1OfVertexOfDelaun& theVertices) { - Bnd_Box2d aBox; Standard_Integer aLowerIdx = theVertices.Lower(); Standard_Integer anUpperIdx = theVertices.Upper(); - BRepMesh::Array1OfInteger aVertexIndexes( aLowerIdx, anUpperIdx ); + IMeshData::VectorOfInteger aVertexIndexes(theVertices.Size()); Standard_Integer anIndex = aLowerIdx; for ( ; anIndex <= anUpperIdx; ++anIndex ) { - aBox.Add( gp_Pnt2d( theVertices( anIndex ).Coord() ) ); - aVertexIndexes( anIndex ) = myMeshData->AddNode( theVertices( anIndex ) ); + aVertexIndexes.Append(myMeshData->AddNode( theVertices( anIndex ) )); } - perform( aBox, aVertexIndexes ); + perform( aVertexIndexes ); +} + +//======================================================================= +//function : InitCirclesTool +//purpose : +//======================================================================= +void BRepMesh_Delaun::InitCirclesTool (const Standard_Integer theCellsCountU, + const Standard_Integer theCellsCountV) +{ + Bnd_Box2d aBox; + for (Standard_Integer aNodeIt = 1; aNodeIt <= myMeshData->NbNodes(); ++aNodeIt) + { + aBox.Add (gp_Pnt2d (GetVertex (aNodeIt).Coord ())); + } + aBox.Enlarge (Precision); + + initCirclesTool (aBox, theCellsCountU, theCellsCountV); + + IMeshData::IteratorOfMapOfInteger aTriangleIt (myMeshData->ElementsOfDomain()); + for (; aTriangleIt.More(); aTriangleIt.Next()) + { + Standard_Integer aNodesIndices[3]; + const BRepMesh_Triangle& aTriangle = myMeshData->GetElement (aTriangleIt.Key()); + myMeshData->ElementNodes (aTriangle, aNodesIndices); + myCircles.Bind (aTriangleIt.Key(), + GetVertex( aNodesIndices[0] ).Coord(), + GetVertex( aNodesIndices[1] ).Coord(), + GetVertex( aNodesIndices[2] ).Coord()); + } +} + +//======================================================================= +//function : initCirclesTool +//purpose : +//======================================================================= +void BRepMesh_Delaun::initCirclesTool (const Bnd_Box2d& theBox, + const Standard_Integer theCellsCountU, + const Standard_Integer theCellsCountV) +{ + Standard_Real aMinX, aMinY, aMaxX, aMaxY; + theBox.Get ( aMinX, aMinY, aMaxX, aMaxY ); + const Standard_Real aDeltaX = aMaxX - aMinX; + const Standard_Real aDeltaY = aMaxY - aMinY; + + Standard_Integer aScaler = 2; + if ( myMeshData->NbNodes() > 100 ) + { + aScaler = 5; + } + else if( myMeshData->NbNodes() > 1000 ) + { + aScaler = 7; + } + + myCircles.SetMinMaxSize( gp_XY( aMinX, aMinY ), gp_XY( aMaxX, aMaxY ) ); + myCircles.SetCellSize ( aDeltaX / Max (theCellsCountU, aScaler), + aDeltaY / Max (theCellsCountV, aScaler)); } //======================================================================= //function : perform //purpose : Create super mesh and run triangulation procedure //======================================================================= -void BRepMesh_Delaun::perform(Bnd_Box2d& theBndBox, - BRepMesh::Array1OfInteger& theVertexIndexes) +void BRepMesh_Delaun::perform(IMeshData::VectorOfInteger& theVertexIndices, + const Standard_Integer theCellsCountU /* = -1 */, + const Standard_Integer theCellsCountV /* = -1 */) { - theBndBox.Enlarge( Precision ); - superMesh( theBndBox ); + if (theVertexIndices.Length () <= 2) + { + return; + } + + Bnd_Box2d aBox; + Standard_Integer anIndex = theVertexIndices.Lower (); + Standard_Integer anUpper = theVertexIndices.Upper (); + for (; anIndex <= anUpper; ++anIndex) + { + aBox.Add (gp_Pnt2d (GetVertex (theVertexIndices (anIndex)).Coord ())); + } + + aBox.Enlarge (Precision); + + initCirclesTool (aBox, theCellsCountU, theCellsCountV); + superMesh (aBox); ComparatorOfIndexedVertexOfDelaun aCmp(myMeshData); - std::make_heap(theVertexIndexes.begin(), theVertexIndexes.end(), aCmp); - std::sort_heap(theVertexIndexes.begin(), theVertexIndexes.end(), aCmp); + std::make_heap(theVertexIndices.begin(), theVertexIndices.end(), aCmp); + std::sort_heap(theVertexIndices.begin(), theVertexIndices.end(), aCmp); - compute( theVertexIndexes ); + compute( theVertexIndices ); } //======================================================================= //function : superMesh //purpose : Build the super mesh //======================================================================= -void BRepMesh_Delaun::superMesh( const Bnd_Box2d& theBox ) +void BRepMesh_Delaun::superMesh(const Bnd_Box2d& theBox) { Standard_Real aMinX, aMinY, aMaxX, aMaxY; - theBox.Get( aMinX, aMinY, aMaxX, aMaxY ); + theBox.Get ( aMinX, aMinY, aMaxX, aMaxY ); Standard_Real aDeltaX = aMaxX - aMinX; Standard_Real aDeltaY = aMaxY - aMinY; Standard_Real aDeltaMin = Min( aDeltaX, aDeltaY ); Standard_Real aDeltaMax = Max( aDeltaX, aDeltaY ); Standard_Real aDelta = aDeltaX + aDeltaY; - - myCircles.SetMinMaxSize( gp_XY( aMinX, aMinY ), gp_XY( aMaxX, aMaxY ) ); - - Standard_Integer aScaler = 2; - if ( myMeshData->NbNodes() > 100 ) - aScaler = 5; - else if( myMeshData->NbNodes() > 1000 ) - aScaler = 7; - - myCircles.SetCellSize( aDeltaX / aScaler, - aDeltaY / aScaler ); mySupVert[0] = myMeshData->AddNode( BRepMesh_Vertex( ( aMinX + aMaxX ) / 2, aMaxY + aDeltaMax, BRepMesh_Free ) ); - + mySupVert[1] = myMeshData->AddNode( BRepMesh_Vertex( aMinX - aDelta, aMinY - aDeltaMin, BRepMesh_Free ) ); - + mySupVert[2] = myMeshData->AddNode( BRepMesh_Vertex( aMaxX + aDelta, aMinY - aDeltaMin, BRepMesh_Free ) ); @@ -211,13 +299,13 @@ void BRepMesh_Delaun::superMesh( const Bnd_Box2d& theBox ) { Standard_Integer aFirstNode = aNodeId; Standard_Integer aLastNode = (aNodeId + 1) % 3; - Standard_Integer aLinkIndex = myMeshData->AddLink( BRepMesh_Edge( + Standard_Integer aLinkIndex = myMeshData->AddLink( BRepMesh_Edge( mySupVert[aFirstNode], mySupVert[aLastNode], BRepMesh_Free ) ); e[aNodeId] = Abs(aLinkIndex); o[aNodeId] = (aLinkIndex > 0); } - + mySupTrian = BRepMesh_Triangle(e, o, BRepMesh_Free); } @@ -227,15 +315,18 @@ void BRepMesh_Delaun::superMesh( const Bnd_Box2d& theBox ) // edges into the map. // When an edge is suppressed more than one time it is destroyed. //======================================================================= -void BRepMesh_Delaun::deleteTriangle(const Standard_Integer theIndex, - BRepMesh::MapOfIntegerInteger& theLoopEdges ) +void BRepMesh_Delaun::deleteTriangle(const Standard_Integer theIndex, + IMeshData::MapOfIntegerInteger& theLoopEdges ) { - myCircles.Delete( theIndex ); + if (!myCircles.IsEmpty()) + { + myCircles.Delete (theIndex); + } + + const BRepMesh_Triangle& aElement = GetTriangle(theIndex); + const Standard_Integer(&e)[3] = aElement.myEdges; + const Standard_Boolean(&o)[3] = aElement.myOrientations; - Standard_Integer e[3]; - Standard_Boolean o[3]; - GetTriangle( theIndex ).Edges( e, o ); - myMeshData->RemoveElement( theIndex ); for ( Standard_Integer i = 0; i < 3; ++i ) @@ -253,13 +344,14 @@ void BRepMesh_Delaun::deleteTriangle(const Standard_Integer theIndex, //purpose : Computes the triangulation and add the vertices edges and // triangles to the Mesh data structure //======================================================================= -void BRepMesh_Delaun::compute(BRepMesh::Array1OfInteger& theVertexIndexes) +void BRepMesh_Delaun::compute(IMeshData::VectorOfInteger& theVertexIndexes) { - // Insertion of edges of super triangles in the list of free edges: - BRepMesh::MapOfIntegerInteger aLoopEdges(10, myMeshData->Allocator()); - Standard_Integer e[3]; - Standard_Boolean o[3]; - mySupTrian.Edges( e, o ); + // Insertion of edges of super triangles in the list of free edges: + Handle(NCollection_IncAllocator) aAllocator = new NCollection_IncAllocator( + IMeshData::MEMORY_BLOCK_SIZE_HUGE); + + IMeshData::MapOfIntegerInteger aLoopEdges(10, aAllocator); + const Standard_Integer(&e)[3] = mySupTrian.myEdges; aLoopEdges.Bind( e[0], Standard_True ); aLoopEdges.Bind( e[1], Standard_True ); @@ -281,13 +373,13 @@ void BRepMesh_Delaun::compute(BRepMesh::Array1OfInteger& theVertexIndexes) aSelector.NeighboursOfNode( mySupVert[aSupVertId] ); aLoopEdges.Clear(); - BRepMesh::MapOfInteger::Iterator aFreeTriangles( aSelector.Elements() ); + IMeshData::IteratorOfMapOfInteger aFreeTriangles( aSelector.Elements() ); for ( ; aFreeTriangles.More(); aFreeTriangles.Next() ) deleteTriangle( aFreeTriangles.Key(), aLoopEdges ); // All edges that remain free are removed from aLoopEdges; // only the boundary edges of the triangulation remain there - BRepMesh::MapOfIntegerInteger::Iterator aFreeEdges( aLoopEdges ); + IMeshData::MapOfIntegerInteger::Iterator aFreeEdges( aLoopEdges ); for ( ; aFreeEdges.More(); aFreeEdges.Next() ) { if ( myMeshData->ElementsConnectedTo( aFreeEdges.Key() ).IsEmpty() ) @@ -303,34 +395,19 @@ void BRepMesh_Delaun::compute(BRepMesh::Array1OfInteger& theVertexIndexes) //function : createTriangles //purpose : Creates the triangles beetween the node and the polyline. //======================================================================= -void BRepMesh_Delaun::createTriangles(const Standard_Integer theVertexIndex, - BRepMesh::MapOfIntegerInteger& thePoly) +void BRepMesh_Delaun::createTriangles(const Standard_Integer theVertexIndex, + IMeshData::MapOfIntegerInteger& thePoly) { - createTriangles (theVertexIndex, thePoly, NULL); -} - -//======================================================================= -//function : createTriangles -//purpose : Creates the triangles beetween the node and the polyline. -//======================================================================= -void BRepMesh_Delaun::createTriangles(const Standard_Integer theVertexIndex, - BRepMesh::MapOfIntegerInteger& thePoly, - Message_ProgressSentry* theProgressEntry) -{ - BRepMesh::ListOfInteger aLoopEdges, anExternalEdges; + IMeshData::ListOfInteger aLoopEdges, anExternalEdges; const gp_XY& aVertexCoord = myMeshData->GetNode( theVertexIndex ).Coord(); - BRepMesh::MapOfIntegerInteger::Iterator anEdges( thePoly ); + IMeshData::MapOfIntegerInteger::Iterator anEdges( thePoly ); for ( ; anEdges.More(); anEdges.Next() ) { - if (theProgressEntry != NULL && !theProgressEntry->More()) - { - return; - } Standard_Integer anEdgeId = anEdges.Key(); const BRepMesh_Edge& anEdge = GetEdge( anEdgeId ); - const Standard_Boolean isPositive = thePoly (anEdgeId) != 0; + Standard_Boolean isPositive = thePoly( anEdgeId ) != 0; Standard_Integer aNodes[3]; if ( isPositive ) @@ -424,10 +501,6 @@ void BRepMesh_Delaun::createTriangles(const Standard_Integer theVertexIn while ( !aLoopEdges.IsEmpty() ) { - if (theProgressEntry != NULL && !theProgressEntry->More()) - { - return; - } const BRepMesh_Edge& anEdge = GetEdge( Abs( aLoopEdges.First() ) ); if ( anEdge.Movability() != BRepMesh_Deleted ) { @@ -444,21 +517,10 @@ void BRepMesh_Delaun::createTriangles(const Standard_Integer theVertexIn //purpose : Creation of triangles from the new nodes //======================================================================= void BRepMesh_Delaun::createTrianglesOnNewVertices( - BRepMesh::Array1OfInteger& theVertexIndexes) -{ - createTrianglesOnNewVertices (theVertexIndexes, NULL); -} - -//======================================================================= -//function : createTrianglesOnNewVertices -//purpose : Creation of triangles from the new nodes -//======================================================================= -void BRepMesh_Delaun::createTrianglesOnNewVertices( - BRepMesh::Array1OfInteger& theVertexIndexes, - Message_ProgressSentry* theProgressEntry) + IMeshData::VectorOfInteger& theVertexIndexes) { Handle(NCollection_IncAllocator) aAllocator = - new NCollection_IncAllocator(BRepMesh::MEMORY_BLOCK_SIZE_HUGE); + new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE); Standard_Real aTolU, aTolV; myMeshData->Data()->GetTolerance(aTolU, aTolV); @@ -471,22 +533,17 @@ void BRepMesh_Delaun::createTrianglesOnNewVertices( Standard_Integer anUpper = theVertexIndexes.Upper(); for( ; anIndex <= anUpper; ++anIndex ) { - if (theProgressEntry != NULL && !theProgressEntry->More()) - { - return; - } - aAllocator->Reset(Standard_False); - BRepMesh::MapOfIntegerInteger aLoopEdges(10, aAllocator); + IMeshData::MapOfIntegerInteger aLoopEdges(10, aAllocator); Standard_Integer aVertexIdx = theVertexIndexes( anIndex ); const BRepMesh_Vertex& aVertex = GetVertex( aVertexIdx ); // Iterator in the list of indexes of circles containing the node - BRepMesh::ListOfInteger& aCirclesList = myCircles.Select( aVertex.Coord() ); + IMeshData::ListOfInteger& aCirclesList = myCircles.Select( aVertex.Coord() ); Standard_Integer onEgdeId = 0, aTriangleId = 0; - BRepMesh::ListOfInteger::Iterator aCircleIt( aCirclesList ); + IMeshData::ListOfInteger::Iterator aCircleIt( aCirclesList ); for ( ; aCircleIt.More(); aCircleIt.Next() ) { // To add a node in the mesh it is necessary to check conditions: @@ -519,18 +576,12 @@ void BRepMesh_Delaun::createTrianglesOnNewVertices( isModify = Standard_True; while ( isModify && !aCirclesList.IsEmpty() ) { - if (theProgressEntry != NULL && !theProgressEntry->More()) - { - return; - } - isModify = Standard_False; - BRepMesh::ListOfInteger::Iterator aCircleIt1( aCirclesList ); + IMeshData::ListOfInteger::Iterator aCircleIt1( aCirclesList ); for ( ; aCircleIt1.More(); aCircleIt1.Next() ) { - Standard_Integer e[3]; - Standard_Boolean o[3]; - GetTriangle( aCircleIt1.Value() ).Edges( e, o ); + const BRepMesh_Triangle& aElement = GetTriangle(aCircleIt1.Value()); + const Standard_Integer(&e)[3] = aElement.myEdges; if ( aLoopEdges.IsBound( e[0] ) || aLoopEdges.IsBound( e[1] ) || @@ -544,28 +595,13 @@ void BRepMesh_Delaun::createTrianglesOnNewVertices( } } - if (theProgressEntry != NULL && !theProgressEntry->More()) - { - return; - } // Creation of triangles with the current node and free edges // and removal of these edges from the list of free edges - createTriangles( aVertexIdx, aLoopEdges, theProgressEntry ); + createTriangles( aVertexIdx, aLoopEdges ); } } - if (theProgressEntry != NULL && !theProgressEntry->More()) - { - return; - } - - insertInternalEdges (theProgressEntry); - if (theProgressEntry != NULL && !theProgressEntry->More()) - { - return; - } - // Adjustment of meshes to boundary edges - frontierAdjust(); + ProcessConstraints(); } //======================================================================= @@ -574,29 +610,13 @@ void BRepMesh_Delaun::createTrianglesOnNewVertices( //======================================================================= void BRepMesh_Delaun::insertInternalEdges() { - insertInternalEdges (NULL); -} - -//======================================================================= -//function : insertInternalEdges -//purpose : -//======================================================================= -void BRepMesh_Delaun::insertInternalEdges (Message_ProgressSentry* theProgressEntry) -{ - BRepMesh::HMapOfInteger anInternalEdges = InternalEdges(); + Handle(IMeshData::MapOfInteger) anInternalEdges = InternalEdges();; // Destruction of triancles intersecting internal edges // and their replacement by makeshift triangles - Standard_Integer e[3]; - Standard_Boolean o[3]; - BRepMesh::MapOfInteger::Iterator anInernalEdgesIt( *anInternalEdges ); + IMeshData::IteratorOfMapOfInteger anInernalEdgesIt( *anInternalEdges ); for ( ; anInernalEdgesIt.More(); anInernalEdgesIt.Next() ) { - if (theProgressEntry != NULL && !theProgressEntry->More()) - { - return; - } - const Standard_Integer aLinkIndex = anInernalEdgesIt.Key(); const BRepMesh_PairOfIndex& aPair = myMeshData->ElementsConnectedTo(aLinkIndex); @@ -604,7 +624,10 @@ void BRepMesh_Delaun::insertInternalEdges (Message_ProgressSentry* theProgressEn Standard_Boolean isGo[2] = { Standard_True, Standard_True }; for (Standard_Integer aTriangleIt = 1; aTriangleIt <= aPair.Extent(); ++aTriangleIt) { - GetTriangle(aPair.Index(aTriangleIt)).Edges(e, o); + const BRepMesh_Triangle& aElement = GetTriangle(aPair.Index(aTriangleIt)); + const Standard_Integer(&e)[3] = aElement.myEdges; + const Standard_Boolean(&o)[3] = aElement.myOrientations; + for (Standard_Integer i = 0; i < 3; ++i) { if (e[i] == aLinkIndex) @@ -653,9 +676,8 @@ Standard_Boolean BRepMesh_Delaun::isBoundToFrontier( if ( aTriId < 0 || aTriId == thePrevElementId ) continue; - Standard_Integer anEdges[3]; - Standard_Boolean anEdgesOri[3]; - GetTriangle( aTriId ).Edges( anEdges, anEdgesOri ); + const BRepMesh_Triangle& aElement = GetTriangle(aTriId); + const Standard_Integer(&anEdges)[3] = aElement.myEdges; for ( Standard_Integer anEdgeIt = 0; anEdgeIt < 3; ++anEdgeIt ) { @@ -690,16 +712,16 @@ Standard_Boolean BRepMesh_Delaun::isBoundToFrontier( void BRepMesh_Delaun::cleanupMesh() { Handle(NCollection_IncAllocator) aAllocator = - new NCollection_IncAllocator(BRepMesh::MEMORY_BLOCK_SIZE_HUGE); + new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE); for(;;) { aAllocator->Reset(Standard_False); - BRepMesh::MapOfIntegerInteger aLoopEdges(10, aAllocator); - BRepMesh::MapOfInteger aDelTriangles(10, aAllocator); + IMeshData::MapOfIntegerInteger aLoopEdges(10, aAllocator); + IMeshData::MapOfInteger aDelTriangles; - BRepMesh::HMapOfInteger aFreeEdges = FreeEdges(); - BRepMesh::MapOfInteger::Iterator aFreeEdgesIt( *aFreeEdges ); + Handle(IMeshData::MapOfInteger) aFreeEdges = FreeEdges(); + IMeshData::IteratorOfMapOfInteger aFreeEdgesIt( *aFreeEdges ); for ( ; aFreeEdgesIt.More(); aFreeEdgesIt.Next() ) { const Standard_Integer& aFreeEdgeId = aFreeEdgesIt.Key(); @@ -718,9 +740,8 @@ void BRepMesh_Delaun::cleanupMesh() Standard_Integer aTriId = aPair.FirstIndex(); // Check that the connected triangle is not surrounded by another triangles - Standard_Integer anEdges[3]; - Standard_Boolean anEdgesOri[3]; - GetTriangle( aTriId ).Edges( anEdges, anEdgesOri ); + const BRepMesh_Triangle& aElement = GetTriangle(aTriId); + const Standard_Integer(&anEdges)[3] = aElement.myEdges; Standard_Boolean isCanNotBeRemoved = Standard_True; for ( Standard_Integer aCurEdgeIdx = 0; aCurEdgeIdx < 3; ++aCurEdgeIdx ) @@ -728,7 +749,7 @@ void BRepMesh_Delaun::cleanupMesh() if ( anEdges[aCurEdgeIdx] != aFreeEdgeId ) continue; - for ( Standard_Integer anOtherEdgeIt = 1; anOtherEdgeIt <= 2; ++anOtherEdgeIt ) + for ( Standard_Integer anOtherEdgeIt = 1; anOtherEdgeIt <= 2 && isCanNotBeRemoved; ++anOtherEdgeIt ) { Standard_Integer anOtherEdgeId = ( aCurEdgeIdx + anOtherEdgeIt ) % 3; const BRepMesh_PairOfIndex& anOtherEdgePair = @@ -737,7 +758,27 @@ void BRepMesh_Delaun::cleanupMesh() if ( anOtherEdgePair.Extent() < 2 ) { isCanNotBeRemoved = Standard_False; - break; + } + else + { + for (int aTriIdx = 1; aTriIdx <= anOtherEdgePair.Extent () && isCanNotBeRemoved; ++aTriIdx) + { + if (anOtherEdgePair.Index (aTriIdx) == aTriId) + continue; + + Standard_Integer v[3]; + const BRepMesh_Triangle& aCurTriangle = GetTriangle (anOtherEdgePair.Index (aTriIdx)); + myMeshData->ElementNodes (aCurTriangle, v); + for (int aNodeIdx = 0; aNodeIdx < 3 && isCanNotBeRemoved; ++aNodeIdx) + { + if (v[aNodeIdx] == mySupVert[0] || + v[aNodeIdx] == mySupVert[1] || + v[aNodeIdx] == mySupVert[2]) + { + isCanNotBeRemoved = Standard_False; + } + } + } } } @@ -761,7 +802,7 @@ void BRepMesh_Delaun::cleanupMesh() // Destruction of triangles : Standard_Integer aDeletedTrianglesNb = 0; - BRepMesh::MapOfInteger::Iterator aDelTrianglesIt( aDelTriangles ); + IMeshData::IteratorOfMapOfInteger aDelTrianglesIt( aDelTriangles ); for ( ; aDelTrianglesIt.More(); aDelTrianglesIt.Next() ) { deleteTriangle( aDelTrianglesIt.Key(), aLoopEdges ); @@ -769,7 +810,7 @@ void BRepMesh_Delaun::cleanupMesh() } // Destruction of remaining hanging edges - BRepMesh::MapOfIntegerInteger::Iterator aLoopEdgesIt( aLoopEdges ); + IMeshData::MapOfIntegerInteger::Iterator aLoopEdgesIt( aLoopEdges ); for ( ; aLoopEdgesIt.More(); aLoopEdgesIt.Next() ) { if ( myMeshData->ElementsConnectedTo( aLoopEdgesIt.Key() ).IsEmpty() ) @@ -787,15 +828,14 @@ void BRepMesh_Delaun::cleanupMesh() //======================================================================= void BRepMesh_Delaun::frontierAdjust() { - BRepMesh::HMapOfInteger aFrontier = Frontier(); + Handle(IMeshData::MapOfInteger) aFrontier = Frontier(); Handle(NCollection_IncAllocator) aAllocator = - new NCollection_IncAllocator(BRepMesh::MEMORY_BLOCK_SIZE_HUGE); + new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE); - BRepMesh::VectorOfInteger aFailedFrontiers(256, aAllocator); - BRepMesh::MapOfIntegerInteger aLoopEdges(10, aAllocator); - BRepMesh::HMapOfInteger aIntFrontierEdges = - new BRepMesh::MapOfInteger(10, aAllocator); + IMeshData::VectorOfInteger aFailedFrontiers(256, aAllocator); + IMeshData::MapOfIntegerInteger aLoopEdges(10, aAllocator); + Handle(IMeshData::MapOfInteger) aIntFrontierEdges = new IMeshData::MapOfInteger; for ( Standard_Integer aPass = 1; aPass <= 2; ++aPass ) { @@ -803,7 +843,7 @@ void BRepMesh_Delaun::frontierAdjust() // 2 pass): find external triangles on boundary edges appeared // during triangles replacement. - BRepMesh::MapOfInteger::Iterator aFrontierIt( *aFrontier ); + IMeshData::IteratorOfMapOfInteger aFrontierIt( *aFrontier ); for ( ; aFrontierIt.More(); aFrontierIt.Next() ) { Standard_Integer aFrontierId = aFrontierIt.Key(); @@ -815,9 +855,9 @@ void BRepMesh_Delaun::frontierAdjust() if( aPriorElemId < 0 ) continue; - Standard_Integer e[3]; - Standard_Boolean o[3]; - GetTriangle( aPriorElemId ).Edges( e, o ); + const BRepMesh_Triangle& aElement = GetTriangle(aPriorElemId); + const Standard_Integer(&e)[3] = aElement.myEdges; + const Standard_Boolean(&o)[3] = aElement.myOrientations; Standard_Boolean isTriangleFound = Standard_False; for ( Standard_Integer n = 0; n < 3; ++n ) @@ -837,7 +877,7 @@ void BRepMesh_Delaun::frontierAdjust() } // destrucrion of remaining hanging edges : - BRepMesh::MapOfIntegerInteger::Iterator aLoopEdgesIt( aLoopEdges ); + IMeshData::MapOfIntegerInteger::Iterator aLoopEdgesIt( aLoopEdges ); for ( ; aLoopEdgesIt.More(); aLoopEdgesIt.Next() ) { Standard_Integer aLoopEdgeId = aLoopEdgesIt.Key(); @@ -868,7 +908,7 @@ void BRepMesh_Delaun::frontierAdjust() // situation when frontier edge has a triangle at a right side, but its free // links cross another frontieres and meshLeftPolygonOf itself can't collect // a closed polygon. - BRepMesh::VectorOfInteger::Iterator aFailedFrontiersIt( aFailedFrontiers ); + IMeshData::VectorOfInteger::Iterator aFailedFrontiersIt( aFailedFrontiers ); for ( ; aFailedFrontiersIt.More(); aFailedFrontiersIt.Next() ) { Standard_Integer aFrontierId = aFailedFrontiersIt.Value(); @@ -884,9 +924,9 @@ void BRepMesh_Delaun::frontierAdjust() //purpose : Add boundig box for edge defined by start & end point to // the given vector of bounding boxes for triangulation edges //======================================================================= -void BRepMesh_Delaun::fillBndBox(BRepMesh::SequenceOfBndB2d& theBoxes, - const BRepMesh_Vertex& theV1, - const BRepMesh_Vertex& theV2) +void BRepMesh_Delaun::fillBndBox(IMeshData::SequenceOfBndB2d& theBoxes, + const BRepMesh_Vertex& theV1, + const BRepMesh_Vertex& theV2) { Bnd_B2d aBox; UpdateBndBox(theV1.Coord(), theV2.Coord(), aBox); @@ -898,16 +938,16 @@ void BRepMesh_Delaun::fillBndBox(BRepMesh::SequenceOfBndB2d& theBoxes, //purpose : Collect the polygon at the left of the given edge (material side) //======================================================================= Standard_Boolean BRepMesh_Delaun::meshLeftPolygonOf( - const Standard_Integer theStartEdgeId, - const Standard_Boolean isForward, - BRepMesh::HMapOfInteger theSkipped ) + const Standard_Integer theStartEdgeId, + const Standard_Boolean isForward, + Handle(IMeshData::MapOfInteger) theSkipped) { if ( !theSkipped.IsNull() && theSkipped->Contains( theStartEdgeId ) ) return Standard_True; const BRepMesh_Edge& aRefEdge = GetEdge( theStartEdgeId ); - BRepMesh::SequenceOfInteger aPolygon; + IMeshData::SequenceOfInteger aPolygon; Standard_Integer aStartNode, aPivotNode; if ( isForward ) { @@ -935,14 +975,14 @@ Standard_Boolean BRepMesh_Delaun::meshLeftPolygonOf( // Auxilary structures. // Bounding boxes of polygon links to be used for preliminary // analysis of intersections - BRepMesh::SequenceOfBndB2d aBoxes; + IMeshData::SequenceOfBndB2d aBoxes; fillBndBox( aBoxes, aStartEdgeVertexS, aPivotVertex ); // Hanging ends - BRepMesh::MapOfInteger aDeadLinks; + IMeshData::MapOfInteger aDeadLinks; // Links are temporarily excluded from consideration - BRepMesh::MapOfInteger aLeprousLinks; + IMeshData::MapOfInteger aLeprousLinks; aLeprousLinks.Add( theStartEdgeId ); Standard_Boolean isSkipLeprous = Standard_True; @@ -1027,26 +1067,26 @@ Standard_Boolean BRepMesh_Delaun::meshLeftPolygonOf( // consideration next time until a hanging end is occured. //======================================================================= Standard_Integer BRepMesh_Delaun::findNextPolygonLink( - const Standard_Integer& theFirstNode, - const Standard_Integer& thePivotNode, - const BRepMesh_Vertex& thePivotVertex, - const gp_Vec2d& theRefLinkDir, - const BRepMesh::SequenceOfBndB2d& theBoxes, - const BRepMesh::SequenceOfInteger& thePolygon, - const BRepMesh::HMapOfInteger theSkipped, - const Standard_Boolean& isSkipLeprous, - BRepMesh::MapOfInteger& theLeprousLinks, - BRepMesh::MapOfInteger& theDeadLinks, - Standard_Integer& theNextPivotNode, - gp_Vec2d& theNextLinkDir, - Bnd_B2d& theNextLinkBndBox ) + const Standard_Integer& theFirstNode, + const Standard_Integer& thePivotNode, + const BRepMesh_Vertex& thePivotVertex, + const gp_Vec2d& theRefLinkDir, + const IMeshData::SequenceOfBndB2d& theBoxes, + const IMeshData::SequenceOfInteger& thePolygon, + const Handle(IMeshData::MapOfInteger) theSkipped, + const Standard_Boolean& isSkipLeprous, + IMeshData::MapOfInteger& theLeprousLinks, + IMeshData::MapOfInteger& theDeadLinks, + Standard_Integer& theNextPivotNode, + gp_Vec2d& theNextLinkDir, + Bnd_B2d& theNextLinkBndBox ) { // Find the next link having the greatest angle // respect to a direction of a reference one Standard_Real aMaxAngle = RealFirst(); Standard_Integer aNextLinkId = 0; - BRepMesh::ListOfInteger::Iterator aLinkIt( myMeshData->LinksConnectedTo( thePivotNode ) ); + IMeshData::ListOfInteger::Iterator aLinkIt( myMeshData->LinksConnectedTo( thePivotNode ) ); for ( ; aLinkIt.More(); aLinkIt.Next() ) { const Standard_Integer& aNeighbourLinkInfo = aLinkIt.Value(); @@ -1136,13 +1176,13 @@ Standard_Integer BRepMesh_Delaun::findNextPolygonLink( // parameter. //======================================================================= Standard_Boolean BRepMesh_Delaun::checkIntersection( - const BRepMesh_Edge& theLink, - const BRepMesh::SequenceOfInteger& thePolygon, - const BRepMesh::SequenceOfBndB2d& thePolyBoxes, - const Standard_Boolean isConsiderEndPointTouch, - const Standard_Boolean isConsiderPointOnEdge, - const Standard_Boolean isSkipLastEdge, - Bnd_B2d& theLinkBndBox ) const + const BRepMesh_Edge& theLink, + const IMeshData::SequenceOfInteger& thePolygon, + const IMeshData::SequenceOfBndB2d& thePolyBoxes, + const Standard_Boolean isConsiderEndPointTouch, + const Standard_Boolean isConsiderPointOnEdge, + const Standard_Boolean isSkipLastEdge, + Bnd_B2d& theLinkBndBox ) const { UpdateBndBox(GetVertex(theLink.FirstNode()).Coord(), GetVertex(theLink.LastNode()).Coord(), theLinkBndBox); @@ -1168,7 +1208,7 @@ Standard_Boolean BRepMesh_Delaun::checkIntersection( continue; gp_Pnt2d anIntPnt; - BRepMesh_GeomTool::IntFlag aIntFlag = intSegSeg( theLink, aPolyLink, + BRepMesh_GeomTool::IntFlag aIntFlag = intSegSeg( theLink, aPolyLink, isConsiderEndPointTouch, isConsiderPointOnEdge, anIntPnt ); if ( aIntFlag != BRepMesh_GeomTool::NoIntersection ) @@ -1184,17 +1224,10 @@ Standard_Boolean BRepMesh_Delaun::checkIntersection( //function : addTriangle //purpose : Add a triangle based on the given oriented edges into mesh //======================================================================= -void BRepMesh_Delaun::addTriangle( const Standard_Integer (&theEdgesId)[3], - const Standard_Boolean (&theEdgesOri)[3], - const Standard_Integer (&theNodesId)[3]) +inline void BRepMesh_Delaun::addTriangle( const Standard_Integer (&theEdgesId)[3], + const Standard_Boolean (&theEdgesOri)[3], + const Standard_Integer (&theNodesId)[3] ) { - for (Standard_Integer i = 0; i < 3; ++i) - { - const BRepMesh_PairOfIndex& aPair = myMeshData->ElementsConnectedTo(theEdgesId[i]); - if (aPair.Extent() == 2) - // it is forbidden to have more than two triangles connected to the same link - return; - } Standard_Integer aNewTriangleId = myMeshData->AddElement(BRepMesh_Triangle(theEdgesId, theEdgesOri, BRepMesh_Free)); @@ -1213,20 +1246,20 @@ void BRepMesh_Delaun::addTriangle( const Standard_Integer (&theEdgesId)[3], //function : cleanupPolygon //purpose : Remove internal triangles from the given polygon //======================================================================= -void BRepMesh_Delaun::cleanupPolygon(const BRepMesh::SequenceOfInteger& thePolygon, - const BRepMesh::SequenceOfBndB2d& thePolyBoxes ) +void BRepMesh_Delaun::cleanupPolygon(const IMeshData::SequenceOfInteger& thePolygon, + const IMeshData::SequenceOfBndB2d& thePolyBoxes ) { Standard_Integer aPolyLen = thePolygon.Length(); if ( aPolyLen < 3 ) return; Handle(NCollection_IncAllocator) aAllocator = - new NCollection_IncAllocator(BRepMesh::MEMORY_BLOCK_SIZE_HUGE); + new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE); - BRepMesh::MapOfIntegerInteger aLoopEdges(10, aAllocator); - BRepMesh::MapOfInteger anIgnoredEdges(10, aAllocator); - BRepMesh::MapOfInteger aPolyVerticesFindMap(10, aAllocator); - BRepMesh::VectorOfInteger aPolyVertices(256, aAllocator); + IMeshData::MapOfIntegerInteger aLoopEdges(10, aAllocator); + IMeshData::MapOfInteger anIgnoredEdges; + IMeshData::MapOfInteger aPolyVerticesFindMap; + IMeshData::VectorOfInteger aPolyVertices(256, aAllocator); // Collect boundary vertices of the polygon for ( Standard_Integer aPolyIt = 1; aPolyIt <= aPolyLen; ++aPolyIt ) { @@ -1245,9 +1278,9 @@ void BRepMesh_Delaun::cleanupPolygon(const BRepMesh::SequenceOfInteger& thePolyg if ( anElemId < 0 ) continue; - Standard_Integer anEdges[3]; - Standard_Boolean anEdgesOri[3]; - GetTriangle( anElemId ).Edges(anEdges, anEdgesOri); + const BRepMesh_Triangle& aElement = GetTriangle(anElemId); + const Standard_Integer(&anEdges)[3] = aElement.myEdges; + const Standard_Boolean(&anEdgesOri)[3] = aElement.myOrientations; Standard_Integer isTriangleFound = Standard_False; for ( Standard_Integer anEdgeIt = 0; anEdgeIt < 3; ++anEdgeIt ) @@ -1292,7 +1325,7 @@ void BRepMesh_Delaun::cleanupPolygon(const BRepMesh::SequenceOfInteger& thePolyg if ( aPolyVertices.First() != aPolyVertices.Last() ) aPolyVertices.Append( aPolyVertices.First() ); - BRepMesh::MapOfInteger aSurvivedLinks( anIgnoredEdges ); + IMeshData::MapOfInteger aSurvivedLinks( anIgnoredEdges ); Standard_Integer aPolyVertIt = 0; Standard_Integer anUniqueVerticesNum = aPolyVertices.Length() - 1; @@ -1303,7 +1336,7 @@ void BRepMesh_Delaun::cleanupPolygon(const BRepMesh::SequenceOfInteger& thePolyg thePolyBoxes, aSurvivedLinks, aLoopEdges ); } - BRepMesh::MapOfIntegerInteger::Iterator aLoopEdgesIt( aLoopEdges ); + IMeshData::MapOfIntegerInteger::Iterator aLoopEdgesIt( aLoopEdges ); for ( ; aLoopEdgesIt.More(); aLoopEdgesIt.Next() ) { const Standard_Integer& aLoopEdgeId = aLoopEdgesIt.Key(); @@ -1321,19 +1354,19 @@ void BRepMesh_Delaun::cleanupPolygon(const BRepMesh::SequenceOfInteger& thePolyg // inside the polygon or crossed it. //======================================================================= void BRepMesh_Delaun::killTrianglesAroundVertex( - const Standard_Integer theZombieNodeId, - const BRepMesh::VectorOfInteger& thePolyVertices, - const BRepMesh::MapOfInteger& thePolyVerticesFindMap, - const BRepMesh::SequenceOfInteger& thePolygon, - const BRepMesh::SequenceOfBndB2d& thePolyBoxes, - BRepMesh::MapOfInteger& theSurvivedLinks, - BRepMesh::MapOfIntegerInteger& theLoopEdges ) + const Standard_Integer theZombieNodeId, + const IMeshData::VectorOfInteger& thePolyVertices, + const IMeshData::MapOfInteger& thePolyVerticesFindMap, + const IMeshData::SequenceOfInteger& thePolygon, + const IMeshData::SequenceOfBndB2d& thePolyBoxes, + IMeshData::MapOfInteger& theSurvivedLinks, + IMeshData::MapOfIntegerInteger& theLoopEdges ) { - BRepMesh::ListOfInteger::Iterator aNeighborsIt = + IMeshData::ListOfInteger::Iterator aNeighborsIt = myMeshData->LinksConnectedTo( theZombieNodeId ); // Try to infect neighbor nodes - BRepMesh::VectorOfInteger aVictimNodes; + IMeshData::VectorOfInteger aVictimNodes; for ( ; aNeighborsIt.More(); aNeighborsIt.Next() ) { const Standard_Integer& aNeighborLinkId = aNeighborsIt.Value(); @@ -1391,7 +1424,7 @@ void BRepMesh_Delaun::killTrianglesAroundVertex( } // Go and do your job! - BRepMesh::VectorOfInteger::Iterator aVictimIt( aVictimNodes ); + IMeshData::VectorOfInteger::Iterator aVictimIt( aVictimNodes ); for ( ; aVictimIt.More(); aVictimIt.Next() ) { killTrianglesAroundVertex( aVictimIt.Value(), thePolyVertices, @@ -1405,8 +1438,8 @@ void BRepMesh_Delaun::killTrianglesAroundVertex( //purpose : Checks is the given vertex lies inside the polygon //======================================================================= Standard_Boolean BRepMesh_Delaun::isVertexInsidePolygon( - const Standard_Integer& theVertexId, - const BRepMesh::VectorOfInteger& thePolygonVertices ) const + const Standard_Integer& theVertexId, + const IMeshData::VectorOfInteger& thePolygonVertices ) const { Standard_Integer aPolyLen = thePolygonVertices.Length(); if ( aPolyLen < 3 ) @@ -1446,13 +1479,13 @@ Standard_Boolean BRepMesh_Delaun::isVertexInsidePolygon( // boundary intersection. Does nothing elsewhere. //======================================================================= void BRepMesh_Delaun::killTrianglesOnIntersectingLinks( - const Standard_Integer& theLinkToCheckId, - const BRepMesh_Edge& theLinkToCheck, - const Standard_Integer& theEndPoint, - const BRepMesh::SequenceOfInteger& thePolygon, - const BRepMesh::SequenceOfBndB2d& thePolyBoxes, - BRepMesh::MapOfInteger& theSurvivedLinks, - BRepMesh::MapOfIntegerInteger& theLoopEdges ) + const Standard_Integer& theLinkToCheckId, + const BRepMesh_Edge& theLinkToCheck, + const Standard_Integer& theEndPoint, + const IMeshData::SequenceOfInteger& thePolygon, + const IMeshData::SequenceOfBndB2d& thePolyBoxes, + IMeshData::MapOfInteger& theSurvivedLinks, + IMeshData::MapOfIntegerInteger& theLoopEdges ) { if ( theSurvivedLinks.Contains( theLinkToCheckId ) ) return; @@ -1470,7 +1503,7 @@ void BRepMesh_Delaun::killTrianglesOnIntersectingLinks( killLinkTriangles( theLinkToCheckId, theLoopEdges ); - BRepMesh::ListOfInteger::Iterator aNeighborsIt( + IMeshData::ListOfInteger::Iterator aNeighborsIt( myMeshData->LinksConnectedTo(theEndPoint)); for ( ; aNeighborsIt.More(); aNeighborsIt.Next() ) @@ -1492,8 +1525,8 @@ void BRepMesh_Delaun::killTrianglesOnIntersectingLinks( //purpose : Kill triangles bound to the given link. //======================================================================= void BRepMesh_Delaun::killLinkTriangles( - const Standard_Integer& theLinkId, - BRepMesh::MapOfIntegerInteger& theLoopEdges ) + const Standard_Integer& theLinkId, + IMeshData::MapOfIntegerInteger& theLoopEdges ) { const BRepMesh_PairOfIndex& aPair = myMeshData->ElementsConnectedTo( theLinkId ); @@ -1535,17 +1568,17 @@ void BRepMesh_Delaun::getOrientedNodes(const BRepMesh_Edge& theEdge, //purpose : Processes loop within the given polygon formed by range of // its links specified by start and end link indices. //======================================================================= -void BRepMesh_Delaun::processLoop(const Standard_Integer theLinkFrom, - const Standard_Integer theLinkTo, - const BRepMesh::SequenceOfInteger& thePolygon, - const BRepMesh::SequenceOfBndB2d& thePolyBoxes) +void BRepMesh_Delaun::processLoop(const Standard_Integer theLinkFrom, + const Standard_Integer theLinkTo, + const IMeshData::SequenceOfInteger& thePolygon, + const IMeshData::SequenceOfBndB2d& thePolyBoxes) { Standard_Integer aNbOfLinksInLoop = theLinkTo - theLinkFrom - 1; if ( aNbOfLinksInLoop < 3 ) return; - BRepMesh::SequenceOfInteger aPolygon; - BRepMesh::SequenceOfBndB2d aPolyBoxes; + IMeshData::SequenceOfInteger aPolygon; + IMeshData::SequenceOfBndB2d aPolyBoxes; for ( ; aNbOfLinksInLoop > 0; --aNbOfLinksInLoop ) { Standard_Integer aLoopLinkIndex = theLinkFrom + aNbOfLinksInLoop; @@ -1563,10 +1596,10 @@ void BRepMesh_Delaun::processLoop(const Standard_Integer theLinkFrom Standard_Integer BRepMesh_Delaun::createAndReplacePolygonLink( const Standard_Integer *theNodes, const gp_Pnt2d *thePnts, - const Standard_Integer theRootIndex, - const ReplaceFlag theReplaceFlag, - BRepMesh::SequenceOfInteger& thePolygon, - BRepMesh::SequenceOfBndB2d& thePolyBoxes ) + const Standard_Integer theRootIndex, + const ReplaceFlag theReplaceFlag, + IMeshData::SequenceOfInteger& thePolygon, + IMeshData::SequenceOfBndB2d& thePolyBoxes ) { Standard_Integer aNewEdgeId = myMeshData->AddLink( BRepMesh_Edge( @@ -1600,9 +1633,9 @@ Standard_Integer BRepMesh_Delaun::createAndReplacePolygonLink( //function : meshPolygon //purpose : //======================================================================= -void BRepMesh_Delaun::meshPolygon(BRepMesh::SequenceOfInteger& thePolygon, - BRepMesh::SequenceOfBndB2d& thePolyBoxes, - BRepMesh::HMapOfInteger theSkipped ) +void BRepMesh_Delaun::meshPolygon(IMeshData::SequenceOfInteger& thePolygon, + IMeshData::SequenceOfBndB2d& thePolyBoxes, + Handle(IMeshData::MapOfInteger) theSkipped) { // Check is the source polygon elementary if ( meshElementaryPolygon( thePolygon ) ) @@ -1649,7 +1682,7 @@ void BRepMesh_Delaun::meshPolygon(BRepMesh::SequenceOfInteger& thePolygon, }; gp_Pnt2d anIntPnt; - BRepMesh_GeomTool::IntFlag aIntFlag = intSegSeg( *aCurEdge, *aNextEdge, + BRepMesh_GeomTool::IntFlag aIntFlag = intSegSeg( *aCurEdge, *aNextEdge, Standard_False, Standard_True, anIntPnt ); if ( aIntFlag == BRepMesh_GeomTool::NoIntersection ) @@ -1816,14 +1849,14 @@ void BRepMesh_Delaun::meshPolygon(BRepMesh::SequenceOfInteger& thePolygon, } } - BRepMesh::SequenceOfInteger* aPolygon1 = &thePolygon; - BRepMesh::SequenceOfBndB2d* aPolyBoxes1 = &thePolyBoxes; + IMeshData::SequenceOfInteger* aPolygon1 = &thePolygon; + IMeshData::SequenceOfBndB2d* aPolyBoxes1 = &thePolyBoxes; - BRepMesh::HSequenceOfInteger aPolygon2 = new BRepMesh::SequenceOfInteger; - BRepMesh::HSequenceOfBndB2d aPolyBoxes2 = new BRepMesh::SequenceOfBndB2d; + Handle(IMeshData::SequenceOfInteger) aPolygon2 = new IMeshData::SequenceOfInteger; + Handle(IMeshData::SequenceOfBndB2d) aPolyBoxes2 = new IMeshData::SequenceOfBndB2d; - NCollection_Sequence aPolyStack; - NCollection_Sequence aPolyBoxStack; + NCollection_Sequence aPolyStack; + NCollection_Sequence aPolyBoxStack; for (;;) { decomposeSimplePolygon(*aPolygon1, *aPolyBoxes1, *aPolygon2, *aPolyBoxes2); @@ -1832,8 +1865,8 @@ void BRepMesh_Delaun::meshPolygon(BRepMesh::SequenceOfInteger& thePolygon, aPolyStack.Append(aPolygon2); aPolyBoxStack.Append(aPolyBoxes2); - aPolygon2 = new BRepMesh::SequenceOfInteger; - aPolyBoxes2 = new BRepMesh::SequenceOfBndB2d; + aPolygon2 = new IMeshData::SequenceOfInteger; + aPolyBoxes2 = new IMeshData::SequenceOfBndB2d; } if (aPolygon1->IsEmpty()) @@ -1858,7 +1891,7 @@ void BRepMesh_Delaun::meshPolygon(BRepMesh::SequenceOfInteger& thePolygon, //purpose : Triangulation of closed polygon containing only three edges. //======================================================================= inline Standard_Boolean BRepMesh_Delaun::meshElementaryPolygon( - const BRepMesh::SequenceOfInteger& thePolygon) + const IMeshData::SequenceOfInteger& thePolygon) { Standard_Integer aPolyLen = thePolygon.Length(); if ( aPolyLen < 3 ) @@ -1898,10 +1931,10 @@ inline Standard_Boolean BRepMesh_Delaun::meshElementaryPolygon( //purpose : //======================================================================= void BRepMesh_Delaun::decomposeSimplePolygon( - BRepMesh::SequenceOfInteger& thePolygon, - BRepMesh::SequenceOfBndB2d& thePolyBoxes, - BRepMesh::SequenceOfInteger& thePolygonCut, - BRepMesh::SequenceOfBndB2d& thePolyBoxesCut) + IMeshData::SequenceOfInteger& thePolygon, + IMeshData::SequenceOfBndB2d& thePolyBoxes, + IMeshData::SequenceOfInteger& thePolygonCut, + IMeshData::SequenceOfBndB2d& thePolyBoxesCut) { // Check is the given polygon elementary if ( meshElementaryPolygon( thePolygon ) ) @@ -1993,7 +2026,7 @@ void BRepMesh_Delaun::decomposeSimplePolygon( // intersection is possible... gp_Pnt2d anIntPnt; - BRepMesh_GeomTool::IntFlag aIntFlag = intSegSeg( aCheckLink, aPolyLink, + BRepMesh_GeomTool::IntFlag aIntFlag = intSegSeg( aCheckLink, aPolyLink, Standard_False, Standard_False, anIntPnt ); if( aIntFlag != BRepMesh_GeomTool::NoIntersection ) @@ -2085,17 +2118,17 @@ void BRepMesh_Delaun::RemoveVertex( const BRepMesh_Vertex& theVertex ) BRepMesh_SelectorOfDataStructureOfDelaun aSelector( myMeshData ); aSelector.NeighboursOf( theVertex ); - BRepMesh::MapOfIntegerInteger aLoopEdges;//( 10, myMeshData->Allocator() ); + IMeshData::MapOfIntegerInteger aLoopEdges;//( 10, myMeshData->Allocator() ); // Loop on triangles to be destroyed : - BRepMesh::MapOfInteger::Iterator aTriangleIt( aSelector.Elements() ); + IMeshData::IteratorOfMapOfInteger aTriangleIt( aSelector.Elements() ); for ( ; aTriangleIt.More(); aTriangleIt.Next() ) deleteTriangle( aTriangleIt.Key(), aLoopEdges ); - BRepMesh::SequenceOfBndB2d aBoxes; - BRepMesh::SequenceOfInteger aPolygon; + IMeshData::SequenceOfBndB2d aBoxes; + IMeshData::SequenceOfInteger aPolygon; Standard_Integer aLoopEdgesCount = aLoopEdges.Extent(); - BRepMesh::MapOfIntegerInteger::Iterator aLoopEdgesIt( aLoopEdges ); + IMeshData::MapOfIntegerInteger::Iterator aLoopEdgesIt( aLoopEdges ); if ( aLoopEdgesIt.More() ) { @@ -2105,7 +2138,7 @@ void BRepMesh_Delaun::RemoveVertex( const BRepMesh_Vertex& theVertex ) Standard_Integer aPivotNode = anEdge.LastNode(); Standard_Integer anEdgeId = aLoopEdgesIt.Key(); - Standard_Boolean isPositive = (aLoopEdges (anEdgeId) != 0); + Standard_Boolean isPositive = aLoopEdges( anEdgeId ) != 0; if ( !isPositive ) { Standard_Integer aTmp; @@ -2125,7 +2158,7 @@ void BRepMesh_Delaun::RemoveVertex( const BRepMesh_Vertex& theVertex ) aLastNode = aFirstNode; while ( aPivotNode != aLastNode ) { - BRepMesh::ListOfInteger::Iterator aLinkIt( myMeshData->LinksConnectedTo( aPivotNode ) ); + IMeshData::ListOfInteger::Iterator aLinkIt( myMeshData->LinksConnectedTo( aPivotNode ) ); for ( ; aLinkIt.More(); aLinkIt.Next() ) { if ( aLinkIt.Value() != anEdgeId && @@ -2161,33 +2194,18 @@ void BRepMesh_Delaun::RemoveVertex( const BRepMesh_Vertex& theVertex ) } } -//======================================================================= -//function : AddVertices -//purpose : Adds some vertices in the triangulation. -//======================================================================= -void BRepMesh_Delaun::AddVertices(BRepMesh::Array1OfVertexOfDelaun& theVertices) -{ - AddVertices (theVertices, NULL); -} //======================================================================= //function : AddVertices //purpose : Adds some vertices in the triangulation. //======================================================================= -void BRepMesh_Delaun::AddVertices(BRepMesh::Array1OfVertexOfDelaun& theVertices, - Message_ProgressSentry* theProgressEntry) +void BRepMesh_Delaun::AddVertices(IMeshData::VectorOfInteger& theVertices) { - std::make_heap(theVertices.begin(), theVertices.end(), ComparatorOfVertexOfDelaun()); - std::sort_heap(theVertices.begin(), theVertices.end(), ComparatorOfVertexOfDelaun()); - - Standard_Integer aLower = theVertices.Lower(); - Standard_Integer anUpper = theVertices.Upper(); - - BRepMesh::Array1OfInteger aVertexIndexes( aLower, anUpper ); - for ( Standard_Integer i = aLower; i <= anUpper; ++i ) - aVertexIndexes(i) = myMeshData->AddNode( theVertices(i) ); + ComparatorOfIndexedVertexOfDelaun aCmp(myMeshData); + std::make_heap(theVertices.begin(), theVertices.end(), aCmp); + std::sort_heap(theVertices.begin(), theVertices.end(), aCmp); - createTrianglesOnNewVertices( aVertexIndexes, theProgressEntry ); + createTrianglesOnNewVertices(theVertices); } //======================================================================= @@ -2282,12 +2300,12 @@ Standard_Boolean BRepMesh_Delaun::UseEdge( const Standard_Integer /*theIndex*/ ) //function : getEdgesByType //purpose : Gives the list of edges with type defined by input parameter //======================================================================= -BRepMesh::HMapOfInteger BRepMesh_Delaun::getEdgesByType( +Handle(IMeshData::MapOfInteger) BRepMesh_Delaun::getEdgesByType( const BRepMesh_DegreeOfFreedom theEdgeType ) const { Handle(NCollection_IncAllocator) anAlloc = new NCollection_IncAllocator; - BRepMesh::HMapOfInteger aResult = new BRepMesh::MapOfInteger(1, anAlloc); - BRepMesh::MapOfInteger::Iterator anEdgeIt( myMeshData->LinksOfDomain() ); + Handle(IMeshData::MapOfInteger) aResult = new IMeshData::MapOfInteger; + IMeshData::IteratorOfMapOfInteger anEdgeIt( myMeshData->LinksOfDomain() ); for ( ; anEdgeIt.More(); anEdgeIt.Next() ) { @@ -2350,12 +2368,10 @@ Standard_Boolean BRepMesh_Delaun::Contains( const Standard_Integer theTriangleId { theEdgeOn = 0; - Standard_Integer e[3]; - Standard_Boolean o[3]; Standard_Integer p[3]; const BRepMesh_Triangle& aElement = GetTriangle( theTriangleId ); - aElement.Edges(e, o); + const Standard_Integer(&e)[3] = aElement.myEdges; const BRepMesh_Edge* anEdges[3] = { &GetEdge( e[0] ), &GetEdge( e[1] ), @@ -2405,7 +2421,7 @@ Standard_Boolean BRepMesh_Delaun::Contains( const Standard_Integer theTriangleId //function : intSegSeg //purpose : Checks intersection between the two segments. //============================================================================= -BRepMesh_GeomTool::IntFlag BRepMesh_Delaun::intSegSeg( +BRepMesh_GeomTool::IntFlag BRepMesh_Delaun::intSegSeg( const BRepMesh_Edge& theEdg1, const BRepMesh_Edge& theEdg2, const Standard_Boolean isConsiderEndPointTouch, @@ -2427,9 +2443,9 @@ BRepMesh_GeomTool::IntFlag BRepMesh_Delaun::intSegSeg( //purpose : Returns area of the loop of the given polygon defined by indices // of its start and end links. //============================================================================= -Standard_Real BRepMesh_Delaun::polyArea(const BRepMesh::SequenceOfInteger& thePolygon, - const Standard_Integer theStartIndex, - const Standard_Integer theEndIndex) const +Standard_Real BRepMesh_Delaun::polyArea(const IMeshData::SequenceOfInteger& thePolygon, + const Standard_Integer theStartIndex, + const Standard_Integer theEndIndex) const { Standard_Real aArea = 0.0; Standard_Integer aPolyLen = thePolygon.Length(); @@ -2482,9 +2498,9 @@ Standard_CString BRepMesh_DumpPoly(void* thePolygon, return "Error: file name or polygon data is null"; } - BRepMesh::SequenceOfInteger& aPolygon = *(BRepMesh::SequenceOfInteger*)thePolygon; + IMeshData::SequenceOfInteger& aPolygon = *(IMeshData::SequenceOfInteger*)thePolygon; - Handle(BRepMesh_DataStructureOfDelaun) aMeshData = + Handle(BRepMesh_DataStructureOfDelaun) aMeshData = *(Handle(BRepMesh_DataStructureOfDelaun)*)theMeshHandlePtr; if (aMeshData.IsNull()) @@ -2498,7 +2514,7 @@ Standard_CString BRepMesh_DumpPoly(void* thePolygon, { OCC_CATCH_SIGNALS - BRepMesh::SequenceOfInteger::Iterator aLinksIt(aPolygon); + IMeshData::SequenceOfInteger::Iterator aLinksIt(aPolygon); for (; aLinksIt.More(); aLinksIt.Next()) { const BRepMesh_Edge& aLink = aMeshData->GetLink(Abs(aLinksIt.Value())); diff --git a/src/BRepMesh/BRepMesh_Delaun.hxx b/src/BRepMesh/BRepMesh_Delaun.hxx index 18f1339c11..f03a333a11 100755 --- a/src/BRepMesh/BRepMesh_Delaun.hxx +++ b/src/BRepMesh/BRepMesh_Delaun.hxx @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include #include @@ -33,7 +33,6 @@ class Bnd_B2d; class Bnd_Box2d; class BRepMesh_Vertex; -class Message_ProgressSentry; //! Compute the Delaunay's triangulation with the algorithm of Watson. class BRepMesh_Delaun @@ -42,29 +41,41 @@ public: DEFINE_STANDARD_ALLOC + //! Creates instance of triangulator, but do not run the algorithm automatically. + Standard_EXPORT BRepMesh_Delaun (const Handle(BRepMesh_DataStructureOfDelaun)& theOldMesh, + const Standard_Integer theCellsCountU, + const Standard_Integer theCellsCountV, + const Standard_Boolean isFillCircles); + //! Creates the triangulation with an empty Mesh data structure. - Standard_EXPORT BRepMesh_Delaun (BRepMesh::Array1OfVertexOfDelaun& theVertices); + Standard_EXPORT BRepMesh_Delaun (IMeshData::Array1OfVertexOfDelaun& theVertices); //! Creates the triangulation with an existent Mesh data structure. Standard_EXPORT BRepMesh_Delaun (const Handle(BRepMesh_DataStructureOfDelaun)& theOldMesh, - BRepMesh::Array1OfVertexOfDelaun& theVertices); + IMeshData::Array1OfVertexOfDelaun& theVertices); //! Creates the triangulation with an existant Mesh data structure. Standard_EXPORT BRepMesh_Delaun (const Handle(BRepMesh_DataStructureOfDelaun)& theOldMesh, - BRepMesh::Array1OfInteger& theVertexIndices); + IMeshData::VectorOfInteger& theVertexIndices); + + //! Creates the triangulation with an existant Mesh data structure. + Standard_EXPORT BRepMesh_Delaun (const Handle (BRepMesh_DataStructureOfDelaun)& theOldMesh, + IMeshData::VectorOfInteger& theVertexIndices, + const Standard_Integer theCellsCountU, + const Standard_Integer theCellsCountV); //! Initializes the triangulation with an array of vertices. - Standard_EXPORT void Init (BRepMesh::Array1OfVertexOfDelaun& theVertices); + Standard_EXPORT void Init (IMeshData::Array1OfVertexOfDelaun& theVertices); + + //! Forces initialization of circles cell filter using working structure. + Standard_EXPORT void InitCirclesTool (const Standard_Integer theCellsCountU, + const Standard_Integer theCellsCountV); //! Removes a vertex from the triangulation. Standard_EXPORT void RemoveVertex (const BRepMesh_Vertex& theVertex); //! Adds some vertices into the triangulation. - Standard_EXPORT void AddVertices (BRepMesh::Array1OfVertexOfDelaun& theVertices); - - //! Adds some vertices into the triangulation. - Standard_EXPORT void AddVertices (BRepMesh::Array1OfVertexOfDelaun& theVertices, - Message_ProgressSentry* theProgressEntry); + Standard_EXPORT void AddVertices (IMeshData::VectorOfInteger& theVerticesIndices); //! Modify mesh to use the edge. //! @return True if done @@ -76,20 +87,29 @@ public: return myMeshData; } + //! Forces insertion of constraint edges into the base triangulation. + inline void ProcessConstraints() + { + insertInternalEdges(); + + // Adjustment of meshes to boundary edges + frontierAdjust(); + } + //! Gives the list of frontier edges. - inline BRepMesh::HMapOfInteger Frontier() const + inline Handle(IMeshData::MapOfInteger) Frontier() const { return getEdgesByType (BRepMesh_Frontier); } //! Gives the list of internal edges. - inline BRepMesh::HMapOfInteger InternalEdges() const + inline Handle(IMeshData::MapOfInteger) InternalEdges() const { return getEdgesByType (BRepMesh_Fixed); } //! Gives the list of free edges used only one time - inline BRepMesh::HMapOfInteger FreeEdges() const + inline Handle(IMeshData::MapOfInteger) FreeEdges() const { return getEdgesByType (BRepMesh_Free); } @@ -136,74 +156,80 @@ private: InsertBefore }; - typedef NCollection_DataMap DataMapOfMap; + typedef NCollection_DataMap DataMapOfMap; + + //! Performs initialization of circles cell filter tool. + void initCirclesTool (const Bnd_Box2d& theBox, + const Standard_Integer theCellsCountU, + const Standard_Integer theCellsCountV); //! Add boundig box for edge defined by start & end point to //! the given vector of bounding boxes for triangulation edges. - void fillBndBox (BRepMesh::SequenceOfBndB2d& theBoxes, + void fillBndBox (IMeshData::SequenceOfBndB2d& theBoxes, const BRepMesh_Vertex& theV1, const BRepMesh_Vertex& theV2); //! Gives the list of edges with type defined by the input parameter. //! If the given type is BRepMesh_Free returns list of edges //! that have number of connected elements less or equal 1. - BRepMesh::HMapOfInteger getEdgesByType (const BRepMesh_DegreeOfFreedom theEdgeType) const; + Handle(IMeshData::MapOfInteger) getEdgesByType (const BRepMesh_DegreeOfFreedom theEdgeType) const; - //! Create super mesh and run triangulation procedure. - void perform (Bnd_Box2d& theBndBox, - BRepMesh::Array1OfInteger& theVertexIndices); + //! Run triangulation procedure. + void perform (IMeshData::VectorOfInteger& theVertexIndices, + const Standard_Integer theCellsCountU = -1, + const Standard_Integer theCellsCountV = -1); //! Build the super mesh. void superMesh (const Bnd_Box2d& theBox); //! Computes the triangulation and adds the vertices, //! edges and triangles to the Mesh data structure. - void compute (BRepMesh::Array1OfInteger& theVertexIndices); + void compute (IMeshData::VectorOfInteger& theVertexIndices); //! Adjust the mesh on the frontier. void frontierAdjust(); //! Find left polygon of the given edge and call meshPolygon. Standard_Boolean meshLeftPolygonOf( - const Standard_Integer theEdgeIndex, - const Standard_Boolean isForward, - BRepMesh::HMapOfInteger theSkipped = NULL); + const Standard_Integer theEdgeIndex, + const Standard_Boolean isForward, + Handle(IMeshData::MapOfInteger) theSkipped = NULL); //! Find next link starting from the given node and has maximum //! angle respect the given reference link. //! Each time the next link is found other neighbor links at the pivot //! node are marked as leprous and will be excluded from consideration //! next time until a hanging end is occured. - Standard_Integer findNextPolygonLink (const Standard_Integer& theFirstNode, - const Standard_Integer& thePivotNode, - const BRepMesh_Vertex& thePivotVertex, - const gp_Vec2d& theRefLinkDir, - const BRepMesh::SequenceOfBndB2d& theBoxes, - const BRepMesh::SequenceOfInteger& thePolygon, - const BRepMesh::HMapOfInteger theSkipped, - const Standard_Boolean& isSkipLeprous, - BRepMesh::MapOfInteger& theLeprousLinks, - BRepMesh::MapOfInteger& theDeadLinks, - Standard_Integer& theNextPivotNode, - gp_Vec2d& theNextLinkDir, - Bnd_B2d& theNextLinkBndBox); + Standard_Integer findNextPolygonLink (const Standard_Integer& theFirstNode, + const Standard_Integer& thePivotNode, + const BRepMesh_Vertex& thePivotVertex, + const gp_Vec2d& theRefLinkDir, + const IMeshData::SequenceOfBndB2d& theBoxes, + const IMeshData::SequenceOfInteger& thePolygon, + const Handle(IMeshData::MapOfInteger) theSkipped, + const Standard_Boolean& isSkipLeprous, + IMeshData::MapOfInteger& theLeprousLinks, + IMeshData::MapOfInteger& theDeadLinks, + Standard_Integer& theNextPivotNode, + gp_Vec2d& theNextLinkDir, + Bnd_B2d& theNextLinkBndBox); //! Check is the given link intersects the polygon boundaries. //! Returns bounding box for the given link trough the theLinkBndBox parameter. - Standard_Boolean checkIntersection (const BRepMesh_Edge& theLink, - const BRepMesh::SequenceOfInteger& thePolygon, - const BRepMesh::SequenceOfBndB2d& thePolyBoxes, - const Standard_Boolean isConsiderEndPointTouch, - const Standard_Boolean isConsiderPointOnEdge, - const Standard_Boolean isSkipLastEdge, - Bnd_B2d& theLinkBndBox) const; + Standard_Boolean checkIntersection (const BRepMesh_Edge& theLink, + const IMeshData::SequenceOfInteger& thePolygon, + const IMeshData::SequenceOfBndB2d& thePolyBoxes, + const Standard_Boolean isConsiderEndPointTouch, + const Standard_Boolean isConsiderPointOnEdge, + const Standard_Boolean isSkipLastEdge, + Bnd_B2d& theLinkBndBox) const; //! Triangulatiion of a closed polygon described by the list //! of indexes of its edges in the structure. //! (negative index means reversed edge) - void meshPolygon (BRepMesh::SequenceOfInteger& thePolygon, - BRepMesh::SequenceOfBndB2d& thePolyBoxes, - BRepMesh::HMapOfInteger theSkipped = NULL); + void meshPolygon (IMeshData::SequenceOfInteger& thePolygon, + IMeshData::SequenceOfBndB2d& thePolyBoxes, + Handle(IMeshData::MapOfInteger) theSkipped = NULL); //! Decomposes the given closed simple polygon (polygon without glued edges //! and loops) on two simpler ones by adding new link at the most thin part @@ -215,31 +241,27 @@ private: //! @param thePolygonCut product of decomposition of source polygon (second part of decomposition). //! @param thePolyBoxesCut bounding boxes corresponded to resulting polygon's links. void decomposeSimplePolygon ( - BRepMesh::SequenceOfInteger& thePolygon, - BRepMesh::SequenceOfBndB2d& thePolyBoxes, - BRepMesh::SequenceOfInteger& thePolygonCut, - BRepMesh::SequenceOfBndB2d& thePolyBoxesCut); + IMeshData::SequenceOfInteger& thePolygon, + IMeshData::SequenceOfBndB2d& thePolyBoxes, + IMeshData::SequenceOfInteger& thePolygonCut, + IMeshData::SequenceOfBndB2d& thePolyBoxesCut); //! Triangulation of closed polygon containing only three edges. - inline Standard_Boolean meshElementaryPolygon (const BRepMesh::SequenceOfInteger& thePolygon); + inline Standard_Boolean meshElementaryPolygon (const IMeshData::SequenceOfInteger& thePolygon); //! Creates the triangles beetween the given node and the given polyline. void createTriangles (const Standard_Integer theVertexIndex, - BRepMesh::MapOfIntegerInteger& thePoly); - - void createTriangles (const Standard_Integer theVertexIndex, - BRepMesh::MapOfIntegerInteger& thePoly, - Message_ProgressSentry* theProgressEntry); + IMeshData::MapOfIntegerInteger& thePoly); //! Add a triangle based on the given oriented edges into mesh - void addTriangle (const Standard_Integer (&theEdgesId)[3], - const Standard_Boolean (&theEdgesOri)[3], - const Standard_Integer (&theNodesId)[3]); + inline void addTriangle (const Standard_Integer (&theEdgesId)[3], + const Standard_Boolean (&theEdgesOri)[3], + const Standard_Integer (&theNodesId)[3]); //! Deletes the triangle with the given index and adds the free edges into the map. //! When an edge is suppressed more than one time it is destroyed. void deleteTriangle (const Standard_Integer theIndex, - BRepMesh::MapOfIntegerInteger& theLoopEdges); + IMeshData::MapOfIntegerInteger& theLoopEdges); //! Returns start and end nodes of the given edge in respect to its orientation. void getOrientedNodes (const BRepMesh_Edge& theEdge, @@ -248,25 +270,21 @@ private: //! Processes loop within the given polygon formed by range of its //! links specified by start and end link indices. - void processLoop (const Standard_Integer theLinkFrom, - const Standard_Integer theLinkTo, - const BRepMesh::SequenceOfInteger& thePolygon, - const BRepMesh::SequenceOfBndB2d& thePolyBoxes); + void processLoop (const Standard_Integer theLinkFrom, + const Standard_Integer theLinkTo, + const IMeshData::SequenceOfInteger& thePolygon, + const IMeshData::SequenceOfBndB2d& thePolyBoxes); //! Creates new link based on the given nodes and updates the given polygon. - Standard_Integer createAndReplacePolygonLink (const Standard_Integer theNodes[], - const gp_Pnt2d thePnts [], - const Standard_Integer theRootIndex, - const ReplaceFlag theReplaceFlag, - BRepMesh::SequenceOfInteger& thePolygon, - BRepMesh::SequenceOfBndB2d& thePolyBoxes); + Standard_Integer createAndReplacePolygonLink (const Standard_Integer theNodes[], + const gp_Pnt2d thePnts [], + const Standard_Integer theRootIndex, + const ReplaceFlag theReplaceFlag, + IMeshData::SequenceOfInteger& thePolygon, + IMeshData::SequenceOfBndB2d& thePolyBoxes); //! Creates the triangles on new nodes. - void createTrianglesOnNewVertices (BRepMesh::Array1OfInteger& theVertexIndices, - Message_ProgressSentry* theProgressEntry); - - //! Creates the triangles on new nodes. - void createTrianglesOnNewVertices (BRepMesh::Array1OfInteger& theVertexIndices); + void createTrianglesOnNewVertices (IMeshData::VectorOfInteger& theVertexIndices); //! Cleanup mesh from the free triangles. void cleanupMesh(); @@ -282,35 +300,35 @@ private: const Standard_Integer thePrevElementId); //! Remove internal triangles from the given polygon. - void cleanupPolygon (const BRepMesh::SequenceOfInteger& thePolygon, - const BRepMesh::SequenceOfBndB2d& thePolyBoxes); + void cleanupPolygon (const IMeshData::SequenceOfInteger& thePolygon, + const IMeshData::SequenceOfBndB2d& thePolyBoxes); //! Checks is the given vertex lies inside the polygon. - Standard_Boolean isVertexInsidePolygon (const Standard_Integer& theVertexId, - const BRepMesh::VectorOfInteger& thePolygonVertices) const; + Standard_Boolean isVertexInsidePolygon (const Standard_Integer& theVertexId, + const IMeshData::VectorOfInteger& thePolygonVertices) const; //! Remove all triangles and edges that are placed inside the polygon or crossed it. - void killTrianglesAroundVertex (const Standard_Integer theZombieNodeId, - const BRepMesh::VectorOfInteger& thePolyVertices, - const BRepMesh::MapOfInteger& thePolyVerticesFindMap, - const BRepMesh::SequenceOfInteger& thePolygon, - const BRepMesh::SequenceOfBndB2d& thePolyBoxes, - BRepMesh::MapOfInteger& theSurvivedLinks, - BRepMesh::MapOfIntegerInteger& theLoopEdges); + void killTrianglesAroundVertex (const Standard_Integer theZombieNodeId, + const IMeshData::VectorOfInteger& thePolyVertices, + const IMeshData::MapOfInteger& thePolyVerticesFindMap, + const IMeshData::SequenceOfInteger& thePolygon, + const IMeshData::SequenceOfBndB2d& thePolyBoxes, + IMeshData::MapOfInteger& theSurvivedLinks, + IMeshData::MapOfIntegerInteger& theLoopEdges); //! Checks is the given link crosses the polygon boundary. //! If yes, kills its triangles and checks neighbor links on boundary intersection. Does nothing elsewhere. - void killTrianglesOnIntersectingLinks (const Standard_Integer& theLinkToCheckId, - const BRepMesh_Edge& theLinkToCheck, - const Standard_Integer& theEndPoint, - const BRepMesh::SequenceOfInteger& thePolygon, - const BRepMesh::SequenceOfBndB2d& thePolyBoxes, - BRepMesh::MapOfInteger& theSurvivedLinks, - BRepMesh::MapOfIntegerInteger& theLoopEdges); + void killTrianglesOnIntersectingLinks (const Standard_Integer& theLinkToCheckId, + const BRepMesh_Edge& theLinkToCheck, + const Standard_Integer& theEndPoint, + const IMeshData::SequenceOfInteger& thePolygon, + const IMeshData::SequenceOfBndB2d& thePolyBoxes, + IMeshData::MapOfInteger& theSurvivedLinks, + IMeshData::MapOfIntegerInteger& theLoopEdges); //! Kill triangles bound to the given link. - void killLinkTriangles (const Standard_Integer& theLinkId, - BRepMesh::MapOfIntegerInteger& theLoopEdges); + void killLinkTriangles (const Standard_Integer& theLinkId, + IMeshData::MapOfIntegerInteger& theLoopEdges); //! Calculates distances between the given point and edges of triangle. Standard_Real calculateDist (const gp_XY theVEdges[3], @@ -329,16 +347,13 @@ private: gp_Pnt2d& theIntPnt) const; //! Returns area of the loop of the given polygon defined by indices of its start and end links. - Standard_Real polyArea (const BRepMesh::SequenceOfInteger& thePolygon, - const Standard_Integer theStartIndex, - const Standard_Integer theEndIndex) const; + Standard_Real polyArea (const IMeshData::SequenceOfInteger& thePolygon, + const Standard_Integer theStartIndex, + const Standard_Integer theEndIndex) const; //! Performs insertion of internal edges into mesh. void insertInternalEdges(); - //! Performs insertion of internal edges into mesh. - void insertInternalEdges (Message_ProgressSentry* theProgressEntry); - private: Handle(BRepMesh_DataStructureOfDelaun) myMeshData; diff --git a/src/BRepMesh/BRepMesh_DelaunayBaseMeshAlgo.cxx b/src/BRepMesh/BRepMesh_DelaunayBaseMeshAlgo.cxx new file mode 100644 index 0000000000..1394bd7a4a --- /dev/null +++ b/src/BRepMesh/BRepMesh_DelaunayBaseMeshAlgo.cxx @@ -0,0 +1,57 @@ +// Created on: 2016-04-19 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 +#include +#include + +//======================================================================= +// Function: Constructor +// Purpose : +//======================================================================= +BRepMesh_DelaunayBaseMeshAlgo::BRepMesh_DelaunayBaseMeshAlgo() +{ +} + +//======================================================================= +// Function: Destructor +// Purpose : +//======================================================================= +BRepMesh_DelaunayBaseMeshAlgo::~BRepMesh_DelaunayBaseMeshAlgo() +{ +} + +//======================================================================= +//function : generateMesh +//purpose : +//======================================================================= +void BRepMesh_DelaunayBaseMeshAlgo::generateMesh() +{ + const Handle(BRepMesh_DataStructureOfDelaun)& aStructure = getStructure(); + const Handle(VectorOfPnt)& aNodesMap = getNodesMap(); + + IMeshData::VectorOfInteger aVerticesOrder(aNodesMap->Size(), getAllocator()); + for (Standard_Integer i = 1; i <= aNodesMap->Size(); ++i) + { + aVerticesOrder.Append(i); + } + + std::pair aCellsCount = getCellsCount (aVerticesOrder.Size ()); + BRepMesh_Delaun aMesher(aStructure, aVerticesOrder, aCellsCount.first, aCellsCount.second); + BRepMesh_MeshTool aCleaner(aStructure); + aCleaner.EraseFreeLinks(); + + postProcessMesh(aMesher); +} diff --git a/src/BRepMesh/BRepMesh_DelaunayBaseMeshAlgo.hxx b/src/BRepMesh/BRepMesh_DelaunayBaseMeshAlgo.hxx new file mode 100644 index 0000000000..81bfdc7c9f --- /dev/null +++ b/src/BRepMesh/BRepMesh_DelaunayBaseMeshAlgo.hxx @@ -0,0 +1,46 @@ +// Created on: 2016-07-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _BRepMesh_DelaunayBaseMeshAlgo_HeaderFile +#define _BRepMesh_DelaunayBaseMeshAlgo_HeaderFile + +#include +#include +#include + +class BRepMesh_DataStructureOfDelaun; +class BRepMesh_Delaun; + +//! Class provides base fuctionality to build face triangulation using Dealunay approach. +//! Performs generation of mesh using raw data from model. +class BRepMesh_DelaunayBaseMeshAlgo : public BRepMesh_ConstrainedBaseMeshAlgo +{ +public: + + //! Constructor. + Standard_EXPORT BRepMesh_DelaunayBaseMeshAlgo(); + + //! Destructor. + Standard_EXPORT virtual ~BRepMesh_DelaunayBaseMeshAlgo(); + + DEFINE_STANDARD_RTTI_INLINE(BRepMesh_DelaunayBaseMeshAlgo, BRepMesh_ConstrainedBaseMeshAlgo) + +protected: + + //! Generates mesh for the contour stored in data structure. + Standard_EXPORT virtual void generateMesh() Standard_OVERRIDE; +}; + +#endif diff --git a/src/BRepMesh/BRepMesh_DelaunayDeflectionControlMeshAlgo.hxx b/src/BRepMesh/BRepMesh_DelaunayDeflectionControlMeshAlgo.hxx new file mode 100644 index 0000000000..04f4708d66 --- /dev/null +++ b/src/BRepMesh/BRepMesh_DelaunayDeflectionControlMeshAlgo.hxx @@ -0,0 +1,452 @@ +// Created on: 2016-07-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _BRepMeshTools_DelaunayDeflectionControlMeshAlgo_HeaderFile +#define _BRepMeshTools_DelaunayDeflectionControlMeshAlgo_HeaderFile + +#include +#include +#include + +//! Extends node insertion Delaunay meshing algo in order to control +//! deflection of generated trianges. Splits triangles failing the check. +template +class BRepMesh_DelaunayDeflectionControlMeshAlgo : public BRepMesh_DelaunayNodeInsertionMeshAlgo +{ +private: + // Typedef for OCCT RTTI + typedef BRepMesh_DelaunayNodeInsertionMeshAlgo DelaunayInsertionBaseClass; + +public: + + //! Constructor. + BRepMesh_DelaunayDeflectionControlMeshAlgo() + : myMaxSqDeflection(-1.), + myIsAllDegenerated(Standard_False) + { + } + + //! Destructor. + virtual ~BRepMesh_DelaunayDeflectionControlMeshAlgo() + { + } + +protected: + + //! Perfroms processing of generated mesh. Generates surface nodes and inserts them into structure. + virtual void postProcessMesh(BRepMesh_Delaun& theMesher) Standard_OVERRIDE + { + // Insert surface nodes. + DelaunayInsertionBaseClass::postProcessMesh(theMesher); + + if (this->getParameters().ControlSurfaceDeflection && + this->getStructure()->ElementsOfDomain().Extent() > 0) + { + optimizeMesh(theMesher); + } + } + + //! Checks deviation of a mesh from geometrical surface. + //! Inserts additional nodes in case of huge deviation. + virtual void optimizeMesh(BRepMesh_Delaun& theMesher) + { + Handle(NCollection_IncAllocator) aTmpAlloc = + new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE); + + myCouplesMap = new IMeshData::MapOfOrientedEdges(3 * this->getStructure()->ElementsOfDomain().Extent(), aTmpAlloc); + myControlNodes = new IMeshData::ListOfPnt2d(aTmpAlloc); + myCircles = &theMesher.Circles(); + + const Standard_Integer aIterationsNb = 11; + Standard_Boolean isInserted = Standard_True; + for (Standard_Integer aPass = 1; aPass <= aIterationsNb && isInserted && !myIsAllDegenerated; ++aPass) + { + // Reset stop condition + myMaxSqDeflection = -1.; + myIsAllDegenerated = Standard_True; + myControlNodes->Clear(); + + if (this->getStructure()->ElementsOfDomain().Extent() < 1) + { + break; + } + + // Iterate on current triangles + IMeshData::IteratorOfMapOfInteger aTriangleIt(this->getStructure()->ElementsOfDomain()); + for (; aTriangleIt.More(); aTriangleIt.Next()) + { + const BRepMesh_Triangle& aTriangle = this->getStructure()->GetElement(aTriangleIt.Key()); + splitTriangleGeometry(aTriangle); + } + + isInserted = this->insertNodes(myControlNodes, theMesher); + } + + myCouplesMap.Nullify(); + myControlNodes.Nullify(); + + if (!(myMaxSqDeflection < 0.)) + { + this->getDFace()->SetDeflection(Sqrt(myMaxSqDeflection)); + } + } + +private: + //! Contains geometrical data related to node of triangle. + struct TriangleNodeInfo + { + gp_XY Point2d; + gp_XYZ Point; + Standard_Boolean isFrontierLink; + }; + + //! Functor computing deflection of a point from surface. + class NormalDeviation + { + public: + NormalDeviation( + const gp_Pnt& theRefPnt, + const gp_Vec& theNormal) + : myRefPnt(theRefPnt), + myNormal(theNormal) + { + } + + Standard_Real SquareDeviation(const gp_Pnt& thePoint) const + { + const Standard_Real aDeflection = Abs(myNormal.Dot(gp_Vec(myRefPnt, thePoint))); + return aDeflection * aDeflection; + } + + private: + + NormalDeviation (const NormalDeviation& theOther); + + void operator= (const NormalDeviation& theOther); + + private: + + const gp_Pnt& myRefPnt; + const gp_Vec& myNormal; + }; + + //! Functor computing deflection of a point on triangle link from surface. + class LineDeviation + { + public: + + LineDeviation( + const gp_Pnt& thePnt1, + const gp_Pnt& thePnt2) + : myPnt1(thePnt1), + myPnt2(thePnt2) + { + } + + Standard_Real SquareDeviation(const gp_Pnt& thePoint) const + { + return BRepMesh_GeomTool::SquareDeflectionOfSegment(myPnt1, myPnt2, thePoint); + } + + private: + + LineDeviation (const LineDeviation& theOther); + + void operator= (const LineDeviation& theOther); + + private: + const gp_Pnt& myPnt1; + const gp_Pnt& myPnt2; + }; + + //! Returns nodes info of the given triangle. + inline void getTriangleInfo( + const BRepMesh_Triangle& theTriangle, + const Standard_Integer (&theNodesIndices)[3], + TriangleNodeInfo (&theInfo)[3]) const + { + const Standard_Integer(&e)[3] = theTriangle.myEdges; + for (Standard_Integer i = 0; i < 3; ++i) + { + const BRepMesh_Vertex& aVertex = this->getStructure()->GetNode(theNodesIndices[i]); + theInfo[i].Point2d = this->getRangeSplitter().Scale(aVertex.Coord(), Standard_False).XY(); + theInfo[i].Point = this->getNodesMap()->Value(aVertex.Location3d()).XYZ(); + theInfo[i].isFrontierLink = (this->getStructure()->GetLink(e[i]).Movability() == BRepMesh_Frontier); + } + } + + // Check geometry of the given triangle. If triangle does not suit specified deflection, inserts new point. + void splitTriangleGeometry(const BRepMesh_Triangle& theTriangle) + { + if (theTriangle.Movability() != BRepMesh_Deleted) + { + Standard_Integer aNodexIndices[3]; + this->getStructure()->ElementNodes(theTriangle, aNodexIndices); + + TriangleNodeInfo aNodesInfo[3]; + getTriangleInfo(theTriangle, aNodexIndices, aNodesInfo); + + gp_Vec aNormal; + gp_Vec aLinkVec[3]; + if (computeTriangleGeometry(aNodesInfo, aLinkVec, aNormal)) + { + myIsAllDegenerated = Standard_False; + + const gp_XY aCenter2d = (aNodesInfo[0].Point2d + + aNodesInfo[1].Point2d + + aNodesInfo[2].Point2d) / 3.; + + usePoint(aCenter2d, NormalDeviation(aNodesInfo[0].Point, aNormal)); + splitLinks(aNodesInfo, aNodexIndices); + } + } + } + + //! Updates array of links vectors. + //! @return False on degenerative triangle. + inline Standard_Boolean computeTriangleGeometry( + const TriangleNodeInfo(&theNodesInfo)[3], + gp_Vec (&theLinks)[3], + gp_Vec &theNormal) + { + if (checkTriangleForDegenerativityAndGetLinks(theNodesInfo, theLinks)) + { + if (checkTriangleArea2d(theNodesInfo)) + { + if (computeNormal(theLinks[0], theLinks[1], theNormal)) + { + return Standard_True; + } + } + } + + return Standard_False; + } + + //! Updates array of links vectors. + //! @return False on degenerative triangle. + inline Standard_Boolean checkTriangleForDegenerativityAndGetLinks( + const TriangleNodeInfo (&theNodesInfo)[3], + gp_Vec (&theLinks)[3]) + { + const Standard_Real MinimalSqLength3d = 1.e-12; + for (Standard_Integer i = 0; i < 3; ++i) + { + theLinks[i] = theNodesInfo[(i + 1) % 3].Point - theNodesInfo[i].Point; + if (theLinks[i].SquareMagnitude() < MinimalSqLength3d) + { + return Standard_False; + } + } + + return Standard_True; + } + + //! Checks area of triangle in parametric space for degenerativity. + //! @return False on degenerative triangle. + inline Standard_Boolean checkTriangleArea2d( + const TriangleNodeInfo (&theNodesInfo)[3]) + { + const gp_Vec2d aLink2d1(theNodesInfo[0].Point2d, theNodesInfo[1].Point2d); + const gp_Vec2d aLink2d2(theNodesInfo[1].Point2d, theNodesInfo[2].Point2d); + + const Standard_Real MinimalArea2d = 1.e-9; + return (Abs(aLink2d1 ^ aLink2d2) > MinimalArea2d); + } + + //! Computes normal using two link vectors. + //! @return True on success, False in case of normal of null magnitude. + inline Standard_Boolean computeNormal(const gp_Vec& theLink1, + const gp_Vec& theLink2, + gp_Vec& theNormal) + { + const gp_Vec aNormal(theLink1 ^ theLink2); + if (aNormal.SquareMagnitude() > gp::Resolution()) + { + theNormal = aNormal.Normalized(); + return Standard_True; + } + + return Standard_False; + } + + //! Computes deflection of midpoints of triangles links. + //! @return True if point fits specified deflection. + inline void splitLinks( + const TriangleNodeInfo (&theNodesInfo)[3], + const Standard_Integer (&theNodesIndices)[3]) + { + // Check deflection at triangle links + for (Standard_Integer i = 0; i < 3; ++i) + { + if (theNodesInfo[i].isFrontierLink) + { + continue; + } + + const Standard_Integer j = (i + 1) % 3; + // Check if this link was already processed + Standard_Integer aFirstVertex, aLastVertex; + if (theNodesIndices[i] < theNodesIndices[j]) + { + aFirstVertex = theNodesIndices[i]; + aLastVertex = theNodesIndices[j]; + } + else + { + aFirstVertex = theNodesIndices[j]; + aLastVertex = theNodesIndices[i]; + } + + if (myCouplesMap->Add(BRepMesh_OrientedEdge(aFirstVertex, aLastVertex))) + { + const gp_XY aMidPnt2d = (theNodesInfo[i].Point2d + + theNodesInfo[j].Point2d) / 2.; + + if (!usePoint (aMidPnt2d, LineDeviation (theNodesInfo[i].Point, + theNodesInfo[j].Point))) + { + if (!checkLinkEndsForAngularDeviation(theNodesInfo[i], + theNodesInfo[j], + aMidPnt2d)) + { + myControlNodes->Append(aMidPnt2d); + } + } + } + } + } + + //! Checks the given point (located between the given nodes) + //! for specified angular deviation. + Standard_Boolean checkLinkEndsForAngularDeviation(const TriangleNodeInfo& theNodeInfo1, + const TriangleNodeInfo& theNodeInfo2, + const gp_XY& /*theMidPoint*/) + { + gp_Dir aNorm1, aNorm2; + const Handle(Geom_Surface)& aSurf = + this->getDFace()->GetSurface()->ChangeSurface().Surface().Surface(); + + if ((GeomLib::NormEstim(aSurf, theNodeInfo1.Point2d, Precision::Confusion(), aNorm1) == 0) && + (GeomLib::NormEstim(aSurf, theNodeInfo2.Point2d, Precision::Confusion(), aNorm2) == 0)) + { + Standard_Real anAngle = aNorm1.Angle(aNorm2); + if (anAngle > this->getParameters().AngleInterior) + return Standard_False; + } +#if 0 + else if (GeomLib::NormEstim(aSurf, theMidPoint, Precision::Confusion(), aNorm1) != 0) + { + // It is better to consider the singular point as a node of triangulation. + // However, it leads to hangs up meshing some faces (including faces with + // degenerated edges). E.g. tests "mesh standard_incmesh Q6". + // So, this code fragment is better to implement in the future. + return Standard_False; + } +#endif + + return Standard_True; + } + + //! Computes deflection of the given point and caches it for + //! insertion in case if it overflows deflection. + //! @return True if point has been cached for insertion. + template + inline Standard_Boolean usePoint( + const gp_XY& thePnt2d, + const DeflectionFunctor& theDeflectionFunctor) + { + gp_Pnt aPnt; + this->getDFace()->GetSurface()->D0(thePnt2d.X(), thePnt2d.Y(), aPnt); + if (!checkDeflectionOfPointAndUpdateCache(thePnt2d, aPnt, theDeflectionFunctor.SquareDeviation(aPnt))) + { + myControlNodes->Append(thePnt2d); + return Standard_True; + } + + return Standard_False; + } + + //! Checks the given point for specified linear deflection. + //! Updates value of total mesh defleciton. + Standard_Boolean checkDeflectionOfPointAndUpdateCache( + const gp_XY& thePnt2d, + const gp_Pnt& thePnt3d, + const Standard_Real theSqDeflection) + { + if (theSqDeflection > myMaxSqDeflection) + { + myMaxSqDeflection = theSqDeflection; + } + + const Standard_Real aSqDeflection = + this->getDFace()->GetDeflection() * this->getDFace()->GetDeflection(); + if (theSqDeflection < aSqDeflection) + { + return Standard_True; + } + + return rejectByMinSize(thePnt2d, thePnt3d); + } + + //! Checks the given node for + Standard_Boolean rejectByMinSize( + const gp_XY& thePnt2d, + const gp_Pnt& thePnt3d) + { + const Standard_Real aSqMinSize = + this->getParameters().MinSize * this->getParameters().MinSize; + + IMeshData::MapOfInteger aUsedNodes; + IMeshData::ListOfInteger& aCirclesList = + const_cast(*myCircles).Select( + this->getRangeSplitter().Scale(thePnt2d, Standard_True).XY()); + + IMeshData::ListOfInteger::Iterator aCircleIt(aCirclesList); + for (; aCircleIt.More(); aCircleIt.Next()) + { + const BRepMesh_Triangle& aTriangle = this->getStructure()->GetElement(aCircleIt.Value()); + + Standard_Integer aNodes[3]; + this->getStructure()->ElementNodes(aTriangle, aNodes); + + for (Standard_Integer i = 0; i < 3; ++i) + { + if (!aUsedNodes.Contains(aNodes[i])) + { + aUsedNodes.Add(aNodes[i]); + const BRepMesh_Vertex& aVertex = this->getStructure()->GetNode(aNodes[i]); + const gp_Pnt& aPoint = this->getNodesMap()->Value(aVertex.Location3d()); + + if (thePnt3d.SquareDistance(aPoint) < aSqMinSize) + { + return Standard_True; + } + } + } + } + + return Standard_False; + } + +private: + Standard_Real myMaxSqDeflection; + Standard_Boolean myIsAllDegenerated; + Handle(IMeshData::MapOfOrientedEdges) myCouplesMap; + Handle(IMeshData::ListOfPnt2d) myControlNodes; + const BRepMesh_CircleTool* myCircles; +}; + +#endif diff --git a/src/BRepMesh/BRepMesh_DelaunayNodeInsertionMeshAlgo.hxx b/src/BRepMesh/BRepMesh_DelaunayNodeInsertionMeshAlgo.hxx new file mode 100644 index 0000000000..ccbe55278e --- /dev/null +++ b/src/BRepMesh/BRepMesh_DelaunayNodeInsertionMeshAlgo.hxx @@ -0,0 +1,159 @@ +// Created on: 2016-07-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _BRepMesh_DelaunayNodeInsertionMeshAlgo_HeaderFile +#define _BRepMesh_DelaunayNodeInsertionMeshAlgo_HeaderFile + +#include +#include + +//! Extends base Delaunay meshing algo in order to enable possibility +//! of addition of free vertices and internal nodes into the mesh. +template +class BRepMesh_DelaunayNodeInsertionMeshAlgo : public BRepMesh_NodeInsertionMeshAlgo +{ +private: + // Typedef for OCCT RTTI + typedef BRepMesh_NodeInsertionMeshAlgo InsertionBaseClass; + +public: + + //! Constructor. + BRepMesh_DelaunayNodeInsertionMeshAlgo() + : myIsPreProcessSurfaceNodes (Standard_False) + { + } + + //! Destructor. + virtual ~BRepMesh_DelaunayNodeInsertionMeshAlgo() + { + } + + //! Returns PreProcessSurfaceNodes flag. + inline Standard_Boolean IsPreProcessSurfaceNodes () const + { + return myIsPreProcessSurfaceNodes; + } + + //! Sets PreProcessSurfaceNodes flag. + //! If TRUE, registers surface nodes before generation of base mesh. + //! If FALSE, inserts surface nodes after generation of base mesh. + inline void SetPreProcessSurfaceNodes (const Standard_Boolean isPreProcessSurfaceNodes) + { + myIsPreProcessSurfaceNodes = isPreProcessSurfaceNodes; + } + +protected: + + //! Performs initialization of data structure using existing model data. + virtual Standard_Boolean initDataStructure() Standard_OVERRIDE + { + if (!InsertionBaseClass::initDataStructure()) + { + return Standard_False; + } + + if (myIsPreProcessSurfaceNodes) + { + const Handle(IMeshData::ListOfPnt2d) aSurfaceNodes = + this->getRangeSplitter().GenerateSurfaceNodes(this->getParameters()); + + registerSurfaceNodes (aSurfaceNodes); + } + + return Standard_True; + } + + //! Returns size of cell to be used by acceleration circles grid structure. + virtual std::pair getCellsCount (const Standard_Integer theVerticesNb) Standard_OVERRIDE + { + return BRepMesh_GeomTool::CellsCount (this->getDFace()->GetSurface(), theVerticesNb, + this->getDFace()->GetDeflection(), + &this->getRangeSplitter()); + } + + //! Perfroms processing of generated mesh. Generates surface nodes and inserts them into structure. + virtual void postProcessMesh(BRepMesh_Delaun& theMesher) Standard_OVERRIDE + { + InsertionBaseClass::postProcessMesh(theMesher); + + if (!myIsPreProcessSurfaceNodes) + { + const Handle(IMeshData::ListOfPnt2d) aSurfaceNodes = + this->getRangeSplitter().GenerateSurfaceNodes(this->getParameters()); + + insertNodes(aSurfaceNodes, theMesher); + } + } + + //! Inserts nodes into mesh. + Standard_Boolean insertNodes( + const Handle(IMeshData::ListOfPnt2d)& theNodes, + BRepMesh_Delaun& theMesher) + { + if (theNodes.IsNull() || theNodes->IsEmpty()) + { + return Standard_False; + } + + IMeshData::VectorOfInteger aVertexIndexes(theNodes->Size(), this->getAllocator()); + IMeshData::ListOfPnt2d::Iterator aNodesIt(*theNodes); + for (Standard_Integer aNodeIt = 1; aNodesIt.More(); aNodesIt.Next(), ++aNodeIt) + { + const gp_Pnt2d& aPnt2d = aNodesIt.Value(); + if (this->getClassifier()->Perform(aPnt2d) == TopAbs_IN) + { + aVertexIndexes.Append(this->registerNode(this->getRangeSplitter().Point(aPnt2d), + aPnt2d, BRepMesh_Free, Standard_False)); + } + } + + theMesher.AddVertices(aVertexIndexes); + return !aVertexIndexes.IsEmpty(); + } + +private: + + //! Registers surface nodes in data structure. + Standard_Boolean registerSurfaceNodes( + const Handle(IMeshData::ListOfPnt2d)& theNodes) + { + if (theNodes.IsNull() || theNodes->IsEmpty()) + { + return Standard_False; + } + + Standard_Boolean isAdded = Standard_False; + IMeshData::ListOfPnt2d::Iterator aNodesIt(*theNodes); + for (Standard_Integer aNodeIt = 1; aNodesIt.More(); aNodesIt.Next(), ++aNodeIt) + { + const gp_Pnt2d& aPnt2d = aNodesIt.Value(); + if (this->getClassifier()->Perform(aPnt2d) == TopAbs_IN) + { + isAdded = Standard_True; + this->registerNode(this->getRangeSplitter().Point(aPnt2d), + aPnt2d, BRepMesh_Free, Standard_False); + } + } + + return isAdded; + } + +private: + + Standard_Boolean myIsPreProcessSurfaceNodes; +}; + +#endif diff --git a/src/BRepMesh/BRepMesh_DiscretFactory.hxx b/src/BRepMesh/BRepMesh_DiscretFactory.hxx index dc47c791b2..a5f47d3111 100644 --- a/src/BRepMesh/BRepMesh_DiscretFactory.hxx +++ b/src/BRepMesh/BRepMesh_DiscretFactory.hxx @@ -47,7 +47,7 @@ public: //! Setup meshing algorithm by name.
//! Returns TRUE if requested tool is available.
//! On fail Factory will continue to use previous algo. - Standard_EXPORT Standard_Boolean SetDefaultName(const TCollection_AsciiString& theName) + Standard_Boolean SetDefaultName(const TCollection_AsciiString& theName) { return SetDefault(theName, myFunctionName); } @@ -61,7 +61,7 @@ public: //! Advanced function. Changes function name to retrieve from plugin.
//! Returns TRUE if requested tool is available.
//! On fail Factory will continue to use previous algo. - Standard_EXPORT Standard_Boolean SetFunctionName(const TCollection_AsciiString& theFuncName) + Standard_Boolean SetFunctionName(const TCollection_AsciiString& theFuncName) { return SetDefault(myDefaultName, theFuncName); } diff --git a/src/BRepMesh/BRepMesh_DiscretRoot.hxx b/src/BRepMesh/BRepMesh_DiscretRoot.hxx index f3834204df..361cf0e242 100644 --- a/src/BRepMesh/BRepMesh_DiscretRoot.hxx +++ b/src/BRepMesh/BRepMesh_DiscretRoot.hxx @@ -46,7 +46,7 @@ public: } //! Compute triangulation for set shape. - Standard_EXPORT virtual void Perform() = 0; + virtual void Perform() = 0; DEFINE_STANDARD_RTTIEXT(BRepMesh_DiscretRoot,Standard_Transient) diff --git a/src/BRepMesh/BRepMesh_Edge.hxx b/src/BRepMesh/BRepMesh_Edge.hxx index 0eb80ddd42..3ef8151311 100644 --- a/src/BRepMesh/BRepMesh_Edge.hxx +++ b/src/BRepMesh/BRepMesh_Edge.hxx @@ -76,7 +76,7 @@ public: } //! Alias for IsEqual. - Standard_Boolean operator ==(const BRepMesh_Edge& Other) const + inline Standard_Boolean operator ==(const BRepMesh_Edge& Other) const { return IsEqual(Other); } @@ -86,10 +86,13 @@ private: BRepMesh_DegreeOfFreedom myMovability; }; -inline Standard_Integer HashCode(const BRepMesh_Edge& theEdge, - const Standard_Integer theUpper) +//! Computes a hash code for the given edge, in the range [1, theUpperBound] +//! @param theEdge the edge which hash code is to be computed +//! @param theUpperBound the upper bound of the range a computing hash code must be within +//! @return a computed hash code, in the range [1, theUpperBound] +inline Standard_Integer HashCode (const BRepMesh_Edge& theEdge, const Standard_Integer theUpperBound) { - return theEdge.HashCode(theUpper); + return theEdge.HashCode (theUpperBound); } #endif diff --git a/src/BRepMesh/BRepMesh_EdgeDiscret.cxx b/src/BRepMesh/BRepMesh_EdgeDiscret.cxx new file mode 100644 index 0000000000..d9e575af43 --- /dev/null +++ b/src/BRepMesh/BRepMesh_EdgeDiscret.cxx @@ -0,0 +1,333 @@ +// Created on: 2016-04-19 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//======================================================================= +// Function: Constructor +// Purpose : +//======================================================================= +BRepMesh_EdgeDiscret::BRepMesh_EdgeDiscret () +{ +} + +//======================================================================= +// Function: Destructor +// Purpose : +//======================================================================= +BRepMesh_EdgeDiscret::~BRepMesh_EdgeDiscret () +{ +} + +//======================================================================= +// Function: CreateFreeEdgeTessellator +// Purpose : +//======================================================================= +Handle(IMeshTools_CurveTessellator) BRepMesh_EdgeDiscret::CreateEdgeTessellator( + const IMeshData::IEdgeHandle& theDEdge, + const IMeshTools_Parameters& theParameters) +{ + return new BRepMesh_CurveTessellator(theDEdge, theParameters); +} + +//======================================================================= +// Function: CreateEdgeTessellator +// Purpose : +//======================================================================= +Handle(IMeshTools_CurveTessellator) BRepMesh_EdgeDiscret::CreateEdgeTessellator( + const IMeshData::IEdgeHandle& theDEdge, + const TopAbs_Orientation theOrientation, + const IMeshData::IFaceHandle& theDFace, + const IMeshTools_Parameters& theParameters) +{ + return theDEdge->GetSameParam() ? + new BRepMesh_CurveTessellator(theDEdge, theParameters) : + new BRepMesh_CurveTessellator(theDEdge, theOrientation, theDFace, theParameters); +} + +//======================================================================= +// Function: CreateEdgeTessellationExtractor +// Purpose : +//======================================================================= +Handle(IMeshTools_CurveTessellator) BRepMesh_EdgeDiscret::CreateEdgeTessellationExtractor( + const IMeshData::IEdgeHandle& theDEdge, + const IMeshData::IFaceHandle& theDFace) +{ + return new BRepMesh_EdgeTessellationExtractor(theDEdge, theDFace); +} + +//======================================================================= +// Function: Perform +// Purpose : +//======================================================================= +Standard_Boolean BRepMesh_EdgeDiscret::performInternal ( + const Handle (IMeshData_Model)& theModel, + const IMeshTools_Parameters& theParameters) +{ + myModel = theModel; + myParameters = theParameters; + + if (myModel.IsNull()) + { + return Standard_False; + } + + OSD_Parallel::For (0, myModel->EdgesNb (), *this, !myParameters.InParallel); + + myModel.Nullify(); // Do not hold link to model. + return Standard_True; +} + +//======================================================================= +// Function: process +// Purpose : +//======================================================================= +void BRepMesh_EdgeDiscret::process (const Standard_Integer theEdgeIndex) const +{ + const IMeshData::IEdgeHandle& aDEdge = myModel->GetEdge (theEdgeIndex); + try + { + OCC_CATCH_SIGNALS + + BRepMesh_Deflection::ComputeDeflection (aDEdge, myModel->GetMaxSize (), myParameters); + + Handle (IMeshTools_CurveTessellator) aEdgeTessellator; + if (!aDEdge->IsFree ()) + { + // Iterate over pcurves and check deflection on corresponding face. + Standard_Real aMinDeflection = RealLast (); + Standard_Integer aMinPCurveIndex = -1; + for (Standard_Integer aPCurveIt = 0; aPCurveIt < aDEdge->PCurvesNb (); ++aPCurveIt) + { + const IMeshData::IPCurveHandle& aPCurve = aDEdge->GetPCurve (aPCurveIt); + const Standard_Real aTmpDeflection = checkExistingPolygonAndUpdateStatus(aDEdge, aPCurve); + if (aTmpDeflection < aMinDeflection) + { + // Identify pcurve with the smallest deflection in order to + // retrieve polygon that represents the most smooth discretization. + aMinDeflection = aTmpDeflection; + aMinPCurveIndex = aPCurveIt; + } + + BRepMesh_ShapeTool::CheckAndUpdateFlags (aDEdge, aPCurve); + } + + if (aMinPCurveIndex != -1) + { + aDEdge->SetDeflection (aMinDeflection); + const IMeshData::IFaceHandle aDFace = aDEdge->GetPCurve(aMinPCurveIndex)->GetFace(); + aEdgeTessellator = CreateEdgeTessellationExtractor(aDEdge, aDFace); + } + else + { + const IMeshData::IPCurveHandle& aPCurve = aDEdge->GetPCurve(0); + const IMeshData::IFaceHandle aDFace = aPCurve->GetFace(); + aEdgeTessellator = BRepMesh_EdgeDiscret::CreateEdgeTessellator( + aDEdge, aPCurve->GetOrientation(), aDFace, myParameters); + } + } + else + { + TopLoc_Location aLoc; + const Handle (Poly_Polygon3D)& aPoly3D = BRep_Tool::Polygon3D (aDEdge->GetEdge (), aLoc); + if (!aPoly3D.IsNull ()) + { + if (aPoly3D->HasParameters () && + aPoly3D->Deflection () < 1.1 * aDEdge->GetDeflection ()) + { + // Edge already has suitable 3d polygon. + aDEdge->SetStatus(IMeshData_Reused); + return; + } + else + { + aDEdge->SetStatus(IMeshData_Outdated); + } + } + + aEdgeTessellator = CreateEdgeTessellator(aDEdge, myParameters); + } + + Tessellate3d (aDEdge, aEdgeTessellator, Standard_True); + if (!aDEdge->IsFree()) + { + Tessellate2d(aDEdge, Standard_True); + } + } + catch (Standard_Failure const&) + { + aDEdge->SetStatus (IMeshData_Failure); + } +} + +//======================================================================= +// Function: checkExistingPolygonAndUpdateStatus +// Purpose : +//======================================================================= +Standard_Real BRepMesh_EdgeDiscret::checkExistingPolygonAndUpdateStatus( + const IMeshData::IEdgeHandle& theDEdge, + const IMeshData::IPCurveHandle& thePCurve) const +{ + const TopoDS_Edge& aEdge = theDEdge->GetEdge (); + const TopoDS_Face& aFace = thePCurve->GetFace ()->GetFace (); + + TopLoc_Location aLoc; + const Handle (Poly_Triangulation)& aFaceTriangulation = + BRep_Tool::Triangulation (aFace, aLoc); + + Standard_Real aDeflection = RealLast (); + if (aFaceTriangulation.IsNull()) + { + return aDeflection; + } + + const Handle (Poly_PolygonOnTriangulation)& aPolygon = + BRep_Tool::PolygonOnTriangulation (aEdge, aFaceTriangulation, aLoc); + + if (!aPolygon.IsNull ()) + { + Standard_Boolean isConsistent = aPolygon->HasParameters () && + aPolygon->Deflection () < 1.1 * theDEdge->GetDeflection (); + + if (!isConsistent) + { + // Nullify edge data and mark discrete pcurve to + // notify necessity to mesh the entire face. + theDEdge->SetStatus(IMeshData_Outdated); + } + else + { + aDeflection = aPolygon->Deflection(); + } + } + + return aDeflection; +} + +//======================================================================= +// Function: Tessellate3d +// Purpose : +//======================================================================= +void BRepMesh_EdgeDiscret::Tessellate3d( + const IMeshData::IEdgeHandle& theDEdge, + const Handle (IMeshTools_CurveTessellator)& theTessellator, + const Standard_Boolean theUpdateEnds) +{ + // Create 3d polygon. + const IMeshData::ICurveHandle& aCurve = theDEdge->GetCurve(); + + const TopoDS_Edge& aEdge = theDEdge->GetEdge(); + TopoDS_Vertex aFirstVertex, aLastVertex; + TopExp::Vertices(aEdge, aFirstVertex, aLastVertex); + + if(aFirstVertex.IsNull() || aLastVertex.IsNull()) + return; + + if (theUpdateEnds) + { + gp_Pnt aPoint; + Standard_Real aParam; + theTessellator->Value(1, aPoint, aParam); + aCurve->AddPoint(BRep_Tool::Pnt(aFirstVertex), aParam); + } + + if (!theDEdge->GetDegenerated()) + { + for (Standard_Integer i = 2; i < theTessellator->PointsNb(); ++i) + { + gp_Pnt aPoint; + Standard_Real aParam; + if (!theTessellator->Value(i, aPoint, aParam)) + continue; + + if (theUpdateEnds) + { + aCurve->AddPoint(aPoint, aParam); + } + else + { + aCurve->InsertPoint(aCurve->ParametersNb() - 1, aPoint, aParam); + } + } + } + + if (theUpdateEnds) + { + gp_Pnt aPoint; + Standard_Real aParam; + theTessellator->Value(theTessellator->PointsNb(), aPoint, aParam); + aCurve->AddPoint(BRep_Tool::Pnt(aLastVertex), aParam); + } +} + +//======================================================================= +// Function: Tessellate2d +// Purpose : +//======================================================================= +void BRepMesh_EdgeDiscret::Tessellate2d( + const IMeshData::IEdgeHandle& theDEdge, + const Standard_Boolean theUpdateEnds) +{ + const IMeshData::ICurveHandle& aCurve = theDEdge->GetCurve(); + for (Standard_Integer aPCurveIt = 0; aPCurveIt < theDEdge->PCurvesNb(); ++aPCurveIt) + { + const IMeshData::IPCurveHandle& aPCurve = theDEdge->GetPCurve(aPCurveIt); + const IMeshData::IFaceHandle aDFace = aPCurve->GetFace(); + IMeshData::ICurveArrayAdaptorHandle aCurveArray(new IMeshData::ICurveArrayAdaptor(aCurve)); + BRepMesh_EdgeParameterProvider aProvider( + theDEdge, aPCurve->GetOrientation(), aDFace, aCurveArray); + + const Handle(Adaptor2d_HCurve2d)& aGeomPCurve = aProvider.GetPCurve(); + + Standard_Integer aParamIdx, aParamNb; + if (theUpdateEnds) + { + aParamIdx = 0; + aParamNb = aCurve->ParametersNb(); + } + else + { + aParamIdx = 1; + aParamNb = aCurve->ParametersNb() - 1; + } + + for (; aParamIdx < aParamNb; ++aParamIdx) + { + const Standard_Real aParam = aProvider.Parameter(aParamIdx, aCurve->GetPoint(aParamIdx)); + + gp_Pnt2d aPoint2d; + aGeomPCurve->D0(aParam, aPoint2d); + if (theUpdateEnds) + { + aPCurve->AddPoint(aPoint2d, aParam); + } + else + { + aPCurve->InsertPoint(aPCurve->ParametersNb() - 1, aPoint2d, aParam); + } + } + } +} diff --git a/src/BRepMesh/BRepMesh_EdgeDiscret.hxx b/src/BRepMesh/BRepMesh_EdgeDiscret.hxx new file mode 100644 index 0000000000..82ac8e48d2 --- /dev/null +++ b/src/BRepMesh/BRepMesh_EdgeDiscret.hxx @@ -0,0 +1,98 @@ +// Created on: 2016-04-19 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _BRepMesh_EdgeDiscret_HeaderFile +#define _BRepMesh_EdgeDiscret_HeaderFile + +#include +#include +#include + +class IMeshTools_CurveTessellator; + +//! Class implements functionality of edge discret tool. +//! Performs check of the edges for existing Poly_PolygonOnTriangulation. +//! In case if it fits specified deflection, restores data structure using +//! it, else clears edges from outdated data. +class BRepMesh_EdgeDiscret : public IMeshTools_ModelAlgo +{ +public: + //! Constructor. + Standard_EXPORT BRepMesh_EdgeDiscret (); + + //! Destructor. + Standard_EXPORT virtual ~BRepMesh_EdgeDiscret (); + + //! Creates instance of free edge tessellator. + Standard_EXPORT static Handle(IMeshTools_CurveTessellator) CreateEdgeTessellator( + const IMeshData::IEdgeHandle& theDEdge, + const IMeshTools_Parameters& theParameters); + + //! Creates instance of edge tessellator. + Standard_EXPORT static Handle(IMeshTools_CurveTessellator) CreateEdgeTessellator( + const IMeshData::IEdgeHandle& theDEdge, + const TopAbs_Orientation theOrientation, + const IMeshData::IFaceHandle& theDFace, + const IMeshTools_Parameters& theParameters); + + //! Creates instance of tessellation extractor. + Standard_EXPORT static Handle(IMeshTools_CurveTessellator) CreateEdgeTessellationExtractor( + const IMeshData::IEdgeHandle& theDEdge, + const IMeshData::IFaceHandle& theDFace); + + //! Functor API to discretize the given edge. + inline void operator() (const Standard_Integer theEdgeIndex) const { + process (theEdgeIndex); + } + + //! Updates 3d discrete edge model using the given tessellation tool. + Standard_EXPORT static void Tessellate3d( + const IMeshData::IEdgeHandle& theDEdge, + const Handle(IMeshTools_CurveTessellator)& theTessellator, + const Standard_Boolean theUpdateEnds); + + //! Updates 2d discrete edge model using tessellation of 3D curve. + Standard_EXPORT static void Tessellate2d( + const IMeshData::IEdgeHandle& theDEdge, + const Standard_Boolean theUpdateEnds); + + DEFINE_STANDARD_RTTI_INLINE(BRepMesh_EdgeDiscret, IMeshTools_ModelAlgo) + +protected: + + //! Performs processing of edges of the given model. + Standard_EXPORT virtual Standard_Boolean performInternal ( + const Handle (IMeshData_Model)& theModel, + const IMeshTools_Parameters& theParameters) Standard_OVERRIDE; + +private: + + //! Checks existing discretization of the edge and updates data model. + void process (const Standard_Integer theEdgeIndex) const; + + //! Checks existing polygon on triangulation does it fit edge deflection or not. + //! @return deflection of polygon or RealLast () in case if edge has no polygon + //! or it was dropped. + Standard_Real checkExistingPolygonAndUpdateStatus( + const IMeshData::IEdgeHandle& theDEdge, + const IMeshData::IPCurveHandle& thePCurve) const; + +private: + + Handle (IMeshData_Model) myModel; + IMeshTools_Parameters myParameters; +}; + +#endif \ No newline at end of file diff --git a/src/BRepMesh/BRepMesh_EdgeParameterProvider.cxx b/src/BRepMesh/BRepMesh_EdgeParameterProvider.cxx deleted file mode 100644 index c5ae9c1036..0000000000 --- a/src/BRepMesh/BRepMesh_EdgeParameterProvider.cxx +++ /dev/null @@ -1,89 +0,0 @@ -// Created on: 2014-08-13 -// Created by: Oleg AGASHIN -// Copyright (c) 2011-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 -#include -#include -#include -#include -#include -#include -#include - -//======================================================================= -//function : Constructor -//purpose : -//======================================================================= -BRepMesh_EdgeParameterProvider::BRepMesh_EdgeParameterProvider( - const TopoDS_Edge& theEdge, - const TopoDS_Face& theFace, - const Handle(TColStd_HArray1OfReal)& theParameters) - : myParameters(theParameters), - myIsSameParam(BRep_Tool::SameParameter(theEdge)), - myScale(1.), - myCurveAdaptor(theEdge, theFace) -{ - if (myIsSameParam) - return; - - // Extract actual parametric values - Standard_Real aLastParam; - BRep_Tool::Range(theEdge, theFace, myFirstParam, aLastParam); - - myFoundParam = myCurParam = myFirstParam; - - // Extract parameters stored in polygon - myOldFirstParam = - myParameters->Value(myParameters->Lower()); - - const Standard_Real aOldLastParam = - myParameters->Value(myParameters->Upper()); - - // Calculate scale factor between actual and stored parameters - if ((myOldFirstParam != myFirstParam || aOldLastParam != aLastParam) && - myOldFirstParam != aOldLastParam) - { - myScale = (aLastParam - myFirstParam) / - (aOldLastParam - myOldFirstParam); - } - - myProjector.Initialize(myCurveAdaptor, myCurveAdaptor.FirstParameter(), - myCurveAdaptor.LastParameter(), Precision::PConfusion()); -} - -//======================================================================= -//function : Parameter -//purpose : -//======================================================================= -Standard_Real BRepMesh_EdgeParameterProvider::Parameter( - const Standard_Integer theIndex, - const gp_Pnt& thePoint3d) -{ - if (myIsSameParam) - return myParameters->Value(theIndex); - - // Use scaled - Standard_Real aPrevParam = myCurParam; - myCurParam = myFirstParam + myScale * - (myParameters->Value(theIndex) - myOldFirstParam); - - myFoundParam += (myCurParam - aPrevParam); - - myProjector.Perform(thePoint3d, myFoundParam); - if (myProjector.IsDone()) - myFoundParam = myProjector.Point().Parameter(); - - return myFoundParam; -} diff --git a/src/BRepMesh/BRepMesh_EdgeParameterProvider.hxx b/src/BRepMesh/BRepMesh_EdgeParameterProvider.hxx index 7f735f7fce..64610fef1e 100644 --- a/src/BRepMesh/BRepMesh_EdgeParameterProvider.hxx +++ b/src/BRepMesh/BRepMesh_EdgeParameterProvider.hxx @@ -16,44 +16,138 @@ #ifndef _BRepMesh_EdgeParameterProvider_HeaderFile #define _BRepMesh_EdgeParameterProvider_HeaderFile +#include +#include +#include +#include #include #include #include #include #include +#include +#include +#include +#include class gp_Pnt; class TopoDS_Edge; class TopoDS_Face; -#include //! Auxiliary class provides correct parameters //! on curve regarding SameParameter flag. -class BRepMesh_EdgeParameterProvider +template +class BRepMesh_EdgeParameterProvider : public Standard_Transient { public: DEFINE_STANDARD_ALLOC + //! Constructor. Initializes empty provider. + BRepMesh_EdgeParameterProvider() + { + } + //! Constructor. //! @param theEdge edge which parameters should be processed. //! @param theFace face the parametric values are defined for. //! @param theParameters parameters corresponded to discretization points. BRepMesh_EdgeParameterProvider( - const TopoDS_Edge& theEdge, - const TopoDS_Face& theFace, - const Handle(TColStd_HArray1OfReal)& theParameters); + const IMeshData::IEdgeHandle& theEdge, + const TopAbs_Orientation theOrientation, + const IMeshData::IFaceHandle& theFace, + const ParametersCollection& theParameters) + { + Init(theEdge, theOrientation, theFace, theParameters); + } + + //! Initialized provider by the given data. + void Init ( + const IMeshData::IEdgeHandle& theEdge, + const TopAbs_Orientation theOrientation, + const IMeshData::IFaceHandle& theFace, + const ParametersCollection& theParameters) + { + myParameters = theParameters; + myIsSameParam = theEdge->GetSameParam(); + myScale = 1.; + + // Extract actual parametric values + const TopoDS_Edge aEdge = TopoDS::Edge(theEdge->GetEdge().Oriented(theOrientation)); + + myCurveAdaptor.Initialize(aEdge, theFace->GetFace()); + if (myIsSameParam) + { + return; + } + + myFirstParam = myCurveAdaptor.FirstParameter(); + const Standard_Real aLastParam = myCurveAdaptor.LastParameter(); + + myFoundParam = myCurParam = myFirstParam; + + // Extract parameters stored in polygon + myOldFirstParam = myParameters->Value(myParameters->Lower()); + const Standard_Real aOldLastParam = myParameters->Value(myParameters->Upper()); + + // Calculate scale factor between actual and stored parameters + if ((myOldFirstParam != myFirstParam || aOldLastParam != aLastParam) && + myOldFirstParam != aOldLastParam) + { + myScale = (aLastParam - myFirstParam) / (aOldLastParam - myOldFirstParam); + } + + myProjector.Initialize(myCurveAdaptor, myCurveAdaptor.FirstParameter(), + myCurveAdaptor.LastParameter(),Precision::PConfusion()); + } //! Returns parameter according to SameParameter flag of the edge. //! If SameParameter is TRUE returns value from parameters w/o changes, //! elsewhere scales initial parameter and tries to determine resulting //! value using projection of the corresponded 3D point on PCurve. Standard_Real Parameter(const Standard_Integer theIndex, - const gp_Pnt& thePoint3d); + const gp_Pnt& thePoint3d) const + { + if (myIsSameParam) + { + return myParameters->Value(theIndex); + } + + // Use scaled + const Standard_Real aParam = myParameters->Value(theIndex); + + const Standard_Real aPrevParam = myCurParam; + myCurParam = myFirstParam + myScale * (aParam - myOldFirstParam); + + const Standard_Real aPrevFoundParam = myFoundParam; + myFoundParam += (myCurParam - aPrevParam); + + myProjector.Perform(thePoint3d, myFoundParam); + if (myProjector.IsDone()) + { + const Standard_Real aFoundParam = myProjector.Point().Parameter(); + if ((aPrevFoundParam < myFoundParam && aPrevFoundParam < aFoundParam) || + (aPrevFoundParam > myFoundParam && aPrevFoundParam > aFoundParam)) + { + // Rude protection against case when amplified parameter goes before + // previous one due to period or other reason occurred in projector. + // Using parameter returned by projector as is can produce self-intersections. + myFoundParam = aFoundParam; + } + } + + return myFoundParam; + } + + //! Returns pcurve used to compute parameters. + const Handle(Adaptor2d_HCurve2d)& GetPCurve() const + { + return myCurveAdaptor.CurveOnSurface().GetCurve(); + } private: - Handle(TColStd_HArray1OfReal) myParameters; + ParametersCollection myParameters; Standard_Boolean myIsSameParam; Standard_Real myFirstParam; @@ -61,11 +155,12 @@ private: Standard_Real myOldFirstParam; Standard_Real myScale; - Standard_Real myCurParam; - Standard_Real myFoundParam; + mutable Standard_Real myCurParam; + mutable Standard_Real myFoundParam; BRepAdaptor_Curve myCurveAdaptor; - Extrema_LocateExtPC myProjector; + + mutable Extrema_LocateExtPC myProjector; }; #endif diff --git a/src/BRepMesh/BRepMesh_EdgeTessellationExtractor.cxx b/src/BRepMesh/BRepMesh_EdgeTessellationExtractor.cxx index 5fbb1bba33..5e2748042d 100644 --- a/src/BRepMesh/BRepMesh_EdgeTessellationExtractor.cxx +++ b/src/BRepMesh/BRepMesh_EdgeTessellationExtractor.cxx @@ -1,6 +1,6 @@ -// Created on: 2014-08-13 +// Created on: 2016-04-19 +// Copyright (c) 2016 OPEN CASCADE SAS // Created by: Oleg AGASHIN -// Copyright (c) 2011-2014 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. // @@ -14,48 +14,60 @@ // commercial license or contractual agreement. #include -#include -#include -#include #include +#include +#include +#include +#include +//======================================================================= +//function : Constructor +//purpose : +//======================================================================= +BRepMesh_EdgeTessellationExtractor::BRepMesh_EdgeTessellationExtractor ( + const IMeshData::IEdgeHandle& theEdge, + const IMeshData::IFaceHandle& theFace) +{ + Handle (Poly_Triangulation) aTriangulation = + BRep_Tool::Triangulation (theFace->GetFace(), myLoc); + + Handle (Poly_PolygonOnTriangulation) aPolygon = + BRep_Tool::PolygonOnTriangulation (theEdge->GetEdge(), aTriangulation, myLoc); -IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_EdgeTessellationExtractor,BRepMesh_IEdgeTool) + myNodes = &aTriangulation->Nodes (); + myIndices = &aPolygon->Nodes (); + myProvider.Init (theEdge, TopAbs_FORWARD, theFace, aPolygon->Parameters ()); +} //======================================================================= //function : Constructor //purpose : //======================================================================= -BRepMesh_EdgeTessellationExtractor::BRepMesh_EdgeTessellationExtractor( - const TopoDS_Edge& theEdge, - const Handle(Geom2dAdaptor_HCurve)& thePCurve, - const TopoDS_Face& theFace, - const Handle(Poly_Triangulation)& theTriangulation, - const Handle(Poly_PolygonOnTriangulation)& thePolygon, - const TopLoc_Location& theLocation) - : myProvider(theEdge, theFace, thePolygon->Parameters()), - myPCurve(thePCurve), - myNodes(theTriangulation->Nodes()), - myIndices(thePolygon->Nodes()), - myLoc(theLocation) +BRepMesh_EdgeTessellationExtractor::~BRepMesh_EdgeTessellationExtractor () { } +//======================================================================= +//function : NbPoints +//purpose : +//======================================================================= +Standard_Integer BRepMesh_EdgeTessellationExtractor::PointsNb () const +{ + return myIndices->Size (); +} + //======================================================================= //function : Value //purpose : //======================================================================= -Standard_Boolean BRepMesh_EdgeTessellationExtractor::Value( +Standard_Boolean BRepMesh_EdgeTessellationExtractor::Value ( const Standard_Integer theIndex, - Standard_Real& theParameter, gp_Pnt& thePoint, - gp_Pnt2d& theUV) + Standard_Real& theParameter) const { - const gp_Pnt& theRefPnt = myNodes(myIndices(theIndex)); - thePoint = BRepMesh_ShapeTool::UseLocation(theRefPnt, myLoc); - - theParameter = myProvider.Parameter(theIndex, thePoint); - theUV = myPCurve->Value(theParameter); + const gp_Pnt& theRefPnt = (*myNodes) ((*myIndices) (theIndex)); + thePoint = BRepMesh_ShapeTool::UseLocation (theRefPnt, myLoc); + theParameter = myProvider.Parameter (theIndex, thePoint); return Standard_True; } diff --git a/src/BRepMesh/BRepMesh_EdgeTessellationExtractor.hxx b/src/BRepMesh/BRepMesh_EdgeTessellationExtractor.hxx index d7f20a6146..8ce07f590f 100644 --- a/src/BRepMesh/BRepMesh_EdgeTessellationExtractor.hxx +++ b/src/BRepMesh/BRepMesh_EdgeTessellationExtractor.hxx @@ -1,6 +1,6 @@ -// Created on: 2014-08-13 +// Created on: 2016-04-19 +// Copyright (c) 2016 OPEN CASCADE SAS // Created by: Oleg AGASHIN -// Copyright (c) 2011-2014 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. // @@ -16,72 +16,48 @@ #ifndef _BRepMesh_EdgeTessellationExtractor_HeaderFile #define _BRepMesh_EdgeTessellationExtractor_HeaderFile -#include -#include -#include +#include +#include #include -#include #include #include - -class Poly_Triangulation; -class Poly_PolygonOnTriangulation; -class TopoDS_Edge; -class TopoDS_Face; -class Geom2dAdaptor_HCurve; +#include //! Auxiliary class implements functionality retrieving tessellated //! representation of an edge stored in polygon. -class BRepMesh_EdgeTessellationExtractor : public BRepMesh_IEdgeTool +class BRepMesh_EdgeTessellationExtractor : public IMeshTools_CurveTessellator { public: //! Constructor. - //! Initializes extractor. - BRepMesh_EdgeTessellationExtractor( - const TopoDS_Edge& theEdge, - const Handle(Geom2dAdaptor_HCurve)& thePCurve, - const TopoDS_Face& theFace, - const Handle(Poly_Triangulation)& theTriangulation, - const Handle(Poly_PolygonOnTriangulation)& thePolygon, - const TopLoc_Location& theLocation); + Standard_EXPORT BRepMesh_EdgeTessellationExtractor ( + const IMeshData::IEdgeHandle& theEdge, + const IMeshData::IFaceHandle& theFace); + + //! Destructor. + Standard_EXPORT virtual ~BRepMesh_EdgeTessellationExtractor (); - //! Returns number of dicretization points. - virtual Standard_Integer NbPoints() const Standard_OVERRIDE - { - return myIndices.Length(); - } + //! Returns number of tessellation points. + Standard_EXPORT virtual Standard_Integer PointsNb () const Standard_OVERRIDE; //! Returns parameters of solution with the given index. //! @param theIndex index of tessellation point. //! @param theParameter parameters on PCurve corresponded to the solution. //! @param thePoint tessellation point. - //! @param theUV coordinates of tessellation point in parametric space of face. //! @return True in case of valid result, false elewhere. - virtual Standard_Boolean Value( + Standard_EXPORT virtual Standard_Boolean Value ( const Standard_Integer theIndex, - Standard_Real& theParameter, gp_Pnt& thePoint, - gp_Pnt2d& theUV) Standard_OVERRIDE; + Standard_Real& theParameter) const Standard_OVERRIDE; - DEFINE_STANDARD_RTTIEXT(BRepMesh_EdgeTessellationExtractor,BRepMesh_IEdgeTool) + DEFINE_STANDARD_RTTI_INLINE(BRepMesh_EdgeTessellationExtractor, IMeshTools_CurveTessellator) private: - //! Assignment operator. - void operator =(const BRepMesh_EdgeTessellationExtractor& /*theOther*/) - { - } - -private: - - BRepMesh_EdgeParameterProvider myProvider; - Handle(Geom2dAdaptor_HCurve) myPCurve; - const TColgp_Array1OfPnt& myNodes; - const TColStd_Array1OfInteger& myIndices; - const TopLoc_Location myLoc; + BRepMesh_EdgeParameterProvider myProvider; + const TColgp_Array1OfPnt* myNodes; + const TColStd_Array1OfInteger* myIndices; + TopLoc_Location myLoc; }; -DEFINE_STANDARD_HANDLE(BRepMesh_EdgeTessellationExtractor, BRepMesh_IEdgeTool) - -#endif +#endif \ No newline at end of file diff --git a/src/BRepMesh/BRepMesh_EdgeTessellator.cxx b/src/BRepMesh/BRepMesh_EdgeTessellator.cxx deleted file mode 100644 index 0daa3509d3..0000000000 --- a/src/BRepMesh/BRepMesh_EdgeTessellator.cxx +++ /dev/null @@ -1,264 +0,0 @@ -// Created on: 2014-08-13 -// Created by: Oleg AGASHIN -// Copyright (c) 2011-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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_EdgeTessellator,BRepMesh_IEdgeTool) - -//======================================================================= -//function : Constructor -//purpose : -//======================================================================= -BRepMesh_EdgeTessellator::BRepMesh_EdgeTessellator( - const TopoDS_Edge& theEdge, - const Handle(BRepMesh_FaceAttribute)& theFaceAttribute, - const TopTools_IndexedDataMapOfShapeListOfShape& theMapOfSharedFaces, - const Standard_Real theLinDeflection, - const Standard_Real theAngDeflection, - const Standard_Real theMinSize) - : mySurface(theFaceAttribute->Surface()) -{ - Standard_Real aPreciseAngDef = 0.5 * theAngDeflection; - Standard_Real aPreciseLinDef = 0.5 * theLinDeflection; - if (theEdge.Orientation() == TopAbs_INTERNAL) - aPreciseLinDef *= 0.5; - - mySquareEdgeDef = aPreciseLinDef * aPreciseLinDef; - mySquareMinSize = Max(mySquareEdgeDef, theMinSize * theMinSize); - myEdgeSqTol = BRep_Tool::Tolerance (theEdge); - myEdgeSqTol *= myEdgeSqTol; - - Standard_Boolean isSameParam = BRep_Tool::SameParameter(theEdge); - if (isSameParam) - myCOnS.Initialize(theEdge); - else - myCOnS.Initialize(theEdge, theFaceAttribute->Face()); - - const GeomAbs_CurveType aCurveType = myCOnS.GetType(); - Standard_Integer aMinPntNb = (aCurveType == GeomAbs_Circle) ? 4 : 2; //OCC287 - - // Get 2d curve and init geom tool - Standard_Real aFirstParam, aLastParam; - Handle(Geom2d_Curve) aCurve2d = - BRep_Tool::CurveOnSurface(theEdge, theFaceAttribute->Face(), aFirstParam, aLastParam); - myCurve2d.Load(aCurve2d, aFirstParam, aLastParam); - myTool = new BRepMesh_GeomTool(myCOnS, aFirstParam, aLastParam, - aPreciseLinDef, aPreciseAngDef, aMinPntNb, theMinSize); - - if (aCurveType == GeomAbs_BSplineCurve) - { - // bug24220 - const Standard_Integer aNbInt = myCOnS.NbIntervals(GeomAbs_C1); - if ( aNbInt > 1 ) - { - TColStd_Array1OfReal anIntervals( 1, aNbInt + 1 ); - myCOnS.Intervals(anIntervals, GeomAbs_C1); - for (Standard_Integer aIntIt = 1; aIntIt <= aNbInt; ++aIntIt) - { - const Standard_Real& aStartInt = anIntervals.Value( aIntIt ); - const Standard_Real& anEndInt = anIntervals.Value( aIntIt + 1 ); - - BRepMesh_GeomTool aDetalizator(myCOnS, aStartInt, anEndInt, - aPreciseLinDef, aPreciseAngDef, aMinPntNb, theMinSize); - - Standard_Integer aNbAddNodes = aDetalizator.NbPoints(); - for ( Standard_Integer aNodeIt = 1; aNodeIt <= aNbAddNodes; ++aNodeIt ) - { - Standard_Real aParam; - gp_Pnt aPoint3d; - gp_Pnt2d aPoint2d; - aDetalizator.Value( aNodeIt, aParam, aPoint3d); - myCurve2d.D0(aParam, aPoint2d); - - myTool->AddPoint( aPoint3d, aParam, Standard_False ); - } - } - } - } - - // PTv, chl/922/G9, Take into account internal vertices - // it is necessary for internal edges, which do not split other edges, by their vertex - TopExp_Explorer aVertexIt(theEdge, TopAbs_VERTEX); - for (; aVertexIt.More(); aVertexIt.Next()) - { - const TopoDS_Vertex& aVertex = TopoDS::Vertex(aVertexIt.Current()); - if (aVertex.Orientation() != TopAbs_INTERNAL) - continue; - - myTool->AddPoint(BRep_Tool::Pnt(aVertex), - BRep_Tool::Parameter(aVertex, theEdge), Standard_True); - } - - Standard_Integer aNodesNb = myTool->NbPoints(); - //Check deflection in 2d space for improvement of edge tesselation. - if( isSameParam && aNodesNb > 1) - { - const TopTools_ListOfShape& aSharedFaces = theMapOfSharedFaces.FindFromKey(theEdge); - TopTools_ListIteratorOfListOfShape aFaceIt(aSharedFaces); - for (; aFaceIt.More(); aFaceIt.Next()) - { - const TopoDS_Face& aFace = TopoDS::Face(aFaceIt.Value()); - BRepAdaptor_Surface aSurf(aFace, Standard_False); - - if (aSurf.GetType() == GeomAbs_Plane) - continue; - - Standard_Real aF, aL; - aCurve2d = BRep_Tool::CurveOnSurface(theEdge, aFace, aF, aL); - if ( Abs(aF - aFirstParam) > Precision::PConfusion() || - Abs(aL - aLastParam ) > Precision::PConfusion() ) - { - continue; - } - Geom2dAdaptor_Curve aGACurve(aCurve2d, aF, aL); - - aNodesNb = myTool->NbPoints(); - TColStd_Array1OfReal aParamArray(1, aNodesNb); - for (Standard_Integer i = 1; i <= aNodesNb; ++i) - { - gp_Pnt aTmpPnt; - Standard_Real aParam; - myTool->Value(i, aParam, aTmpPnt); - aParamArray.SetValue(i, aParam); - } - - for (Standard_Integer i = 1; i < aNodesNb; ++i) - splitSegment(aSurf, aGACurve, aParamArray(i), aParamArray(i + 1), 1); - } - } - - const Standard_Real aTol = Precision::Confusion(); - const Standard_Real aDu = mySurface->UResolution (aTol); - const Standard_Real aDv = mySurface->VResolution (aTol); - - myFaceRangeU[0] = mySurface->FirstUParameter() - aDu; - myFaceRangeU[1] = mySurface->LastUParameter() + aDu; - - myFaceRangeV[0] = mySurface->FirstVParameter() - aDv; - myFaceRangeV[1] = mySurface->LastVParameter() + aDv; -} - -//======================================================================= -//function : Value -//purpose : -//======================================================================= -Standard_Boolean BRepMesh_EdgeTessellator::Value( - const Standard_Integer theIndex, - Standard_Real& theParameter, - gp_Pnt& thePoint, - gp_Pnt2d& theUV) -{ - myTool->Value(theIndex, theParameter, thePoint); - myCurve2d.D0(theParameter, theUV); - - // If point coordinates are out of surface range, - // it is necessary to re-project point. - if (mySurface->GetType() != GeomAbs_BSplineSurface && - mySurface->GetType() != GeomAbs_BezierSurface && - mySurface->GetType() != GeomAbs_OtherSurface) - { - return Standard_True; - } - - // Let skip periodic case. - if (mySurface->IsUPeriodic() || mySurface->IsVPeriodic()) - return Standard_True; - - // Point lies within the surface range - nothing to do. - if (theUV.X() > myFaceRangeU[0] && theUV.X() < myFaceRangeU[1] && - theUV.Y() > myFaceRangeV[0] && theUV.Y() < myFaceRangeV[1]) - { - return Standard_True; - } - - gp_Pnt aPntOnSurf; - mySurface->D0 (theUV.X (), theUV.Y (), aPntOnSurf); - - return (thePoint.SquareDistance (aPntOnSurf) < myEdgeSqTol); -} - -//======================================================================= -//function : splitSegment -//purpose : -//======================================================================= -void BRepMesh_EdgeTessellator::splitSegment( - const Adaptor3d_Surface& theSurf, - const Geom2dAdaptor_Curve& theCurve2d, - const Standard_Real theFirst, - const Standard_Real theLast, - const Standard_Integer theNbIter) -{ - // limit iteration depth - if(theNbIter > 10) - return; - - gp_Pnt2d uvf, uvl, uvm; - gp_Pnt P3dF, P3dL, midP3d, midP3dFromSurf; - Standard_Real midpar; - - if(Abs(theLast - theFirst) < 2 * Precision::PConfusion()) - return; - - theCurve2d.D0(theFirst, uvf); - theCurve2d.D0(theLast, uvl); - - P3dF = theSurf.Value(uvf.X(), uvf.Y()); - P3dL = theSurf.Value(uvl.X(), uvl.Y()); - - if(P3dF.SquareDistance(P3dL) < mySquareMinSize) - return; - - uvm = gp_Pnt2d((uvf.XY() + uvl.XY())*0.5); - midP3dFromSurf = theSurf.Value(uvm.X(), uvm.Y()); - - gp_XYZ Vec1 = midP3dFromSurf.XYZ() - P3dF.XYZ(); - if(Vec1.SquareModulus() < mySquareMinSize) - return; - - gp_XYZ aVec = P3dL.XYZ() - P3dF.XYZ(); - aVec.Normalize(); - - Standard_Real aModulus = Vec1.Dot(aVec); - gp_XYZ aProj = aVec * aModulus; - gp_XYZ aDist = Vec1 - aProj; - - if(aDist.SquareModulus() < mySquareEdgeDef) - return; - - midpar = (theFirst + theLast) * 0.5; - myCOnS.D0(midpar, midP3d); - myTool->AddPoint(midP3d, midpar, Standard_False); - - splitSegment(theSurf, theCurve2d, theFirst, midpar, theNbIter + 1); - splitSegment(theSurf, theCurve2d, midpar, theLast, theNbIter + 1); -} diff --git a/src/BRepMesh/BRepMesh_EdgeTessellator.hxx b/src/BRepMesh/BRepMesh_EdgeTessellator.hxx deleted file mode 100644 index 5af1a9e432..0000000000 --- a/src/BRepMesh/BRepMesh_EdgeTessellator.hxx +++ /dev/null @@ -1,93 +0,0 @@ -// Created on: 2014-08-13 -// Created by: Oleg AGASHIN -// Copyright (c) 2011-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. - -#ifndef _BRepMesh_EdgeTessellator_HeaderFile -#define _BRepMesh_EdgeTessellator_HeaderFile - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class Adaptor3d_Surface; -class TopoDS_Edge; -class BRepAdaptor_HSurface; - -//! Auxiliary class implements functionality producing tessellated -//! representation of an edge based on edge geometry. -class BRepMesh_EdgeTessellator : public BRepMesh_IEdgeTool -{ -public: - - //! Constructor. - //! Automatically performs tessellation of the edge according to the - //! given parameters. - BRepMesh_EdgeTessellator( - const TopoDS_Edge& theEdge, - const Handle(BRepMesh_FaceAttribute)& theFaceAttribute, - const TopTools_IndexedDataMapOfShapeListOfShape& theMapOfSharedFaces, - const Standard_Real theLinDeflection, - const Standard_Real theAngDeflection, - const Standard_Real theMinSize); - - //! Returns number of dicretization points. - virtual Standard_Integer NbPoints() const Standard_OVERRIDE - { - return myTool->NbPoints(); - } - - //! Returns parameters of solution with the given index. - //! @param theIndex index of tessellation point. - //! @param theParameter parameters on PCurve corresponded to the solution. - //! @param thePoint tessellation point. - //! @param theUV coordinates of tessellation point in parametric space of face. - //! @return True in case of valid result, false elewhere. - virtual Standard_Boolean Value( - const Standard_Integer theIndex, - Standard_Real& theParameter, - gp_Pnt& thePoint, - gp_Pnt2d& theUV) Standard_OVERRIDE; - - DEFINE_STANDARD_RTTIEXT(BRepMesh_EdgeTessellator,BRepMesh_IEdgeTool) - -private: - - //! - void splitSegment(const Adaptor3d_Surface& theSurf, - const Geom2dAdaptor_Curve& theCurve2d, - const Standard_Real theFirst, - const Standard_Real theLast, - const Standard_Integer theNbIter); - -private: - NCollection_Handle myTool; - Handle(BRepAdaptor_HSurface) mySurface; - BRepAdaptor_Curve myCOnS; - Geom2dAdaptor_Curve myCurve2d; - Standard_Real mySquareEdgeDef; - Standard_Real mySquareMinSize; - Standard_Real myEdgeSqTol; - Standard_Real myFaceRangeU[2]; - Standard_Real myFaceRangeV[2]; -}; - -DEFINE_STANDARD_HANDLE(BRepMesh_EdgeTessellator, BRepMesh_IEdgeTool) - -#endif diff --git a/src/BRepMesh/BRepMesh_FaceAttribute.cxx b/src/BRepMesh/BRepMesh_FaceAttribute.cxx deleted file mode 100644 index 119a746785..0000000000 --- a/src/BRepMesh/BRepMesh_FaceAttribute.cxx +++ /dev/null @@ -1,257 +0,0 @@ -// Created by: Ekaterina SMIRNOVA -// Copyright (c) 2008-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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_FaceAttribute,Standard_Transient) - -//======================================================================= -//function : Constructor -//purpose : -//======================================================================= -BRepMesh_FaceAttribute::BRepMesh_FaceAttribute() - : myDefFace (0.), - myUMin (0.), - myUMax (0.), - myVMin (0.), - myVMax (0.), - myDeltaX (1.), - myDeltaY (1.), - myMinStep (-1.), - myStatus (BRepMesh_NoError), - myAdaptiveMin (Standard_False) -{ - init(); -} - -//======================================================================= -//function : Constructor -//purpose : -//======================================================================= -BRepMesh_FaceAttribute::BRepMesh_FaceAttribute( - const BRepMesh::HDMapOfVertexInteger& theBoundaryVertices, - const BRepMesh::HDMapOfIntegerPnt& theBoundaryPoints) - : myDefFace (0.), - myUMin (0.), - myUMax (0.), - myVMin (0.), - myVMax (0.), - myDeltaX (1.), - myDeltaY (1.), - myMinStep (-1.), - myStatus (BRepMesh_NoError), - myAdaptiveMin (Standard_False), - myBoundaryVertices(theBoundaryVertices), - myBoundaryPoints (theBoundaryPoints) -{ -} - -//======================================================================= -//function : Constructor -//purpose : -//======================================================================= -BRepMesh_FaceAttribute::BRepMesh_FaceAttribute( - const TopoDS_Face& theFace, - const BRepMesh::HDMapOfVertexInteger& theBoundaryVertices, - const BRepMesh::HDMapOfIntegerPnt& theBoundaryPoints, - const Standard_Boolean theAdaptiveMin) - : myDefFace (0.), - myUMin (0.), - myUMax (0.), - myVMin (0.), - myVMax (0.), - myDeltaX (1.), - myDeltaY (1.), - myMinStep (-1.), - myStatus (BRepMesh_NoError), - myAdaptiveMin (theAdaptiveMin), - myBoundaryVertices(theBoundaryVertices), - myBoundaryPoints (theBoundaryPoints), - myFace (theFace) -{ - init(); -} - -//======================================================================= -//function : Destructor -//purpose : -//======================================================================= -BRepMesh_FaceAttribute::~BRepMesh_FaceAttribute() -{ -} - -//======================================================================= -//function : SetFace -//purpose : -//======================================================================= -void BRepMesh_FaceAttribute::SetFace ( - const TopoDS_Face& theFace, - const Standard_Boolean theAdaptiveMin) -{ - myFace = theFace; - myAdaptiveMin = theAdaptiveMin; - - init (); -} - -//======================================================================= -//function : init -//purpose : -//======================================================================= -void BRepMesh_FaceAttribute::init() -{ - myVertexEdgeMap = new BRepMesh::IMapOfInteger; - myInternalEdges = new BRepMesh::DMapOfShapePairOfPolygon; - myLocation2D = new BRepMesh::DMapOfIntegerListOfXY; - myClassifier = new BRepMesh_Classifier; - - if (myFace.IsNull()) - return; - - BRepTools::Update(myFace); - myFace.Orientation(TopAbs_FORWARD); - BRepTools::UVBounds(myFace, myUMin, myUMax, myVMin, myVMax); - - if (myAdaptiveMin) - { - // compute minimal UV distance - // between vertices - - myMinStep = RealLast(); - for (TopoDS_Iterator aFaceIt(myFace); aFaceIt.More(); aFaceIt.Next()) - { - for (TopoDS_Iterator aWireIt(aFaceIt.Value()); aWireIt.More(); aWireIt.Next()) - { - const TopoDS_Edge& anEdge = TopoDS::Edge(aWireIt.Value()); - if (anEdge.IsNull() || BRep_Tool::IsClosed(anEdge)) - continue; - - // Get end points on 2d curve - gp_Pnt2d aFirst2d, aLast2d; - BRep_Tool::UVPoints(anEdge, myFace, aFirst2d, aLast2d); - Standard_Real aDist =aFirst2d.Distance(aLast2d); - if (aDist < myMinStep) - myMinStep = aDist; - } - } - } - - BRepAdaptor_Surface aSurfAdaptor(myFace, Standard_False); - mySurface = new BRepAdaptor_HSurface(aSurfAdaptor); -} - -//======================================================================= -//function : Clear -//purpose : -//======================================================================= -void BRepMesh_FaceAttribute::Clear() -{ - myStructure.Nullify(); - myLocation2D->Clear(); - myInternalEdges->Clear(); - myVertexEdgeMap->Clear(); -} - -//======================================================================= -//function : computeParametricTolerance -//purpose : -//======================================================================= -Standard_Real BRepMesh_FaceAttribute::computeParametricTolerance( - const Standard_Real theFirstParam, - const Standard_Real theLastParam) const -{ - const Standard_Real aDeflectionUV = 1.e-05; - Standard_Real aPreci = (theLastParam - theFirstParam) * aDeflectionUV; - if(myAdaptiveMin && myMinStep < aPreci) - aPreci = myMinStep; - - return Max(Precision::PConfusion(), aPreci); -} - -//======================================================================= -//function : getVertexIndex -//purpose : -//======================================================================= -Standard_Boolean BRepMesh_FaceAttribute::getVertexIndex( - const TopoDS_Vertex& theVertex, - Standard_Integer& theVertexIndex) const -{ - if (!myBoundaryVertices.IsNull() && myBoundaryVertices->IsBound(theVertex)) - theVertexIndex = myBoundaryVertices->Find(theVertex); - else if (!mySurfaceVertices.IsNull() && mySurfaceVertices->IsBound(theVertex)) - theVertexIndex = mySurfaceVertices->Find(theVertex); - else - return Standard_False; - - return Standard_True; -} - -//======================================================================= -//function : AddNode -//purpose : -//======================================================================= -void BRepMesh_FaceAttribute::AddNode( - const Standard_Integer theIndex, - const gp_XY& theUV, - const BRepMesh_DegreeOfFreedom theMovability, - Standard_Integer& theNodeIndex, - Standard_Integer& theNodeOnEdgeIndex) -{ - BRepMesh_Vertex aNode(theUV, theIndex, theMovability); - theNodeIndex = myStructure->AddNode(aNode); - theNodeOnEdgeIndex = myVertexEdgeMap->FindIndex(theNodeIndex); - if (theNodeOnEdgeIndex == 0) - theNodeOnEdgeIndex = myVertexEdgeMap->Add(theNodeIndex); -} - -//======================================================================= -//function : Scale -//purpose : -//======================================================================= -gp_XY BRepMesh_FaceAttribute::Scale(const gp_XY& thePoint2d, - const Standard_Boolean isToFaceBasis) -{ - return isToFaceBasis ? - gp_XY((thePoint2d.X() - myUMin) / myDeltaX, (thePoint2d.Y() - myVMin) / myDeltaY) : - gp_XY(thePoint2d.X() * myDeltaX + myUMin, thePoint2d.Y() * myDeltaY + myVMin); -} - -//======================================================================= -//function : ToleranceU -//purpose : -//======================================================================= -Standard_Real BRepMesh_FaceAttribute::ToleranceU() const -{ - return computeParametricTolerance(myUMin, myUMax); -} - -//======================================================================= -//function : ToleranceV -//purpose : -//======================================================================= -Standard_Real BRepMesh_FaceAttribute::ToleranceV() const -{ - return computeParametricTolerance(myVMin, myVMax); -} diff --git a/src/BRepMesh/BRepMesh_FaceAttribute.hxx b/src/BRepMesh/BRepMesh_FaceAttribute.hxx deleted file mode 100644 index 0460d5308b..0000000000 --- a/src/BRepMesh/BRepMesh_FaceAttribute.hxx +++ /dev/null @@ -1,405 +0,0 @@ -// Copyright (c) 2013 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 _BRepMesh_FaceAttribute_HeaderFile -#define _BRepMesh_FaceAttribute_HeaderFile - -#include -#include -#include - -#include -#include -#include - -class BRepAdaptor_HSurface; - -//! Auxiliary class for FastDiscret and FastDiscretFace classes. -class BRepMesh_FaceAttribute : public Standard_Transient -{ -public: - - //! Constructor. Initializes empty attribute. - //! @param theBoundaryVertices shared map of shape vertices. - //! @param theBoundaryPoints shared discretization points of shape boundaries. - Standard_EXPORT BRepMesh_FaceAttribute( - const BRepMesh::HDMapOfVertexInteger& theBoundaryVertices, - const BRepMesh::HDMapOfIntegerPnt& theBoundaryPoints); - - //! Constructor. - //! @param theFace face the attribute is created for. - //! Used for default initialization. Attribute keeps reference - //! to the source face with forward orientation. - //! @param theBoundaryVertices shared map of shape vertices. - //! @param theBoundaryPoints shared discretization points of shape boundaries. - //! @param theAdaptiveMin switches on adaptive computation of minimal parametric - //! tolerance (if true). - Standard_EXPORT BRepMesh_FaceAttribute( - const TopoDS_Face& theFace, - const BRepMesh::HDMapOfVertexInteger& theBoundaryVertices, - const BRepMesh::HDMapOfIntegerPnt& theBoundaryPoints, - const Standard_Boolean theAdaptiveMin); - - //! Destructor. - Standard_EXPORT virtual ~BRepMesh_FaceAttribute(); - -public: //! @name main geometrical properties. - - //! Returns face's surface. - inline const Handle(BRepAdaptor_HSurface)& Surface() const - { - return mySurface; - } - - //! Returns True in case if this attribute has already been intialized. - inline Standard_Boolean IsInitialized () const - { - return !myFace.IsNull (); - } - - //! Initializes this attribute by the given face. - Standard_EXPORT void SetFace ( - const TopoDS_Face& theFace, - const Standard_Boolean theAdaptiveMin); - - //! Returns forward oriented face to be used for calculations. - inline const TopoDS_Face& Face() const - { - return myFace; - } - - //! Sets boundary vertices map. - inline void SetBoundaryVertices(const BRepMesh::HDMapOfVertexInteger& theVertices) - { - myBoundaryVertices = theVertices; - } - - //! Sets boundary points map. - inline void SetBoundaryPoints(const BRepMesh::HDMapOfIntegerPnt& theBoundaryPoints) - { - myBoundaryPoints = theBoundaryPoints; - } - - //! Returns U tolerance of face calculated regarding its parameters. - Standard_EXPORT Standard_Real ToleranceU() const; - - //! Returns V tolerance of face calculated regarding its parameters. - Standard_EXPORT Standard_Real ToleranceV() const; - - //! Gives face deflection parameter. - inline Standard_Real GetDefFace() const - { - return myDefFace; - } - - //! Sets face deflection. - inline void SetDefFace(const Standard_Real theDefFace) - { - myDefFace = theDefFace; - } - - //! Gives minimal value in U domain. - inline Standard_Real GetUMin() const - { - return myUMin; - } - - //! Sets minimal value in U domain. - inline void SetUMin(const Standard_Real theUMin) - { - myUMin = theUMin; - } - - //! Gives minimal value in V domain. - inline Standard_Real GetVMin() const - { - return myVMin; - } - - //! Sets minimal value in V domain. - inline void SetVMin(const Standard_Real theVMin) - { - myVMin = theVMin; - } - - //! Gives maximal value in U domain. - inline Standard_Real GetUMax() const - { - return myUMax; - } - - //! Sets maximal value in U domain. - inline void SetUMax(const Standard_Real theUMax) - { - myUMax = theUMax; - } - - //! Gives maximal value in V domain. - inline Standard_Real GetVMax() const - { - return myVMax; - } - - //! Sets maximal value in V domain. - inline void SetVMax(const Standard_Real theVMax) - { - myVMax = theVMax; - } - - //! Gives value of step in U domain. - inline Standard_Real GetDeltaX() const - { - return myDeltaX; - } - - //! Sets value of step in U domain. - inline void SetDeltaX(const Standard_Real theDeltaX) - { - myDeltaX = theDeltaX; - } - - //! Gives value of step in V domain. - inline Standard_Real GetDeltaY() const - { - return myDeltaY; - } - - //! Sets value of step in V domain. - inline void SetDeltaY(const Standard_Real theDeltaY) - { - myDeltaY = theDeltaY; - } - - //! Sets set of status flags for this face. - inline Standard_Integer GetStatus() const - { - return myStatus; - } - - //! Sets status flag for this face. - inline void SetStatus(const BRepMesh_Status theStatus) - { - myStatus |= theStatus; - } - - //! Returns TRUE in case if computed data is valid. - inline Standard_Boolean IsValid() const - { - return (myStatus == BRepMesh_NoError || myStatus == BRepMesh_ReMesh); - } - -public: //! @name auxiliary structures - - //! Clear face attribute. - Standard_EXPORT void Clear(); - - //! Gives reference to map of internal edges of face. - inline BRepMesh::HDMapOfShapePairOfPolygon& ChangeInternalEdges() - { - return myInternalEdges; - } - - //! Gives reference to map of 2D points of discretization. - inline BRepMesh::HDMapOfIntegerListOfXY& ChangeLocation2D() - { - return myLocation2D; - } - - //! Gives reference to map of 3D points of discretization. - inline BRepMesh::HDMapOfIntegerPnt& ChangeSurfacePoints() - { - return mySurfacePoints; - } - - //! Gives reference to map of vertices of discretization. - inline BRepMesh::HDMapOfVertexInteger& ChangeSurfaceVertices() - { - return mySurfaceVertices; - } - - //! Gives reference on map of (vertex, edge) pairs of face. - inline BRepMesh::HIMapOfInteger& ChangeVertexEdgeMap() - { - return myVertexEdgeMap; - } - - //! Gives Delaunay data structure. - inline Handle(BRepMesh_DataStructureOfDelaun)& ChangeStructure() - { - return myStructure; - } - - //! Returns classifier. - inline BRepMesh::HClassifier& ChangeClassifier() - { - return myClassifier; - } - - //! Returns mesh nodes calculated for boundaries. - inline BRepMesh::HVectorOfVertex& ChangeMeshNodes() - { - return myMeshNodes; - } - -public: //! @name Point/Vertex/Node manipulators - - //! Gives the number of different locations in 3D space. - inline Standard_Integer LastPointId() const - { - return (myBoundaryPoints.IsNull() ? 0 : myBoundaryPoints->Extent()) + - (mySurfacePoints.IsNull() ? 0 : mySurfacePoints->Extent()); - } - - //! Gives the 3D location of the vertex. - inline const gp_Pnt& GetPoint(const BRepMesh_Vertex& theVertex) const - { - return GetPoint(theVertex.Location3d()); - } - - //! Gives the 3D location of the vertex. - inline const gp_Pnt& GetPoint(const Standard_Integer theIndex) const - { - if (!mySurfacePoints.IsNull() && theIndex > myBoundaryPoints->Extent()) - return mySurfacePoints->Find(theIndex); - - return myBoundaryPoints->Find(theIndex); - } - - //! Returns index of the given vertex if it exists in cache, - //! elsewhere adds it to cache and returns cached index. - //! @param theVertexExplorer template parameter intended to transfer - //! parameters of vertex to method. Explorer class can implement different - //! approaches of extraction of target parameters. - //! @param isFillEdgeVertices if TRUE adds vertex to shared map of - //! edges vertices, elsewhere adds it map of face vertices. - template - Standard_Integer GetVertexIndex( - const HVertexExplorer& theVertexExplorer, - const Standard_Boolean isFillEdgeVertices = Standard_False) - { - const TopoDS_Vertex& aVertex = theVertexExplorer->Vertex(); - Standard_Integer aNewVertexIndex = 0; - if (getVertexIndex(aVertex, aNewVertexIndex)) - return aNewVertexIndex; - - if (!theVertexExplorer->IsSameUV() || - !getVertexIndex(theVertexExplorer->SameVertex(), aNewVertexIndex)) - { - aNewVertexIndex = LastPointId() + 1; - - BRepMesh::DMapOfIntegerPnt& aPointsMap = isFillEdgeVertices ? - *myBoundaryPoints : *mySurfacePoints; - - aPointsMap.Bind(aNewVertexIndex, theVertexExplorer->Point()); - } - - BRepMesh::DMapOfVertexInteger& aVertexMap = isFillEdgeVertices ? - *myBoundaryVertices : *mySurfaceVertices; - - aVertexMap.Bind(aVertex, aNewVertexIndex); - - return aNewVertexIndex; - } - - //! Adds node with the given parameters to mesh. - //! @param theIndex index of 3D point corresponded to the node. - //! @param theUV node position. - //! @param theMovability movability of a node. - //! @param theNodeIndex index of vertex in mesh structure. - //! @param theNodeOnEdgeIndex ordered index of node on the boundary. - Standard_EXPORT void AddNode(const Standard_Integer theIndex, - const gp_XY& theUV, - const BRepMesh_DegreeOfFreedom theMovability, - Standard_Integer& theNodeIndex, - Standard_Integer& theNodeOnEdgeIndex); - -public: //! @name Auxiliary methods - - //! Scales the given point from real parametric space - //! to face basis and otherwise. - //! @param thePoint2d point to be scaled. - //! @param isToFaceBasis if TRUE converts point to face basis, - //! otherwise performs reverse conversion. - //! @return scaled point. - Standard_EXPORT gp_XY Scale(const gp_XY& thePoint2d, - const Standard_Boolean isToFaceBasis); - - DEFINE_STANDARD_RTTIEXT(BRepMesh_FaceAttribute,Standard_Transient) - -private: - - //! Default constructor. - BRepMesh_FaceAttribute(); - - //! Assignment operator. - void operator =(const BRepMesh_FaceAttribute& /*theOther*/) - { - } - - //! Initializes internal data structures. - void init(); - - //! Computes parametric tolerance of a face regarding the given limits. - Standard_Real computeParametricTolerance( - const Standard_Real theFirstParam, - const Standard_Real theLastParam) const; - - //! Clears internal data structures local to face. - void clearLocal( - const Standard_Boolean isClearSurfaceDataOnly = Standard_False); - - //! Returns index of the given vertex if it exists in cache. - //! @param theVertex vertex which index should be retrieved. - //! @param theVertexIndex index of the given vertex. - //! @return TRUE if cached value is found, FALSE elsewhere. - Standard_EXPORT Standard_Boolean getVertexIndex( - const TopoDS_Vertex& theVertex, - Standard_Integer& theVertexIndex) const; - -private: - - Standard_Real myDefFace; //!< Restore face deflection - Standard_Real myUMin; //!< Describes minimal value in U domain - Standard_Real myUMax; //!< Describes maximal value in U domain - Standard_Real myVMin; //!< Describes minimal value in V domain - Standard_Real myVMax; //!< Describes maximal value in V domain - Standard_Real myDeltaX; - Standard_Real myDeltaY; - Standard_Real myMinStep; - Standard_Integer myStatus; - Standard_Boolean myAdaptiveMin; - - BRepMesh::HDMapOfVertexInteger myBoundaryVertices; - BRepMesh::HDMapOfIntegerPnt myBoundaryPoints; - - TopoDS_Face myFace; - Handle(BRepAdaptor_HSurface) mySurface; - BRepMesh::HClassifier myClassifier; - - BRepMesh::HDMapOfShapePairOfPolygon myInternalEdges; - - BRepMesh::HDMapOfIntegerListOfXY myLocation2D; - BRepMesh::HIMapOfInteger myVertexEdgeMap; - - // This field is intended to keep calculated mesh nodes to prevent - // extremely high memory consumption in case if the whole structure is kept. - BRepMesh::HVectorOfVertex myMeshNodes; - - BRepMesh::HDMapOfVertexInteger mySurfaceVertices; - BRepMesh::HDMapOfIntegerPnt mySurfacePoints; - Handle(BRepMesh_DataStructureOfDelaun) myStructure; -}; - -DEFINE_STANDARD_HANDLE(BRepMesh_FaceAttribute, Standard_Transient) - -#endif diff --git a/src/BRepMesh/BRepMesh_FaceChecker.cxx b/src/BRepMesh/BRepMesh_FaceChecker.cxx new file mode 100644 index 0000000000..cc2491df70 --- /dev/null +++ b/src/BRepMesh/BRepMesh_FaceChecker.cxx @@ -0,0 +1,312 @@ +// Created on: 2016-07-04 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 +#include +#include +#include +#include + +namespace +{ + const Standard_Real MaxTangentAngle = 5. * M_PI / 180.; + + //! Functor to be used to fill segments and bounding box tree in parallel. + class SegmentsFiller + { + public: + //! Constructor. + SegmentsFiller(const IMeshData::IFaceHandle& theDFace, + Handle(BRepMesh_FaceChecker::ArrayOfSegments)& theWiresSegments, + Handle(BRepMesh_FaceChecker::ArrayOfBndBoxTree)& theWiresBndBoxTree) + : myDFace(theDFace), + myWiresSegments(theWiresSegments), + myWiresBndBoxTree(theWiresBndBoxTree) + { + myWiresSegments = new BRepMesh_FaceChecker::ArrayOfSegments (0, myDFace->WiresNb() - 1); + myWiresBndBoxTree = new BRepMesh_FaceChecker::ArrayOfBndBoxTree (0, myDFace->WiresNb() - 1); + } + + //! Performs initialization of wire with the given index. + void operator()(const Standard_Integer theWireIndex) const + { + const IMeshData::IWireHandle& aDWire = myDFace->GetWire(theWireIndex); + + Handle(NCollection_IncAllocator) aTmpAlloc1 = new NCollection_IncAllocator(); + + Handle(BRepMesh_FaceChecker::Segments) aSegments = + new BRepMesh_FaceChecker::Segments(aDWire->EdgesNb(), aTmpAlloc1); + Handle(IMeshData::BndBox2dTree) aBndBoxTree = new IMeshData::BndBox2dTree(aTmpAlloc1); + + myWiresSegments ->ChangeValue(theWireIndex) = aSegments; + myWiresBndBoxTree->ChangeValue(theWireIndex) = aBndBoxTree; + + Handle(NCollection_IncAllocator) aTmpAlloc2 = new NCollection_IncAllocator(); + IMeshData::BndBox2dTreeFiller aBndBoxTreeFiller(*aBndBoxTree, aTmpAlloc2); + + for (Standard_Integer aEdgeIt = 0; aEdgeIt < aDWire->EdgesNb(); ++aEdgeIt) + { + // TODO: check 2d wire for consistency. + + const IMeshData::IEdgePtr& aDEdge = aDWire->GetEdge(aEdgeIt); + const IMeshData::IPCurveHandle& aPCurve = aDEdge->GetPCurve(myDFace.get(), aDWire->GetEdgeOrientation(aEdgeIt)); + + for (Standard_Integer aPointIt = 1; aPointIt < aPCurve->ParametersNb(); ++aPointIt) + { + gp_Pnt2d& aPnt1 = aPCurve->GetPoint(aPointIt - 1); + gp_Pnt2d& aPnt2 = aPCurve->GetPoint(aPointIt); + + Bnd_Box2d aBox; + aBox.Add(aPnt1); + aBox.Add(aPnt2); + aBox.Enlarge(Precision::Confusion()); + + aBndBoxTreeFiller.Add(aSegments->Size(), aBox); + aSegments->Append(BRepMesh_FaceChecker::Segment(aDEdge, &aPnt1, &aPnt2)); + } + } + + aBndBoxTreeFiller.Fill(); + } + + private: + + SegmentsFiller (const SegmentsFiller& theOther); + + void operator=(const SegmentsFiller& theOther); + + private: + + const IMeshData::IFaceHandle& myDFace; + Handle(BRepMesh_FaceChecker::ArrayOfSegments)& myWiresSegments; + Handle(BRepMesh_FaceChecker::ArrayOfBndBoxTree)& myWiresBndBoxTree; + }; + + //! Selector. + //! Used to identify segments with overlapped bounding boxes. + class BndBox2dTreeSelector : public IMeshData::BndBox2dTree::Selector + { + public: + //! Constructor. + BndBox2dTreeSelector(const Standard_Real theTolerance) + : myMaxLoopSize(M_PI * theTolerance * theTolerance), + mySelfSegmentIndex(-1), + myIndices(256, new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE)) + { + } + + //! Sets working set of segments. + void SetSegments(const Handle(BRepMesh_FaceChecker::Segments)& theSegments) + { + mySegments = theSegments; + } + + //! Resets current selector. + void Reset(const BRepMesh_FaceChecker::Segment* theSegment, + const Standard_Integer theSelfSegmentIndex) + { + myIndices.Clear(); + + mySelfSegmentIndex = theSelfSegmentIndex; + mySegment = theSegment; + + myBox.SetVoid(); + myBox.Add(*mySegment->Point1); + myBox.Add(*mySegment->Point2); + myBox.Enlarge(Precision::Confusion()); + } + + //! Indicates should the given box be rejected or not. + virtual Standard_Boolean Reject(const Bnd_Box2d& theBox) const + { + return myBox.IsOut(theBox); + } + + //! Accepts segment with the given index in case if it fits conditions. + virtual Standard_Boolean Accept(const Standard_Integer& theSegmentIndex) + { + const BRepMesh_FaceChecker::Segment& aSegment = mySegments->Value(theSegmentIndex); + + gp_Pnt2d aIntPnt; + const BRepMesh_GeomTool::IntFlag aIntStatus = BRepMesh_GeomTool::IntSegSeg( + mySegment->Point1->XY(), mySegment->Point2->XY(), + aSegment.Point1->XY(), aSegment.Point2->XY(), + Standard_False, Standard_False, aIntPnt); + + if (aIntStatus == BRepMesh_GeomTool::Cross) + { + const Standard_Real aAngle = gp_Vec2d(mySegment->Point1->XY(), mySegment->Point2->XY()).Angle( + gp_Vec2d(aSegment.Point1->XY(), aSegment.Point2->XY())); + + if (Abs(aAngle) < MaxTangentAngle) + { + return Standard_False; + } + + if (mySelfSegmentIndex != -1) + { + gp_XY aPrevVec; + Standard_Real aSumS = 0.; + const gp_XY& aRefPnt = aIntPnt.Coord(); + for (Standard_Integer i = mySelfSegmentIndex; i < theSegmentIndex; ++i) + { + const BRepMesh_FaceChecker::Segment& aCurrSegment = mySegments->Value(i); + gp_XY aCurVec = aCurrSegment.Point2->XY() - aRefPnt; + + if (aCurVec.SquareModulus() < gp::Resolution()) + continue; + + if (aPrevVec.SquareModulus() > gp::Resolution()) + aSumS += aPrevVec ^ aCurVec; + + aPrevVec = aCurVec; + } + + if (Abs(aSumS / 2.) < myMaxLoopSize) + { + return Standard_False; + } + } + + myIndices.Append(theSegmentIndex); + return Standard_True; + } + + return Standard_False; + } + + //! Returns indices of intersecting segments. + const IMeshData::VectorOfInteger& Indices() const + { + return myIndices; + } + + private: + + Standard_Real myMaxLoopSize; + Standard_Integer mySelfSegmentIndex; + Handle(BRepMesh_FaceChecker::Segments) mySegments; + const BRepMesh_FaceChecker::Segment* mySegment; + Bnd_Box2d myBox; + IMeshData::VectorOfInteger myIndices; + }; +} + +//======================================================================= +//function : Constructor +//purpose : +//======================================================================= +BRepMesh_FaceChecker::BRepMesh_FaceChecker( + const IMeshData::IFaceHandle& theFace, + const IMeshTools_Parameters& theParameters) + : myDFace(theFace), + myParameters(theParameters) +{ +} + +//======================================================================= +//function : Destructor +//purpose : +//======================================================================= +BRepMesh_FaceChecker::~BRepMesh_FaceChecker() +{ +} + +//======================================================================= +//function : Perform +//purpose : +//======================================================================= +Standard_Boolean BRepMesh_FaceChecker::Perform() +{ + myIntersectingEdges = new IMeshData::MapOfIEdgePtr; + collectSegments(); + + OSD_Parallel::For(0, myDFace->WiresNb(), *this, !isParallel()); + collectResult(); + + myWiresBndBoxTree.Nullify(); + myWiresSegments.Nullify(); + myWiresIntersectingEdges.Nullify(); + return myIntersectingEdges->IsEmpty(); +} + +//======================================================================= +//function : collectSegments +//purpose : +//======================================================================= +void BRepMesh_FaceChecker::collectSegments() +{ + SegmentsFiller aSegmentsFiller(myDFace, myWiresSegments, myWiresBndBoxTree); + OSD_Parallel::For(0, myDFace->WiresNb(), aSegmentsFiller, !isParallel()); + + myWiresIntersectingEdges = new ArrayOfMapOfIEdgePtr(0, myDFace->WiresNb() - 1); +} + +//======================================================================= +//function : perform +//purpose : +//======================================================================= +void BRepMesh_FaceChecker::perform(const Standard_Integer theWireIndex) const +{ + const Handle(Segments)& aSegments1 = myWiresSegments->Value(theWireIndex); + Handle(IMeshData::MapOfIEdgePtr)& aIntersections = myWiresIntersectingEdges->ChangeValue(theWireIndex); + + // TODO: Tolerance is set to twice value of face deflection in order to fit regressions. + BndBox2dTreeSelector aSelector(2 * myDFace->GetDeflection()); + for (Standard_Integer aWireIt = theWireIndex; aWireIt < myDFace->WiresNb(); ++aWireIt) + { + const Handle(IMeshData::BndBox2dTree)& aBndBoxTree2 = myWiresBndBoxTree->Value(aWireIt); + const Handle(Segments)& aSegments2 = myWiresSegments->Value(aWireIt); + + aSelector.SetSegments(aSegments2); + for (Standard_Integer aSegmentIt = 0; aSegmentIt < aSegments1->Size(); ++aSegmentIt) + { + const BRepMesh_FaceChecker::Segment& aSegment1 = aSegments1->Value(aSegmentIt); + aSelector.Reset(&aSegment1, (aWireIt == theWireIndex) ? aSegmentIt : -1); + if (aBndBoxTree2->Select(aSelector) != 0) + { + if (aIntersections.IsNull()) + { + aIntersections = new IMeshData::MapOfIEdgePtr; + } + + aIntersections->Add(aSegment1.EdgePtr); + + const IMeshData::VectorOfInteger& aSegments = aSelector.Indices(); + for (Standard_Integer aSelIt = 0; aSelIt < aSegments.Size(); ++aSelIt) + { + const BRepMesh_FaceChecker::Segment& aSegment2 = aSegments2->Value(aSegments(aSelIt)); + aIntersections->Add(aSegment2.EdgePtr); + } + } + } + } +} + +//======================================================================= +//function : collectResult +//purpose : +//======================================================================= +void BRepMesh_FaceChecker::collectResult() +{ + for (Standard_Integer aWireIt = 0; aWireIt < myDFace->WiresNb(); ++aWireIt) + { + const Handle(IMeshData::MapOfIEdgePtr)& aEdges = myWiresIntersectingEdges->Value(aWireIt); + if (!aEdges.IsNull()) + { + myIntersectingEdges->Unite(*aEdges); + } + } +} diff --git a/src/BRepMesh/BRepMesh_FaceChecker.hxx b/src/BRepMesh/BRepMesh_FaceChecker.hxx new file mode 100644 index 0000000000..93f574a45d --- /dev/null +++ b/src/BRepMesh/BRepMesh_FaceChecker.hxx @@ -0,0 +1,122 @@ +// Created on: 2016-07-04 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _BRepMesh_FaceChecker_HeaderFile +#define _BRepMesh_FaceChecker_HeaderFile + +#include +#include +#include +#include +#include + +//! Auxiliary class checking wires of target face for self-intersections. +//! Explodes wires of discrete face on sets of segments using tessellation +//! data stored in model. Each segment is then checked for intersection with +//! other ones. All collisions are registerd and returned as result of check. +class BRepMesh_FaceChecker : public Standard_Transient +{ +public: //! @name mesher API + + //! Identifies segment inside face. + struct Segment + { + IMeshData::IEdgePtr EdgePtr; + gp_Pnt2d* Point1; // \ Use explicit pointers to points instead of accessing + gp_Pnt2d* Point2; // / using indices. + + Segment() + : Point1(NULL) + , Point2(NULL) + { + } + + Segment(const IMeshData::IEdgePtr& theEdgePtr, + gp_Pnt2d* thePoint1, + gp_Pnt2d* thePoint2) + : EdgePtr(theEdgePtr) + , Point1(thePoint1) + , Point2(thePoint2) + { + } + }; + + typedef NCollection_Shared > Segments; + typedef NCollection_Shared > ArrayOfSegments; + typedef NCollection_Shared > ArrayOfBndBoxTree; + typedef NCollection_Shared > ArrayOfMapOfIEdgePtr; + + + //! Default constructor + Standard_EXPORT BRepMesh_FaceChecker(const IMeshData::IFaceHandle& theFace, + const IMeshTools_Parameters& theParameters); + + //! Destructor + Standard_EXPORT virtual ~BRepMesh_FaceChecker(); + + //! Performs check wires of the face for intersections. + //! @return True if there is no intersection, False elsewhere. + Standard_EXPORT Standard_Boolean Perform(); + + //! Returns intersecting edges. + const Handle(IMeshData::MapOfIEdgePtr)& GetIntersectingEdges() const + { + return myIntersectingEdges; + } + + //! Checks wire with the given index for intersection with others. + inline void operator()(const Standard_Integer theWireIndex) const + { + perform(theWireIndex); + } + + DEFINE_STANDARD_RTTI_INLINE(BRepMesh_FaceChecker, Standard_Transient) + +private: + + //! Returns True in case if check can be performed in parallel mode. + inline Standard_Boolean isParallel() const + { + return (myParameters.InParallel && myDFace->WiresNb() > 1); + } + + //! Collects face segments. + void collectSegments(); + + //! Collects intersecting edges. + void collectResult(); + + //! Checks wire with the given index for intersection with others. + void perform(const Standard_Integer theWireIndex) const; + +private: + + BRepMesh_FaceChecker (const BRepMesh_FaceChecker& theOther); + + void operator=(const BRepMesh_FaceChecker& theOther); + +private: + + IMeshData::IFaceHandle myDFace; + const IMeshTools_Parameters& myParameters; + + Handle(ArrayOfSegments) myWiresSegments; + Handle(ArrayOfBndBoxTree) myWiresBndBoxTree; + Handle(ArrayOfMapOfIEdgePtr) myWiresIntersectingEdges; + Handle(IMeshData::MapOfIEdgePtr) myIntersectingEdges; + +}; + +#endif diff --git a/src/BRepMesh/BRepMesh_FaceDiscret.cxx b/src/BRepMesh/BRepMesh_FaceDiscret.cxx new file mode 100644 index 0000000000..ce6db2102e --- /dev/null +++ b/src/BRepMesh/BRepMesh_FaceDiscret.cxx @@ -0,0 +1,95 @@ +// Created on: 2016-04-19 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 +#include +#include +#include +#include +#include +#include + +//======================================================================= +// Function: Constructor +// Purpose : +//======================================================================= +BRepMesh_FaceDiscret::BRepMesh_FaceDiscret( + const Handle(IMeshTools_MeshAlgoFactory)& theAlgoFactory) + : myAlgoFactory(theAlgoFactory) +{ +} + +//======================================================================= +// Function: Destructor +// Purpose : +//======================================================================= +BRepMesh_FaceDiscret::~BRepMesh_FaceDiscret() +{ +} + +//======================================================================= +// Function: Perform +// Purpose : +//======================================================================= +Standard_Boolean BRepMesh_FaceDiscret::performInternal( + const Handle(IMeshData_Model)& theModel, + const IMeshTools_Parameters& theParameters) +{ + myModel = theModel; + myParameters = theParameters; + if (myModel.IsNull()) + { + return Standard_False; + } + + OSD_Parallel::For(0, myModel->FacesNb(), *this, !(myParameters.InParallel && myModel->FacesNb() > 1)); + + myModel.Nullify(); // Do not hold link to model. + return Standard_True; +} + +//======================================================================= +// Function: process +// Purpose : +//======================================================================= +void BRepMesh_FaceDiscret::process(const Standard_Integer theFaceIndex) const +{ + const IMeshData::IFaceHandle& aDFace = myModel->GetFace(theFaceIndex); + if (aDFace->IsSet(IMeshData_Failure) || + aDFace->IsSet(IMeshData_Reused)) + { + return; + } + + try + { + OCC_CATCH_SIGNALS + + Handle(IMeshTools_MeshAlgo) aMeshingAlgo = + myAlgoFactory->GetAlgo(aDFace->GetSurface()->GetType(), myParameters); + + if (aMeshingAlgo.IsNull()) + { + aDFace->SetStatus(IMeshData_Failure); + return; + } + + aMeshingAlgo->Perform(aDFace, myParameters); + } + catch (Standard_Failure const&) + { + aDFace->SetStatus (IMeshData_Failure); + } +} diff --git a/src/BRepMesh/BRepMesh_FaceDiscret.hxx b/src/BRepMesh/BRepMesh_FaceDiscret.hxx new file mode 100644 index 0000000000..9ca86800b6 --- /dev/null +++ b/src/BRepMesh/BRepMesh_FaceDiscret.hxx @@ -0,0 +1,65 @@ +// Created on: 2016-04-19 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _BRepMesh_FaceDiscret_HeaderFile +#define _BRepMesh_FaceDiscret_HeaderFile + +#include +#include +#include +#include + +//! Class implements functionality starting triangulation of model's faces. +//! Each face is processed separately and can be executed in parallel mode. +//! Uses mesh algo factory passed as initializer to create instance of triangulation +//! algorithm according to type of surface of target face. +class BRepMesh_FaceDiscret : public IMeshTools_ModelAlgo +{ +public: + + //! Constructor. + Standard_EXPORT BRepMesh_FaceDiscret( + const Handle(IMeshTools_MeshAlgoFactory)& theAlgoFactory); + + //! Destructor. + Standard_EXPORT virtual ~BRepMesh_FaceDiscret(); + + //! Functor API to discretize the given edge. + inline void operator() (const Standard_Integer theFaceIndex) const { + process(theFaceIndex); + } + + DEFINE_STANDARD_RTTI_INLINE(BRepMesh_FaceDiscret, IMeshTools_ModelAlgo) + +protected: + + //! Performs processing of faces of the given model. + Standard_EXPORT virtual Standard_Boolean performInternal ( + const Handle(IMeshData_Model)& theModel, + const IMeshTools_Parameters& theParameters) Standard_OVERRIDE; + +private: + + //! Checks existing discretization of the face and updates data model. + void process(const Standard_Integer theFaceIndex) const; + +private: + + Handle(IMeshTools_MeshAlgoFactory) myAlgoFactory; + Handle(IMeshData_Model) myModel; + IMeshTools_Parameters myParameters; +}; + +#endif diff --git a/src/BRepMesh/BRepMesh_FastDiscret.cxx b/src/BRepMesh/BRepMesh_FastDiscret.cxx deleted file mode 100644 index f64de14122..0000000000 --- a/src/BRepMesh/BRepMesh_FastDiscret.cxx +++ /dev/null @@ -1,989 +0,0 @@ -// Created on: 1996-02-27 -// Created by: Ekaterina SMIRNOVA -// Copyright (c) 1996-1999 Matra Datavision -// Copyright (c) 1999-2014 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -#include -#include -#include - -#include - -IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_FastDiscret,Standard_Transient) - -#define UVDEFLECTION 1.e-05 - -//======================================================================= -//function : BRepMesh_FastDiscret -//purpose : -//======================================================================= -BRepMesh_FastDiscret::BRepMesh_FastDiscret( const Bnd_Box& theBox, - const BRepMesh_FastDiscret::Parameters& theParams) - : - myMapdefle(1000, new NCollection_IncAllocator()), - myBoundaryVertices(new BRepMesh::DMapOfVertexInteger), - myBoundaryPoints(new BRepMesh::DMapOfIntegerPnt), - myParameters(theParams), - myDtotale(0.) -{ - if ( myParameters.Relative ) - BRepMesh_ShapeTool::BoxMaxDimension(theBox, myDtotale); -} - -//======================================================================= -//function : InitSharedFaces -//purpose : -//======================================================================= -void BRepMesh_FastDiscret::InitSharedFaces(const TopoDS_Shape& theShape) -{ - TopExp::MapShapesAndAncestors(theShape, TopAbs_EDGE, TopAbs_FACE, mySharedFaces); -} - -//======================================================================= -//function : Perform(shape) -//purpose : -//======================================================================= -void BRepMesh_FastDiscret::Perform(const TopoDS_Shape& theShape) -{ - InitSharedFaces(theShape); - - std::vector aFaces; - TopExp_Explorer anExplorer(theShape, TopAbs_FACE); - for (; anExplorer.More(); anExplorer.Next()) - { - const TopoDS_Face& aFace = TopoDS::Face(anExplorer.Current()); - Add(aFace); - aFaces.push_back(aFace); - } - - OSD_Parallel::ForEach(aFaces.begin(), aFaces.end(), *this, !myParameters.InParallel); -} - -//======================================================================= -//function : Process -//purpose : -//======================================================================= -void BRepMesh_FastDiscret::Process(const TopoDS_Face& theFace) const -{ - Process (theFace, NULL); -} - -//======================================================================= -//function : Process -//purpose : -//======================================================================= -void BRepMesh_FastDiscret::Process (const TopoDS_Face& theFace, - Message_ProgressSentry* theProgrEntry) const -{ - Handle(BRepMesh_FaceAttribute) anAttribute; - if (GetFaceAttribute(theFace, anAttribute) - && (theProgrEntry == NULL || theProgrEntry->More())) - { - try - { - OCC_CATCH_SIGNALS - - BRepMesh_FastDiscretFace aTool(myParameters.Angle, myParameters.MinSize, - myParameters.InternalVerticesMode, myParameters.ControlSurfaceDeflection); - aTool.Perform (anAttribute, theProgrEntry); - } - catch (Standard_Failure) - { - anAttribute->SetStatus(BRepMesh_Failure); - } - } -} - -//======================================================================= -//function : resetDataStructure -//purpose : -//======================================================================= -void BRepMesh_FastDiscret::resetDataStructure() -{ - Handle(NCollection_IncAllocator) aAllocator; - if (myAttribute->ChangeStructure().IsNull()) - aAllocator = new NCollection_IncAllocator(BRepMesh::MEMORY_BLOCK_SIZE_HUGE); - else - aAllocator = myAttribute->ChangeStructure()->Allocator(); - - myAttribute->Clear(); - aAllocator->Reset(Standard_False); - Handle(BRepMesh_DataStructureOfDelaun) aStructure = - new BRepMesh_DataStructureOfDelaun(aAllocator); - - const Standard_Real aTolU = myAttribute->ToleranceU(); - const Standard_Real aTolV = myAttribute->ToleranceV(); - const Standard_Real uCellSize = 14.0 * aTolU; - const Standard_Real vCellSize = 14.0 * aTolV; - - aStructure->Data()->SetCellSize ( uCellSize, vCellSize); - aStructure->Data()->SetTolerance( aTolU , aTolV ); - - myAttribute->ChangeStructure() = aStructure; -} - -//======================================================================= -//function : Add(face) -//purpose : -//======================================================================= -Standard_Integer BRepMesh_FastDiscret::Add(const TopoDS_Face& theFace) -{ - myAttribute.Nullify(); - GetFaceAttribute(theFace, myAttribute, Standard_True); - - try - { - OCC_CATCH_SIGNALS - - // Initialize face attributes - if (!myAttribute->IsInitialized ()) - myAttribute->SetFace (theFace, myParameters.AdaptiveMin); - - BRepMesh::HIMapOfInteger& aVertexEdgeMap = myAttribute->ChangeVertexEdgeMap(); - BRepMesh::HDMapOfShapePairOfPolygon& aInternalEdges = myAttribute->ChangeInternalEdges(); - - resetDataStructure(); - - Standard_Real defedge = myParameters.Deflection; - Standard_Integer nbEdge = 0; - Standard_Real savangle = myParameters.Angle; - Standard_Real cdef; - Standard_Real maxdef = 2.* BRepMesh_ShapeTool::MaxFaceTolerance(theFace); - - Standard_Real defface = 0.; - if (!myParameters.Relative) - { - defedge = Max(UVDEFLECTION, defedge); - defface = Max(myParameters.Deflection, maxdef); - } - - const TopoDS_Face& aFace = myAttribute->Face(); - for (TopoDS_Iterator aWireIt(aFace); aWireIt.More(); aWireIt.Next()) - { - for (TopoDS_Iterator aEdgeIt(aWireIt.Value()); aEdgeIt.More(); aEdgeIt.Next(), ++nbEdge) - { - const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Value()); - if (aEdge.IsNull()) - continue; - if (myParameters.Relative) - { - if (!myMapdefle.IsBound(aEdge)) - { - if (myEdges.IsBound(aEdge)) - { - const BRepMesh_PairOfPolygon& aPair = myEdges.Find(aEdge); - const Handle(Poly_PolygonOnTriangulation)& aPolygon = aPair.First(); - defedge = aPolygon->Deflection(); - } - else - { - defedge = BRepMesh_ShapeTool::RelativeEdgeDeflection( - aEdge, myParameters.Deflection, myDtotale, cdef); - - myParameters.Angle = savangle * cdef; - } - } - else - { - defedge = myMapdefle(aEdge); - } - - defface += defedge; - defface = Max(maxdef, defface); - - if (!myMapdefle.IsBound(aEdge)) - { - defedge = Max(UVDEFLECTION, defedge); - myMapdefle.Bind(aEdge, defedge); - } - } - else - { - if (!myMapdefle.IsBound(aEdge)) - { - myMapdefle.Bind(aEdge, defedge); - } - } - - Standard_Real aFirstParam, aLastParam; - Handle(Geom2d_Curve) aCurve2d = - BRep_Tool::CurveOnSurface(aEdge, aFace, aFirstParam, aLastParam); - - if (aCurve2d.IsNull()) - continue; - Handle(Geom2dAdaptor_HCurve) aPCurve = - new Geom2dAdaptor_HCurve(aCurve2d, aFirstParam, aLastParam); - - add(aEdge, aPCurve, defedge); - myParameters.Angle = savangle; - } - } - - if ( nbEdge == 0 || aVertexEdgeMap->Extent() < 3 ) - { - myAttribute->ChangeStructure().Nullify(); - myAttribute->SetStatus(BRepMesh_Failure); - return myAttribute->GetStatus(); - } - - if ( myParameters.Relative ) - { - defface = defface / nbEdge; - } - else - { - defface = myParameters.Deflection; - } - - defface = Max(maxdef, defface); - - TopLoc_Location aLoc; - Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation(aFace, aLoc); - const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface(); - - if ( aTriangulation.IsNull() ) - { - Standard_Real xCur, yCur; - Standard_Real maxX, minX, maxY, minY; - - minX = minY = 1.e100; - maxX = maxY =-1.e100; - - Standard_Integer ipn = 0; - Standard_Integer i1 = 1; - for ( i1 = 1; i1 <= aVertexEdgeMap->Extent(); ++i1 ) - { - const BRepMesh_Vertex& aVertex = - myAttribute->ChangeStructure()->GetNode(aVertexEdgeMap->FindKey(i1)); - - ++ipn; - - xCur = aVertex.Coord().X(); - yCur = aVertex.Coord().Y(); - - minX = Min(xCur, minX); - maxX = Max(xCur, maxX); - minY = Min(yCur, minY); - maxY = Max(yCur, maxY); - } - - Standard_Real myumin = minX; - Standard_Real myumax = maxX; - Standard_Real myvmin = minY; - Standard_Real myvmax = maxY; - - const Standard_Real umin = gFace->FirstUParameter(); - const Standard_Real umax = gFace->LastUParameter(); - const Standard_Real vmin = gFace->FirstVParameter(); - const Standard_Real vmax = gFace->LastVParameter(); - - if (myumin < umin || myumax > umax) - { - if (gFace->IsUPeriodic()) - { - if ((myumax - myumin) > (umax - umin)) - myumax = myumin + (umax - umin); - } - else - { - if (umin > myumin) - myumin = umin; - - if (umax < myumax) - myumax = umax; - } - } - - if (myvmin < vmin || myvmax > vmax) - { - if (gFace->IsVPeriodic()) - { - if ((myvmax - myvmin) > (vmax - vmin)) - myvmax = myvmin + (vmax - vmin); - } - else - { - if ( vmin > myvmin ) - myvmin = vmin; - - if (vmax < myvmax) - myvmax = vmax; - } - } - - GeomAbs_SurfaceType aSurfType = gFace->GetType(); - // Fast verification of the validity of calculated limits. - // If wrong, sure a problem of pcurve. - if (aSurfType == GeomAbs_BezierSurface && - (myumin < -0.5 || myumax > 1.5 || myvmin < -0.5 || myvmax > 1.5) ) - { - myAttribute->ChangeStructure().Nullify(); - myAttribute->SetStatus(BRepMesh_Failure); - return myAttribute->GetStatus(); - } - - //define parameters for correct parametrics - Standard_Real deltaX = 1.0; - Standard_Real deltaY = 1.0; - - { - Standard_Real aTolU, aTolV; - myAttribute->ChangeStructure()->Data()->GetTolerance(aTolU, aTolV); - const Standard_Real aTol = Sqrt(aTolU * aTolU + aTolV * aTolV); - - BRepMesh::HClassifier& aClassifier = myAttribute->ChangeClassifier(); - BRepMesh_WireChecker aDFaceChecker(aFace, aTol, aInternalEdges, - aVertexEdgeMap, myAttribute->ChangeStructure(), - myumin, myumax, myvmin, myvmax, myParameters.InParallel ); - - aDFaceChecker.ReCompute(aClassifier); - BRepMesh_Status aCheckStatus = aDFaceChecker.Status(); - - if (aCheckStatus == BRepMesh_SelfIntersectingWire) - { - Standard_Integer nbmaill = 0; - Standard_Real eps = Precision::Confusion(); - while (nbmaill < 5 && aCheckStatus != BRepMesh_ReMesh) - { - ++nbmaill; - - resetDataStructure(); - - for (TopoDS_Iterator aWireIt(aFace); aWireIt.More(); aWireIt.Next()) - { - for (TopoDS_Iterator aEdgeIt(aWireIt.Value()); aEdgeIt.More(); aEdgeIt.Next(), ++nbEdge) - { - const TopoDS_Edge& anEdge = TopoDS::Edge(aEdgeIt.Value()); - if (anEdge.IsNull()) - continue; - if (myEdges.IsBound(anEdge)) - myEdges.UnBind(anEdge); - - defedge = Max(myMapdefle(anEdge) / 3.0, eps); - myMapdefle.Bind(anEdge, defedge); - - Standard_Real aFirstParam, aLastParam; - Handle(Geom2d_Curve) aCurve2d = - BRep_Tool::CurveOnSurface(anEdge, aFace, aFirstParam, aLastParam); - if (aCurve2d.IsNull()) - continue; - - Handle(Geom2dAdaptor_HCurve) aPCurve = - new Geom2dAdaptor_HCurve(aCurve2d, aFirstParam, aLastParam); - add(anEdge, aPCurve, defedge); - } - } - - aDFaceChecker.ReCompute(aClassifier); - if (aDFaceChecker.Status() == BRepMesh_NoError) - aCheckStatus = BRepMesh_ReMesh; - } - } - - myAttribute->SetStatus(aCheckStatus); - if (!myAttribute->IsValid()) - { - myAttribute->ChangeStructure().Nullify(); - return myAttribute->GetStatus(); - } - } - - // try to find the real length: - // akm (bug OCC16) : We must calculate these measures in non-singular - // parts of face. Let's try to compute average value of three - // (umin, (umin+umax)/2, umax), and respectively for v. - // vvvvv - Standard_Real longu = 0.0, longv = 0.0; //, last , first; - gp_Pnt P11, P12, P21, P22, P31, P32; - - Standard_Real du = 0.05 * ( myumax - myumin ); - Standard_Real dv = 0.05 * ( myvmax - myvmin ); - Standard_Real dfuave = 0.5 * ( myumin + myumax ); - Standard_Real dfvave = 0.5 * ( myvmin + myvmax ); - Standard_Real dfucur, dfvcur; - - // U loop - gFace->D0(myumin, myvmin, P11); - gFace->D0(myumin, dfvave, P21); - gFace->D0(myumin, myvmax, P31); - for (i1=1, dfucur=myumin+du; i1 <= 20; i1++, dfucur+=du) - { - gFace->D0(dfucur, myvmin, P12); - gFace->D0(dfucur, dfvave, P22); - gFace->D0(dfucur, myvmax, P32); - longu += ( P11.Distance(P12) + P21.Distance(P22) + P31.Distance(P32) ); - P11 = P12; - P21 = P22; - P31 = P32; - } - - // V loop - gFace->D0(myumin, myvmin, P11); - gFace->D0(dfuave, myvmin, P21); - gFace->D0(myumax, myvmin, P31); - for (i1=1, dfvcur=myvmin+dv; i1 <= 20; i1++, dfvcur+=dv) - { - gFace->D0(myumin, dfvcur, P12); - gFace->D0(dfuave, dfvcur, P22); - gFace->D0(myumax, dfvcur, P32); - longv += ( P11.Distance(P12) + P21.Distance(P22) + P31.Distance(P32) ); - P11 = P12; - P21 = P22; - P31 = P32; - } - - longu /= 3.; - longv /= 3.; - // akm (bug OCC16) ^^^^^ - - if (longu <= 1.e-16 || longv <= 1.e-16) - { - //yes, it is seen!! - myAttribute->ChangeStructure().Nullify(); - myAttribute->SetStatus(BRepMesh_Failure); - return myAttribute->GetStatus(); - } - - - if (aSurfType == GeomAbs_Torus) - { - gp_Torus Tor = gFace->Torus(); - Standard_Real r = Tor.MinorRadius(), R = Tor.MajorRadius(); - Standard_Real Du, Dv;//, pasu, pasv; - - Dv = Max(1.0e0 - (defface/r),0.0e0) ; - Standard_Real oldDv = 2.0 * ACos (Dv); - oldDv = Min(oldDv, myParameters.Angle); - Dv = 0.9*oldDv; //TWOTHIRD * oldDv; - Dv = oldDv; - - Standard_Integer nbV = Max((Standard_Integer)((myvmax-myvmin)/Dv), 2); - Dv = (myvmax-myvmin)/(nbV+1); - - Standard_Real ru = R + r; - if ( ru > 1.e-16 ) - { - Du = Max(1.0e0 - (defface/ru),0.0e0); - Du = (2.0 * ACos (Du)); - Du = Min(Du, myParameters.Angle); - Standard_Real aa = sqrt(Du*Du + oldDv*oldDv); - - if (aa < gp::Resolution()) - { - myAttribute->ChangeStructure().Nullify(); - return myAttribute->GetStatus(); - } - - Du = Du * Min(oldDv, Du) / aa; - } - else - { - Du = Dv; - } - - Standard_Integer nbU = Max((Standard_Integer)((myumax-myumin)/Du), 2); - nbU = Max(nbU, (Standard_Integer)(nbV*(myumax-myumin)*R/((myvmax-myvmin)*r)/5.)); - - Du = (myumax-myumin)/(nbU+1); - //-- DeltaX and DeltaY are chosen so that to avoid "jumping" - //-- of points on the grid - deltaX = Du; - deltaY = Dv; - } - else if (aSurfType == GeomAbs_Cylinder) - { - gp_Cylinder Cyl = gFace->Cylinder(); - Standard_Real R = Cyl.Radius(); - - // Calculate parameters for iteration in U direction - Standard_Real Du = 1.0 - (defface/R); - if (Du < 0.0) - Du = 0.0; - - Du = 2.0 * ACos (Du); - if (Du > myParameters.Angle) - Du = myParameters.Angle; - - deltaX = Du / longv; - deltaY = 1.; - } - else - { - deltaX = (myumax-myumin)/longu; - deltaY = (myvmax-myvmin)/longv; - } - - // Restore face attribute - myAttribute->SetDefFace(defface); - myAttribute->SetUMax(myumax); - myAttribute->SetVMax(myvmax); - myAttribute->SetUMin(myumin); - myAttribute->SetVMin(myvmin); - myAttribute->SetDeltaX(deltaX); - myAttribute->SetDeltaY(deltaY); - } - - myAttribute->ChangeMeshNodes() = - myAttribute->ChangeStructure()->Data()->Vertices(); - } - catch(Standard_Failure) - { - myAttribute->SetStatus(BRepMesh_Failure); - } - - myAttribute->ChangeStructure().Nullify(); - return myAttribute->GetStatus(); -} - -//======================================================================= -//function : getEdgeAttributes -//purpose : -//======================================================================= -Standard_Boolean BRepMesh_FastDiscret::getEdgeAttributes( - const TopoDS_Edge& theEdge, - const Handle(Geom2dAdaptor_HCurve)& thePCurve, - const Standard_Real theDefEdge, - BRepMesh_FastDiscret::EdgeAttributes& theAttributes) const -{ - EdgeAttributes& aEAttr = theAttributes; - - // Get vertices - TopExp::Vertices(theEdge, aEAttr.FirstVertex, aEAttr.LastVertex); - if (aEAttr.FirstVertex.IsNull() || aEAttr.LastVertex.IsNull()) - return Standard_False; - - // Get range on 2d curve - const TopoDS_Face& aFace = myAttribute->Face(); - BRep_Tool::Range(theEdge, aFace, aEAttr.FirstParam, aEAttr.LastParam); - - // Get end points on 2d curve - BRep_Tool::UVPoints(theEdge, aFace, aEAttr.FirstUV, aEAttr.LastUV); - - aEAttr.IsSameUV = - aEAttr.FirstUV.IsEqual(aEAttr.LastUV, Precision::PConfusion()); - if (aEAttr.IsSameUV) - { - // 1. is it really sameUV without being degenerated - gp_Pnt2d uvF, uvL; - thePCurve->D0(thePCurve->FirstParameter(), uvF); - thePCurve->D0(thePCurve->LastParameter(), uvL); - - if (!aEAttr.FirstUV.IsEqual(uvF, Precision::PConfusion())) - aEAttr.FirstUV = uvF; - - if (!aEAttr.LastUV.IsEqual(uvL, Precision::PConfusion())) - aEAttr.LastUV = uvL; - - aEAttr.IsSameUV = - aEAttr.FirstUV.IsEqual(aEAttr.LastUV, Precision::PConfusion()); - } - - //Control tolerance of vertices - const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface(); - gp_Pnt pFirst = gFace->Value(aEAttr.FirstUV.X(), aEAttr.FirstUV.Y()); - gp_Pnt pLast = gFace->Value(aEAttr.LastUV.X(), aEAttr.LastUV.Y()); - - Standard_Real aSqDist = pFirst.SquareDistance(BRep_Tool::Pnt(aEAttr.FirstVertex)); - aSqDist = Max(aSqDist, pLast.SquareDistance(BRep_Tool::Pnt(aEAttr.LastVertex))); - - aEAttr.Deflection = Max(theDefEdge, BRep_Tool::Tolerance(theEdge)); - aEAttr.Deflection = Max(aEAttr.Deflection, sqrt(aSqDist)); - - return Standard_True; -} - -//======================================================================= -//function : registerEdgeVertices -//purpose : -//======================================================================= -void BRepMesh_FastDiscret::registerEdgeVertices( - BRepMesh_FastDiscret::EdgeAttributes& theAttributes, - Standard_Integer& ipf, - Standard_Integer& ivf, - Standard_Integer& isvf, - Standard_Integer& ipl, - Standard_Integer& ivl, - Standard_Integer& isvl) -{ - EdgeAttributes& aEAttr = theAttributes; - if (aEAttr.FirstVExtractor.IsNull()) - { - // Use edge geometry to produce tesselation. - aEAttr.FirstVExtractor = - new TopoDSVExplorer(aEAttr.FirstVertex, aEAttr.IsSameUV, aEAttr.LastVertex); - } - - if (aEAttr.LastVExtractor.IsNull()) - { - // Use edge geometry to produce tesselation. - aEAttr.LastVExtractor = - new TopoDSVExplorer(aEAttr.LastVertex, aEAttr.IsSameUV, aEAttr.FirstVertex); - } - - // Process first vertex - ipf = myAttribute->GetVertexIndex(aEAttr.FirstVExtractor, Standard_True); - Standard_Real aMinDist = 2. * BRep_Tool::Tolerance(aEAttr.FirstVertex); - gp_XY aTmpUV1 = BRepMesh_ShapeTool::FindUV(ipf, aEAttr.FirstUV, aMinDist, myAttribute); - - myAttribute->AddNode(ipf, aTmpUV1, BRepMesh_Frontier, ivf, isvf); - - // Process last vertex - ipl = aEAttr.LastVertex.IsSame(aEAttr.FirstVertex) ? ipf : - myAttribute->GetVertexIndex(aEAttr.LastVExtractor, Standard_True); - aMinDist = 2. * BRep_Tool::Tolerance(aEAttr.LastVertex); - gp_XY aTmpUV2 = BRepMesh_ShapeTool::FindUV(ipl, aEAttr.LastUV, aMinDist, myAttribute); - - myAttribute->AddNode(ipl, aTmpUV2, BRepMesh_Frontier, ivl, isvl); - - // Update edge deflection - const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface(); - gp_Pnt aPntE1 = gFace->Value(aEAttr.FirstUV.X(), aEAttr.FirstUV.Y()); - gp_Pnt aPntFound1 = gFace->Value(aTmpUV1.X(), aTmpUV1.Y()); - Standard_Real aSqDist = aPntE1.SquareDistance(aPntFound1); - gp_Pnt aPntE2 = gFace->Value(aEAttr.LastUV.X(), aEAttr.LastUV.Y()); - gp_Pnt aPntFound2 = gFace->Value(aTmpUV2.X(), aTmpUV2.Y()); - aSqDist = Max(aSqDist, aPntE2.SquareDistance(aPntFound2)); - aEAttr.Deflection = Max(aEAttr.Deflection, sqrt(aSqDist)); -} - -//======================================================================= -//function : add -//purpose : -//======================================================================= -void BRepMesh_FastDiscret::add( - const TopoDS_Edge& theEdge, - const Handle(Geom2dAdaptor_HCurve)& thePCurve, - const Standard_Real theDefEdge) -{ - const TopAbs_Orientation orEdge = theEdge.Orientation(); - if (orEdge == TopAbs_EXTERNAL) - return; - - EdgeAttributes aEAttr; - if (!getEdgeAttributes(theEdge, thePCurve, theDefEdge, aEAttr)) - return; - - if (!myEdges.IsBound(theEdge)) - { - update(theEdge, thePCurve, theDefEdge, aEAttr); - return; - } - - Standard_Integer ipf, ivf, isvf, ipl, ivl, isvl; - registerEdgeVertices(aEAttr, ipf, ivf, isvf, ipl, ivl, isvl); - - // If this Edge has been already checked and it is not degenerated, - // the points of the polygon calculated at the first check are retrieved : - - // retrieve the polygone: - const BRepMesh_PairOfPolygon& aPair = myEdges.Find(theEdge); - const Handle(Poly_PolygonOnTriangulation)& aPolygon = aPair.First(); - const TColStd_Array1OfInteger& aNodes = aPolygon->Nodes(); - Handle(TColStd_HArray1OfReal) aParams = aPolygon->Parameters(); - - // creation anew: - const Standard_Integer aNodesNb = aNodes.Length(); - TColStd_Array1OfInteger aNewNodes (1, aNodesNb); - TColStd_Array1OfReal aNewParams(1, aNodesNb); - - aNewNodes (1) = isvf; - aNewParams(1) = aEAttr.FirstParam; - - aNewNodes (aNodesNb) = isvl; - aNewParams(aNodesNb) = aEAttr.LastParam; - - const TopoDS_Face& aFace = myAttribute->Face(); - if (!BRepMesh_ShapeTool::IsDegenerated(theEdge, aFace)) - { - BRepMesh_EdgeParameterProvider aProvider(theEdge, aFace, aParams); - for (Standard_Integer i = 2; i < aNodesNb; ++i) - { - const Standard_Integer aPointId = aNodes(i); - const gp_Pnt& aPnt = myBoundaryPoints->Find(aPointId); - - const Standard_Real aParam = aProvider.Parameter(i, aPnt); - gp_Pnt2d aUV = thePCurve->Value(aParam); - - Standard_Integer iv2, isv; - myAttribute->AddNode(aPointId, aUV.Coord(), BRepMesh_OnCurve, iv2, isv); - - aNewNodes (i) = isv; - aNewParams(i) = aParam; - } - } - - Handle(Poly_PolygonOnTriangulation) P1 = - new Poly_PolygonOnTriangulation(aNewNodes, aNewParams); - - storePolygon(theEdge, P1, aEAttr.Deflection); -} - -//======================================================================= -//function : update(edge) -//purpose : -//======================================================================= -void BRepMesh_FastDiscret::update( - const TopoDS_Edge& theEdge, - const Handle(Geom2dAdaptor_HCurve)& theC2d, - const Standard_Real theDefEdge, - BRepMesh_FastDiscret::EdgeAttributes& theAttributes) -{ - EdgeAttributes& aEAttr = theAttributes; - - const TopoDS_Face& aFace = myAttribute->Face(); - Handle(BRepMesh_IEdgeTool) aEdgeTool; - // Try to find existing tessellation. - for (Standard_Integer i = 1; aEdgeTool.IsNull(); ++i) - { - TopLoc_Location aLoc; - Handle(Poly_Triangulation) aTriangulation; - Handle(Poly_PolygonOnTriangulation) aPolygon; - BRep_Tool::PolygonOnTriangulation(theEdge, aPolygon, aTriangulation, aLoc, i); - - if (aPolygon.IsNull()) - break; - - if (aTriangulation.IsNull() || !aPolygon->HasParameters()) - continue; - - if (aPolygon->Deflection() > 1.1 * theDefEdge) - continue; - - const TColgp_Array1OfPnt& aNodes = aTriangulation->Nodes(); - const TColStd_Array1OfInteger& aIndices = aPolygon->Nodes(); - Handle(TColStd_HArray1OfReal) aParams = aPolygon->Parameters(); - - aEAttr.FirstVExtractor = new PolyVExplorer(aEAttr.FirstVertex, - aEAttr.IsSameUV, aEAttr.LastVertex, aIndices(1), aNodes, aLoc); - - aEAttr.LastVExtractor = new PolyVExplorer(aEAttr.LastVertex, - aEAttr.IsSameUV, aEAttr.FirstVertex, aIndices(aIndices.Length()), aNodes, aLoc); - - aEdgeTool = new BRepMesh_EdgeTessellationExtractor(theEdge, theC2d, - aFace, aTriangulation, aPolygon, aLoc); - } - - if (aEdgeTool.IsNull()) - { - aEdgeTool = new BRepMesh_EdgeTessellator(theEdge, myAttribute, - mySharedFaces, theDefEdge, myParameters.Angle, myParameters.MinSize); - } - - Standard_Integer ipf, ivf, isvf, ipl, ivl, isvl; - registerEdgeVertices(aEAttr, ipf, ivf, isvf, ipl, ivl, isvl); - - Handle(Poly_PolygonOnTriangulation) P1, P2; - if (BRepMesh_ShapeTool::IsDegenerated(theEdge, aFace)) - { - // two nodes - Standard_Integer aNewNodesArr[] = {isvf, isvl}; - Standard_Integer aNewNodInStructArr[] = {ipf, ipl}; - Standard_Real aNewParamsArr[] = {aEAttr.FirstParam, aEAttr.LastParam}; - TColStd_Array1OfInteger aNewNodes (aNewNodesArr[0], 1, 2); - TColStd_Array1OfInteger aNewNodInStruct(aNewNodInStructArr[0], 1, 2); - TColStd_Array1OfReal aNewParams (aNewParamsArr[0], 1, 2); - - P1 = new Poly_PolygonOnTriangulation(aNewNodes, aNewParams); - P2 = new Poly_PolygonOnTriangulation(aNewNodInStruct, aNewParams); - } - else - { - const Standard_Integer aNodesNb = aEdgeTool->NbPoints(); - // Allocate the memory for arrays aNewNodesVec, aNewNodesInStructVec, aNewParamsVec - // only once using the buffer aBuf. - TColStd_Array1OfCharacter aBuf(1, aNodesNb * (2*sizeof(Standard_Integer) + sizeof(Standard_Real))); - TColStd_Array1OfInteger aNewNodesVec(*reinterpret_cast - (&aBuf(1)), 1, aNodesNb); - TColStd_Array1OfInteger aNewNodesInStructVec(*reinterpret_cast - (&aBuf(1 + aNodesNb*sizeof(Standard_Integer))), 1, aNodesNb); - TColStd_Array1OfReal aNewParamsVec(*reinterpret_cast - (&aBuf(1 + aNodesNb*2*sizeof(Standard_Integer))), 1, aNodesNb); - - Standard_Integer aNodesCount = 1; - aNewNodesInStructVec(aNodesCount) = ipf; - aNewNodesVec (aNodesCount) = isvf; - aNewParamsVec (aNodesCount) = aEAttr.FirstParam; - - ++aNodesCount; - Standard_Integer aPrevNodeId = ivf; - Standard_Integer aLastPointId = myAttribute->LastPointId(); - for (Standard_Integer i = 2; i < aNodesNb; ++i) - { - gp_Pnt aPnt; - gp_Pnt2d aUV; - Standard_Real aParam; - if (!aEdgeTool->Value(i, aParam, aPnt, aUV)) - continue; - - // Imitate index of 3d point in order to not to add points to map without necessity. - Standard_Integer iv2, isv; - myAttribute->AddNode(aLastPointId + 1, aUV.Coord(), BRepMesh_Frontier, iv2, isv); - if (aPrevNodeId == iv2) - continue; - - // Ok, now we can add point to the map. - myBoundaryPoints->Bind (++aLastPointId, aPnt); - - aNewNodesInStructVec(aNodesCount) = aLastPointId; - aNewNodesVec (aNodesCount) = isv; - aNewParamsVec (aNodesCount) = aParam; - - ++aNodesCount; - aPrevNodeId = iv2; - } - - aNewNodesInStructVec(aNodesCount) = ipl; - aNewNodesVec (aNodesCount) = isvl; - aNewParamsVec (aNodesCount) = aEAttr.LastParam; - - TColStd_Array1OfInteger aNewNodes (aNewNodesVec.First (), 1, aNodesCount); - TColStd_Array1OfInteger aNewNodInStruct(aNewNodesInStructVec.First(), 1, aNodesCount); - TColStd_Array1OfReal aNewParams (aNewParamsVec.First(), 1, aNodesCount); - - P1 = new Poly_PolygonOnTriangulation(aNewNodes, aNewParams); - P2 = new Poly_PolygonOnTriangulation(aNewNodInStruct, aNewParams); - } - - storePolygon(theEdge, P1, aEAttr.Deflection); - storePolygonSharedData(theEdge, P2, aEAttr.Deflection); -} - -//======================================================================= -//function : storeInternalPolygon -//purpose : -//======================================================================= -void BRepMesh_FastDiscret::storePolygon( - const TopoDS_Edge& theEdge, - Handle(Poly_PolygonOnTriangulation)& thePolygon, - const Standard_Real theDeflection) -{ - thePolygon->Deflection(theDeflection); - BRepMesh::HDMapOfShapePairOfPolygon& aInternalEdges = myAttribute->ChangeInternalEdges(); - if (aInternalEdges->IsBound(theEdge)) - { - BRepMesh_PairOfPolygon& aPair = aInternalEdges->ChangeFind(theEdge); - if (theEdge.Orientation() == TopAbs_REVERSED) - aPair.Append(thePolygon); - else - aPair.Prepend(thePolygon); - - return; - } - - BRepMesh_PairOfPolygon aPair; - aPair.Append(thePolygon); - aInternalEdges->Bind(theEdge, aPair); -} - -//======================================================================= -//function : storePolygonSharedData -//purpose : -//======================================================================= -void BRepMesh_FastDiscret::storePolygonSharedData( - const TopoDS_Edge& theEdge, - Handle(Poly_PolygonOnTriangulation)& thePolygon, - const Standard_Real theDeflection) -{ - thePolygon->Deflection(theDeflection); - BRepMesh_PairOfPolygon aPair; - aPair.Append(thePolygon); - myEdges.Bind(theEdge, aPair); -} - -//======================================================================= -//function : GetFaceAttribute -//purpose : -//======================================================================= -Standard_Boolean BRepMesh_FastDiscret::GetFaceAttribute( - const TopoDS_Face& theFace, - Handle(BRepMesh_FaceAttribute)& theAttribute, - const Standard_Boolean isForceCreate) const -{ - if (myAttributes.IsBound(theFace)) - { - theAttribute = myAttributes(theFace); - return Standard_True; - } - else if (isForceCreate) - { - theAttribute = new BRepMesh_FaceAttribute(myBoundaryVertices, myBoundaryPoints); - myAttributes.Bind(theFace, theAttribute); - } - - return Standard_False; -} - -//======================================================================= -//function : RemoveFaceAttribute -//purpose : -//======================================================================= -void BRepMesh_FastDiscret::RemoveFaceAttribute(const TopoDS_Face& theFace) -{ - if (myAttributes.IsBound(theFace)) - myAttributes.UnBind(theFace); -} diff --git a/src/BRepMesh/BRepMesh_FastDiscret.hxx b/src/BRepMesh/BRepMesh_FastDiscret.hxx index 87cc55587d..c21e20a753 100644 --- a/src/BRepMesh/BRepMesh_FastDiscret.hxx +++ b/src/BRepMesh/BRepMesh_FastDiscret.hxx @@ -14,358 +14,13 @@ #ifndef _BRepMesh_FastDiscret_HeaderFile #define _BRepMesh_FastDiscret_HeaderFile -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include -class BRepMesh_DataStructureOfDelaun; -class Bnd_Box; -class TopoDS_Shape; -class TopoDS_Face; -class TopoDS_Edge; -class Geom2dAdaptor_HCurve; -class BRepAdaptor_HSurface; -class BRepMesh_Edge; -class BRepMesh_Vertex; -class gp_Pnt; -class BRepMesh_FaceAttribute; -class Message_ProgressSentry; - -//! Algorithm to mesh a shape with respect of the
-//! frontier the deflection and by option the shared
-//! components.
-class BRepMesh_FastDiscret : public Standard_Transient +class Standard_DEPRECATED("The class BRepMesh_FastDiscret is deprecated. Please use IMeshTools package") BRepMesh_FastDiscret { public: - - - //! Structure storing meshing parameters - struct Parameters { - - //! Default constructor - Parameters() - : - Angle(0.1), - Deflection(0.001), - MinSize(Precision::Confusion()), - InParallel(Standard_False), - Relative(Standard_False), - AdaptiveMin(Standard_False), - InternalVerticesMode(Standard_True), - ControlSurfaceDeflection(Standard_True) - { - } - - //! Angular deflection - Standard_Real Angle; - - //! Deflection - Standard_Real Deflection; - - //! Minimal allowed size of mesh element - Standard_Real MinSize; - - //! Switches on/off multy thread computation - Standard_Boolean InParallel; - - //! Switches on/off relative computation of edge tolerance
- //! If trur, deflection used for the polygonalisation of each edge will be - //! * Size of Edge. The deflection used for the faces will be the - //! maximum deflection of their edges. - Standard_Boolean Relative; - - //! Adaptive parametric tolerance flag.
- //! If this flag is set to true the minimal parametric tolerance - //! is computed taking minimal parametric distance between vertices - //! into account - Standard_Boolean AdaptiveMin; - - //! Mode to take or ont to take internal face vertices into account - //! in triangulation process - Standard_Boolean InternalVerticesMode; - - //! Prameter to check the deviation of triangulation and interior of - //! the face - Standard_Boolean ControlSurfaceDeflection; - }; - -public: - - - //! Constructor. - //! Sets the meshing parameters and updates - //! relative defletion according to bounding box - //! @param B - bounding box encompasing shape - //! @param theParams - meshing algo parameters - Standard_EXPORT BRepMesh_FastDiscret (const Bnd_Box& B, - const Parameters& theParams); - - //! Build triangulation on the whole shape. - Standard_EXPORT void Perform(const TopoDS_Shape& shape); - - //! Record a face for further processing. - //! @return status flags collected during discretization - //! of boundaries of the given face. - Standard_EXPORT Standard_Integer Add(const TopoDS_Face& face); - - //! Triangulate a face previously recorded for - //! processing by call to Add(). Can be executed in - //! parallel threads. - Standard_EXPORT void Process(const TopoDS_Face& face) const; - - //! Triangulate a face previously recorded for - //! processing by call to Add(). Can be executed in - //! parallel threads. - Standard_EXPORT void Process (const TopoDS_Face& theFace, - Message_ProgressSentry* theProgrEntry) const; - - void operator () (const TopoDS_Face& face) const - { - Process(face); - } - - //! Returns parameters of meshing - inline const Parameters& MeshParameters() const - { - return myParameters; - } - - //! Returns modificable mesh parameters - inline Parameters& ChangeMeshParameters() - { - return myParameters; - } - - - Standard_EXPORT void InitSharedFaces(const TopoDS_Shape& theShape); - - inline const TopTools_IndexedDataMapOfShapeListOfShape& SharedFaces() const - { - return mySharedFaces; - } - - //! Returns attribute descriptor for the given face. - //! @param theFace face the attribute should be returned for. - //! @param[out] theAttribute attribute found for the specified face. - //! @param isForceCreate if True creates new attribute in case if there - //! is no data for the given face. - Standard_EXPORT Standard_Boolean GetFaceAttribute ( - const TopoDS_Face& theFace, - Handle(BRepMesh_FaceAttribute)& theAttribute, - const Standard_Boolean isForceCreate = Standard_False) const; - - //! Remove face attribute as useless to free locate memory. - Standard_EXPORT void RemoveFaceAttribute( const TopoDS_Face& theFace ); - - //! Returns number of boundary 3d points. - inline Standard_Integer NbBoundaryPoints() const - { - return myBoundaryPoints->Extent(); - } - - DEFINE_STANDARD_RTTIEXT(BRepMesh_FastDiscret,Standard_Transient) - -private: - - //! Auxiliary class used to extract geometrical parameters of TopoDS_Vertex. - class TopoDSVExplorer - { - public: - TopoDSVExplorer( - const TopoDS_Vertex& theVertex, - const Standard_Boolean isSameUV, - const TopoDS_Vertex& theSameVertex) - : myVertex(theVertex), - myIsSameUV(isSameUV), - mySameVertex(theSameVertex) - { - } - virtual ~TopoDSVExplorer() { - } - const TopoDS_Vertex& Vertex() const - { - return myVertex; - } - - Standard_Boolean IsSameUV() const - { - return myIsSameUV; - } - - const TopoDS_Vertex& SameVertex() const - { - return mySameVertex; - } - - virtual gp_Pnt Point() const - { - return BRep_Tool::Pnt(myVertex); - } - - private: - - void operator =(const TopoDSVExplorer& /*theOther*/) - { - } - - private: - const TopoDS_Vertex& myVertex; - Standard_Boolean myIsSameUV; - const TopoDS_Vertex& mySameVertex; - }; - - - //! Auxiliary class used to extract polygonal parameters of TopoDS_Vertex. - class PolyVExplorer : public TopoDSVExplorer - { - public: - PolyVExplorer( - const TopoDS_Vertex& theVertex, - const Standard_Boolean isSameUV, - const TopoDS_Vertex& theSameVertex, - const Standard_Integer theVertexIndex, - const TColgp_Array1OfPnt& thePolygon, - const TopLoc_Location& theLoc) - : TopoDSVExplorer(theVertex, isSameUV, theSameVertex), - myVertexIndex(theVertexIndex), - myPolygon(thePolygon), - myLoc(theLoc) - { - } - - virtual gp_Pnt Point() const - { - return BRepMesh_ShapeTool::UseLocation(myPolygon(myVertexIndex), myLoc); - } - - private: - - void operator =(const PolyVExplorer& /*theOther*/) - { - } - - private: - Standard_Integer myVertexIndex; - const TColgp_Array1OfPnt& myPolygon; - const TopLoc_Location myLoc; - }; - - //! Structure keeps common parameters of edge - //! used for tessellation. - struct EdgeAttributes - { - TopoDS_Vertex FirstVertex; - TopoDS_Vertex LastVertex; - - Standard_Real FirstParam; - Standard_Real LastParam; - - gp_Pnt2d FirstUV; - gp_Pnt2d LastUV; - - Standard_Real Deflection; - Standard_Boolean IsSameUV; - - NCollection_Handle FirstVExtractor; - NCollection_Handle LastVExtractor; - }; - - //! Fills structure of by attributes of the given edge. - //! @return TRUE on success, FALSE elsewhere. - Standard_Boolean getEdgeAttributes( - const TopoDS_Edge& theEdge, - const Handle(Geom2dAdaptor_HCurve)& thePCurve, - const Standard_Real theDefEdge, - EdgeAttributes& theAttributes) const; - - //! Registers end vertices of the edge in mesh data - //! structure of currently processed face. - void registerEdgeVertices( - EdgeAttributes& theAttributes, - Standard_Integer& ipf, - Standard_Integer& ivf, - Standard_Integer& isvf, - Standard_Integer& ipl, - Standard_Integer& ivl, - Standard_Integer& isvl); - - //! Adds tessellated representation of the given edge to - //! mesh data structure of currently processed face. - void add(const TopoDS_Edge& theEdge, - const Handle(Geom2dAdaptor_HCurve)& theCurve2D, - const Standard_Real theEdgeDeflection); - - //! Updates tessellated representation of the given edge. - //! If edge already has a polygon which deflection satisfies - //! the given value, retrieves tessellation from polygon. - //! Computes tessellation using edge's geometry elsewhere. - void update( - const TopoDS_Edge& theEdge, - const Handle(Geom2dAdaptor_HCurve)& theCurve2D, - const Standard_Real theEdgeDeflection, - EdgeAttributes& theAttributes); - - //! Stores polygonal model of the given edge. - //! @param theEdge edge which polygonal model is stored. - //! @param thePolygon polygonal model of the edge. - //! @param theDeflection deflection with which polygonalization is performed. - //! This value is stored inside the polygon. - void storePolygon( - const TopoDS_Edge& theEdge, - Handle(Poly_PolygonOnTriangulation)& thePolygon, - const Standard_Real theDeflection); - - //! Caches polygonal model of the given edge to be used in further. - //! @param theEdge edge which polygonal data is stored. - //! @param thePolygon shared polygonal data of the edge. - //! @param theDeflection deflection with which polygonalization is performed. - //! This value is stored inside the polygon. - void storePolygonSharedData( - const TopoDS_Edge& theEdge, - Handle(Poly_PolygonOnTriangulation)& thePolygon, - const Standard_Real theDeflection); - - //! Resets temporary data structure used to collect unique nodes. - void resetDataStructure(); - -private: - - TopoDS_Face myFace; - - BRepMesh::DMapOfShapePairOfPolygon myEdges; - mutable BRepMesh::DMapOfFaceAttribute myAttributes; - TopTools_DataMapOfShapeReal myMapdefle; - - // Data shared for whole shape - BRepMesh::HDMapOfVertexInteger myBoundaryVertices; - BRepMesh::HDMapOfIntegerPnt myBoundaryPoints; - - // Fast access to attributes of current face - Handle(BRepMesh_FaceAttribute) myAttribute; - TopTools_IndexedDataMapOfShapeListOfShape mySharedFaces; - - Parameters myParameters; - - Standard_Real myDtotale; + Standard_DEPRECATED("The class BRepMesh_FastDiscret is deprecated. Please use IMeshTools package") + typedef IMeshTools_Parameters Parameters; }; -DEFINE_STANDARD_HANDLE(BRepMesh_FastDiscret, Standard_Transient) - #endif diff --git a/src/BRepMesh/BRepMesh_FastDiscretFace.cxx b/src/BRepMesh/BRepMesh_FastDiscretFace.cxx deleted file mode 100644 index ed13287b4a..0000000000 --- a/src/BRepMesh/BRepMesh_FastDiscretFace.cxx +++ /dev/null @@ -1,1585 +0,0 @@ -// Created by: Ekaterina SMIRNOVA -// Copyright (c) 2008-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 - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include - -//#define DEBUG_MESH "mesh.tcl" -#ifdef DEBUG_MESH -#include -#endif - - -IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_FastDiscretFace,Standard_Transient) - -static Standard_Real FUN_CalcAverageDUV(TColStd_Array1OfReal& P, const Standard_Integer PLen) -{ - Standard_Integer i, j, n = 0; - Standard_Real p, result = 0.; - - for(i = 1; i <= PLen; i++) - { - // Sort - for(j = i + 1; j <= PLen; j++) - { - if(P(i) > P(j)) - { - p = P(i); - P(i) = P(j); - P(j) = p; - } - } - // Accumulate - if (i != 1) - { - p = Abs(P(i) - P(i-1)); - if(p > 1.e-7) - { - result += p; - n++; - } - } - } - return (n? (result / (Standard_Real) n) : -1.); -} - -namespace -{ - Standard_Real deflectionOfSegment ( - const gp_Pnt& theFirstPoint, - const gp_Pnt& theLastPoint, - const gp_Pnt& theMidPoint) - { - // 23.03.2010 skl for OCC21645 - change precision for comparison - if (theFirstPoint.SquareDistance (theLastPoint) > Precision::SquareConfusion ()) - { - gp_Lin aLin (theFirstPoint, gp_Dir (gp_Vec (theFirstPoint, theLastPoint))); - return aLin.Distance (theMidPoint); - } - - return theFirstPoint.Distance (theMidPoint); - } - - Standard_Boolean IsCompexSurface (const GeomAbs_SurfaceType theType) - { - return ( - theType != GeomAbs_Sphere && - theType != GeomAbs_Cylinder && - theType != GeomAbs_Cone && - theType != GeomAbs_Torus); - } - - //! Auxiliary class used to extract geometrical parameters of fixed TopoDS_Vertex. - class FixedVExplorer - { - public: - - DEFINE_STANDARD_ALLOC - - FixedVExplorer(const TopoDS_Vertex& theVertex) - : myVertex(theVertex) - { - } - - const TopoDS_Vertex& Vertex() const - { - return myVertex; - } - - Standard_Boolean IsSameUV() const - { - return Standard_False; - } - - TopoDS_Vertex SameVertex() const - { - return TopoDS_Vertex(); - } - - gp_Pnt Point() const - { - return BRep_Tool::Pnt(myVertex); - } - - private: - - void operator =(const FixedVExplorer& /*theOther*/) - { - } - - private: - const TopoDS_Vertex& myVertex; - }; -} - - -//======================================================================= -//function : BRepMesh_FastDiscretFace -//purpose : -//======================================================================= -BRepMesh_FastDiscretFace::BRepMesh_FastDiscretFace( - const Standard_Real theAngle, - const Standard_Real theMinSize, - const Standard_Boolean isInternalVerticesMode, - const Standard_Boolean isControlSurfaceDeflection) -: myAngle(theAngle), - myInternalVerticesMode(isInternalVerticesMode), - myMinSize(theMinSize), - myIsControlSurfaceDeflection(isControlSurfaceDeflection) -{ -} - -//======================================================================= -//function : Perform -//purpose : -//======================================================================= -void BRepMesh_FastDiscretFace::Perform(const Handle(BRepMesh_FaceAttribute)& theAttribute) -{ - Perform (theAttribute, NULL); -} - -//======================================================================= -//function : Perform -//purpose : -//======================================================================= -void BRepMesh_FastDiscretFace::Perform (const Handle(BRepMesh_FaceAttribute)& theAttribute, - Message_ProgressSentry* theProgressEntry) -{ - add(theAttribute, theProgressEntry); - if (theProgressEntry != NULL && !theProgressEntry->More()) - { - return; - } - commitSurfaceTriangulation(); -} - -//======================================================================= -//function : initDataStructure -//purpose : -//======================================================================= -void BRepMesh_FastDiscretFace::initDataStructure() -{ - const Standard_Real aTolU = myAttribute->ToleranceU(); - const Standard_Real aTolV = myAttribute->ToleranceV(); - const Standard_Real uCellSize = 14.0 * aTolU; - const Standard_Real vCellSize = 14.0 * aTolV; - - const Standard_Real deltaX = myAttribute->GetDeltaX(); - const Standard_Real deltaY = myAttribute->GetDeltaY(); - - Handle(NCollection_IncAllocator) aAllocator = - new NCollection_IncAllocator(BRepMesh::MEMORY_BLOCK_SIZE_HUGE); - myStructure = new BRepMesh_DataStructureOfDelaun(aAllocator); - myStructure->Data()->SetCellSize ( uCellSize / deltaX, vCellSize / deltaY); - myStructure->Data()->SetTolerance( aTolU / deltaX, aTolV / deltaY); - - myAttribute->ChangeStructure() = myStructure; - myAttribute->ChangeSurfacePoints() = new BRepMesh::DMapOfIntegerPnt(1, aAllocator); - myAttribute->ChangeSurfaceVertices()= new BRepMesh::DMapOfVertexInteger(1, aAllocator); - - // Check the necessity to fill the map of parameters - const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface(); - GeomAbs_SurfaceType thetype = gFace->GetType(); - const Standard_Boolean isBSpline = (thetype == GeomAbs_BezierSurface || - thetype == GeomAbs_BSplineSurface); - const Standard_Boolean useUVParam = (thetype == GeomAbs_Torus || IsCompexSurface (thetype)); - - Handle(NCollection_BaseAllocator) aBaseAlloc = aAllocator; - myUParam.Clear (aBaseAlloc); - myVParam.Clear (aBaseAlloc); - - // essai de determination de la longueur vraie: - // akm (bug OCC16) : We must calculate these measures in non-singular - // parts of face. Let`s try to compute average value of three - // (umin, (umin+umax)/2, umax), and respectively for v. - // vvvvv - //Standard_Real longu = 0.0, longv = 0.0; //, last , first; - //gp_Pnt P11, P12, P21, P22, P31, P32; - BRepMesh::HVectorOfVertex& aBoundaryNodes = myAttribute->ChangeMeshNodes(); - BRepMesh::VectorOfVertex::Iterator aNodesIt(*aBoundaryNodes); - for (; aNodesIt.More(); aNodesIt.Next()) - { - BRepMesh_Vertex& aNode = aNodesIt.ChangeValue(); - gp_XY aPnt2d = aNode.Coord(); - - if (useUVParam) - { - myUParam.Add(aPnt2d.X()); - myVParam.Add(aPnt2d.Y()); - } - - aNode.ChangeCoord() = myAttribute->Scale(aPnt2d, Standard_True); - myStructure->AddNode(aNode, Standard_True); - } - aBoundaryNodes.Nullify(); - - if (isBSpline) - { - const Standard_Real aRange[2][2] = { - {myAttribute->GetUMin(), myAttribute->GetUMax()}, - {myAttribute->GetVMin(), myAttribute->GetVMax()} - }; - - const GeomAbs_Shape aContinuity = GeomAbs_CN; - for (Standard_Integer i = 0; i < 2; ++i) - { - const Standard_Boolean isU = (i == 0); - const Standard_Integer aIntervalsNb = isU ? - gFace->NbUIntervals(aContinuity) : - gFace->NbVIntervals(aContinuity); - - BRepMesh::IMapOfReal& aParams = isU ? myUParam : myVParam; - if (aIntervalsNb < aParams.Size()) - continue; - - TColStd_Array1OfReal aIntervals(1, aIntervalsNb + 1); - if (isU) - gFace->UIntervals(aIntervals, aContinuity); - else - gFace->VIntervals(aIntervals, aContinuity); - - for (Standard_Integer j = 1; j <= aIntervals.Upper(); ++j) - { - const Standard_Real aParam = aIntervals(j); - if (aParam > aRange[i][0] && aParam < aRange[i][1]) - aParams.Add(aParam); - } - } - } - - //////////////////////////////////////////////////////////// - //add internal vertices after self-intersection check - if ( myInternalVerticesMode ) - { - TopExp_Explorer anExplorer(myAttribute->Face(), TopAbs_VERTEX, TopAbs_EDGE); - for ( ; anExplorer.More(); anExplorer.Next() ) - add(TopoDS::Vertex(anExplorer.Current())); - } - - const BRepMesh::HDMapOfShapePairOfPolygon& aEdges = myAttribute->ChangeInternalEdges(); - TopExp_Explorer aWireIt(myAttribute->Face(), TopAbs_WIRE); - for (; aWireIt.More(); aWireIt.Next()) - { - TopExp_Explorer aEdgeIt(aWireIt.Current(), TopAbs_EDGE); - for (; aEdgeIt.More(); aEdgeIt.Next()) - { - const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Current()); - BRepMesh_PairOfPolygon aPair; - if (!aEdges->Find(aEdge, aPair)) - continue; - - TopAbs_Orientation aOri = aEdge.Orientation(); - const Handle(Poly_PolygonOnTriangulation)& aPolygon = - aOri == TopAbs_REVERSED ? aPair.Last() : aPair.First(); - - const TColStd_Array1OfInteger& aIndices = aPolygon->Nodes(); - const Standard_Integer aNodesNb = aPolygon->NbNodes(); - - Standard_Integer aPrevId = aIndices(1); - for (Standard_Integer i = 2; i <= aNodesNb; ++i) - { - const Standard_Integer aCurId = aIndices(i); - addLinkToMesh(aPrevId, aCurId, aOri); - aPrevId = aCurId; - } - } - } -} - -//======================================================================= -//function : addLinkToMesh -//purpose : -//======================================================================= -void BRepMesh_FastDiscretFace::addLinkToMesh( - const Standard_Integer theFirstNodeId, - const Standard_Integer theLastNodeId, - const TopAbs_Orientation theOrientation) -{ - if (theOrientation == TopAbs_FORWARD) - myStructure->AddLink(BRepMesh_Edge(theFirstNodeId, theLastNodeId, BRepMesh_Frontier)); - else if (theOrientation == TopAbs_REVERSED) - myStructure->AddLink(BRepMesh_Edge(theLastNodeId, theFirstNodeId, BRepMesh_Frontier)); - else if (theOrientation == TopAbs_INTERNAL) - myStructure->AddLink(BRepMesh_Edge(theFirstNodeId, theLastNodeId, BRepMesh_Fixed)); -} - -//======================================================================= -//function : Add -//purpose : -//======================================================================= -void BRepMesh_FastDiscretFace::add (const Handle(BRepMesh_FaceAttribute)& theAttribute, - Message_ProgressSentry* theProgressEntry) -{ - if (!theAttribute->IsValid() || theAttribute->ChangeMeshNodes()->IsEmpty()) - return; - - myAttribute = theAttribute; - initDataStructure(); - - BRepMesh::HIMapOfInteger& aVertexEdgeMap = myAttribute->ChangeVertexEdgeMap(); - Standard_Integer nbVertices = aVertexEdgeMap->Extent(); - BRepMesh::Array1OfInteger tabvert_corr(1, nbVertices); - for ( Standard_Integer i = 1; i <= nbVertices; ++i ) - tabvert_corr(i) = i; - - BRepMesh_Delaun trigu(myStructure, tabvert_corr); - - //removed all free edges from triangulation - const Standard_Integer nbLinks = myStructure->NbLinks(); - for( Standard_Integer i = 1; i <= nbLinks; i++ ) - { - if( myStructure->ElementsConnectedTo(i).Extent() < 1 ) - { - BRepMesh_Edge& anEdge = (BRepMesh_Edge&)trigu.GetEdge(i); - if ( anEdge.Movability() == BRepMesh_Deleted ) - continue; - - anEdge.SetMovability(BRepMesh_Free); - myStructure->RemoveLink(i); - } - } - - const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface(); - GeomAbs_SurfaceType thetype = gFace->GetType(); - - Standard_Boolean rajout = - (thetype == GeomAbs_Sphere || thetype == GeomAbs_Torus); - - // Check the necessity to fill the map of parameters - const Standard_Boolean useUVParam = (thetype == GeomAbs_Torus || - thetype == GeomAbs_BezierSurface || - thetype == GeomAbs_BSplineSurface); - - const Standard_Real umax = myAttribute->GetUMax(); - const Standard_Real umin = myAttribute->GetUMin(); - const Standard_Real vmax = myAttribute->GetVMax(); - const Standard_Real vmin = myAttribute->GetVMin(); - - Standard_Boolean isaline = - ((umax - umin) < Precision::PConfusion() || - (vmax - vmin) < Precision::PConfusion()); - - Standard_Real aDef = -1; - if (theProgressEntry != NULL && !theProgressEntry->More()) - { - return; - } - - if ( !isaline && myStructure->ElementsOfDomain().Extent() > 0 ) - { - if (!rajout) - { - // compute maximal deflection - aDef = control(trigu, Standard_True, theProgressEntry); - if (theProgressEntry != NULL && !theProgressEntry->More()) - { - return; - } - - rajout = (aDef > myAttribute->GetDefFace() || aDef < 0.); - } - if (thetype != GeomAbs_Plane) - { - if (!rajout && useUVParam) - { - rajout = (myVParam.Extent() > 2 && - (gFace->IsUClosed() || gFace->IsVClosed())); - } - - if (rajout) - { - insertInternalVertices(trigu, theProgressEntry); - if (theProgressEntry != NULL && !theProgressEntry->More()) - { - return; - } - - //control internal points - if (myIsControlSurfaceDeflection) - { - aDef = control(trigu, Standard_False, theProgressEntry); - if (theProgressEntry != NULL && !theProgressEntry->More()) - { - return; - } - } - } - } - } - - //modify myStructure back - BRepMesh::HVectorOfVertex& aMeshNodes = myStructure->Data()->ChangeVertices(); - for ( Standard_Integer i = 1; i <= myStructure->NbNodes(); ++i ) - { - BRepMesh_Vertex& aNode = aMeshNodes->ChangeValue(i - 1); - aNode.ChangeCoord() = myAttribute->Scale(aNode.Coord(), Standard_False); - - const BRepMesh::ListOfInteger& alist = myStructure->LinksConnectedTo(i); - // Register internal nodes used in triangulation - if (!alist.IsEmpty() && aVertexEdgeMap->FindIndex(i) == 0) - aVertexEdgeMap->Add(i); - } - - if (!(aDef < 0.)) - myAttribute->SetDefFace(aDef); -} - -//======================================================================= -//function : addVerticesToMesh -//purpose : -//======================================================================= -Standard_Boolean BRepMesh_FastDiscretFace::addVerticesToMesh( - const BRepMesh::ListOfVertex& theVertices, - BRepMesh_Delaun& theMeshBuilder, - Message_ProgressSentry* theProgressEntry) -{ - if (theVertices.IsEmpty()) - return Standard_False; - - BRepMesh::Array1OfVertexOfDelaun aArrayOfNewVertices(1, theVertices.Extent()); - BRepMesh::ListOfVertex::Iterator aVertexIt(theVertices); - for (Standard_Integer aVertexId = 0; aVertexIt.More(); aVertexIt.Next()) - aArrayOfNewVertices(++aVertexId) = aVertexIt.Value(); - - theMeshBuilder.AddVertices(aArrayOfNewVertices, theProgressEntry); - return theProgressEntry == NULL || theProgressEntry->More(); -} - -//======================================================================= -//function : filterParameters -//purpose : -//======================================================================= -static void filterParameters(const BRepMesh::IMapOfReal& theParams, - const Standard_Real theMinDist, - const Standard_Real theFilterDist, - BRepMesh::SequenceOfReal& theResult) -{ - // Sort sequence of parameters - const Standard_Integer anInitLen = theParams.Extent(); - - TColStd_Array1OfReal aParamArray(1, anInitLen); - Standard_Integer j; - for (j = 1; j <= anInitLen; j++) - aParamArray(j) = theParams(j); - - std::sort (aParamArray.begin(), aParamArray.end()); - - // mandatory pre-filtering using the first (minimal) filter value - Standard_Integer aParamLength = 1; - for (j = 2; j <= anInitLen; j++) - { - if ((aParamArray(j)-aParamArray(aParamLength)) > theMinDist) - { - if (++aParamLength < j) - aParamArray(aParamLength) = aParamArray(j); - } - } - - //perform filtering on series - Standard_Real aLastAdded, aLastCandidate; - Standard_Boolean isCandidateDefined = Standard_False; - aLastAdded = aParamArray(1); - aLastCandidate = aLastAdded; - theResult.Append(aLastAdded); - - for(j=2; j < aParamLength; j++) - { - Standard_Real aVal = aParamArray(j); - if(aVal-aLastAdded > theFilterDist) - { - //adds the parameter - if(isCandidateDefined) { - aLastAdded = aLastCandidate; - isCandidateDefined = Standard_False; - j--; - } - else - { - aLastAdded = aVal; - } - theResult.Append(aLastAdded); - continue; - } - - aLastCandidate = aVal; - isCandidateDefined = Standard_True; - } - theResult.Append(aParamArray(aParamLength)); -} - -//======================================================================= -//function : insertInternalVertices -//purpose : -//======================================================================= -void BRepMesh_FastDiscretFace::insertInternalVertices (BRepMesh_Delaun& theMeshBuilder, - Message_ProgressSentry* theProgressEntry) -{ - Handle(NCollection_IncAllocator) anAlloc = new NCollection_IncAllocator; - BRepMesh::ListOfVertex aNewVertices(anAlloc); - const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface(); - switch (gFace->GetType()) - { - case GeomAbs_Sphere: - insertInternalVerticesSphere(aNewVertices); - break; - - case GeomAbs_Cylinder: - insertInternalVerticesCylinder(aNewVertices); - break; - - case GeomAbs_Cone: - insertInternalVerticesCone(aNewVertices); - break; - - case GeomAbs_Torus: - insertInternalVerticesTorus(aNewVertices); - break; - - default: - insertInternalVerticesOther(aNewVertices); - break; - } - - addVerticesToMesh(aNewVertices, theMeshBuilder, theProgressEntry); -} - -//======================================================================= -//function : insertInternalVerticesSphere -//purpose : -//======================================================================= -void BRepMesh_FastDiscretFace::insertInternalVerticesSphere( - BRepMesh::ListOfVertex& theNewVertices) -{ - Standard_Real aRange[] = { - myAttribute->GetVMin(), myAttribute->GetVMax(), - myAttribute->GetUMin(), myAttribute->GetUMax() - }; - - gp_Sphere aSphere = myAttribute->Surface()->Sphere(); - - // Calculate parameters for iteration in V direction - Standard_Real aStep = 0.7 * GCPnts_TangentialDeflection::ArcAngularStep( - aSphere.Radius(), myAttribute->GetDefFace(), myAngle, myMinSize); - - Standard_Real aDd[2] = {aStep, aStep}; - Standard_Real aPasMax[2] = {0., 0.}; - for (Standard_Integer i = 0; i < 2; ++i) - { - const Standard_Real aMax = aRange[2 * i + 1]; - const Standard_Real aDiff = aMax - aRange[2 * i + 0]; - aDd[i] = aDiff / ((Standard_Integer)(aDiff / aDd[i]) + 1); - aPasMax[i] = aMax - Precision::PConfusion(); - } - - const Standard_Real aHalfDu = aDd[1] * 0.5; - Standard_Boolean Shift = Standard_False; - Standard_Real aPasV = aRange[0] + aDd[0]; - for (; aPasV < aPasMax[0]; aPasV += aDd[0]) - { - Shift = !Shift; - const Standard_Real d = (Shift) ? aHalfDu : 0.; - Standard_Real aPasU = aRange[2] + d; - for (; aPasU < aPasMax[1]; aPasU += aDd[1]) - { - tryToInsertAnalyticVertex(gp_Pnt2d(aPasU, aPasV), aSphere, theNewVertices); - } - } -} - -//======================================================================= -//function : insertInternalVerticesCylinder -//purpose : -//======================================================================= -void BRepMesh_FastDiscretFace::insertInternalVerticesCylinder( - BRepMesh::ListOfVertex& theNewVertices) -{ - const Standard_Real umax = myAttribute->GetUMax(); - const Standard_Real umin = myAttribute->GetUMin(); - const Standard_Real vmax = myAttribute->GetVMax(); - const Standard_Real vmin = myAttribute->GetVMin(); - - gp_Cylinder aCylinder = myAttribute->Surface()->Cylinder(); - const Standard_Real aRadius = aCylinder.Radius(); - - Standard_Integer nbU = 0; - Standard_Integer nbV = 0; - const Standard_Real su = umax - umin; - const Standard_Real sv = vmax - vmin; - const Standard_Real aArcLen = su * aRadius; - if (aArcLen > myAttribute->GetDefFace ()) - { - // Calculate parameters for iteration in U direction - const Standard_Real Du = GCPnts_TangentialDeflection::ArcAngularStep ( - aRadius, myAttribute->GetDefFace (), myAngle, myMinSize); - nbU = (Standard_Integer)(su / Du); - - // Calculate parameters for iteration in V direction - const Standard_Real aDv = nbU*sv / aArcLen; - // Protection against overflow during casting to int in case - // of long cylinder with small radius. - nbV = aDv > static_cast (IntegerLast ()) ? - 0 : (Standard_Integer)(aDv); - nbV = Min (nbV, 100 * nbU); - } - - const Standard_Real Du = su / (nbU + 1); - const Standard_Real Dv = sv / (nbV + 1); - - Standard_Real pasu, pasv, pasvmax = vmax - Dv*0.5, pasumax = umax - Du*0.5; - for (pasv = vmin + Dv; pasv < pasvmax; pasv += Dv) - { - for (pasu = umin + Du; pasu < pasumax; pasu += Du) - { - tryToInsertAnalyticVertex(gp_Pnt2d(pasu, pasv), aCylinder, theNewVertices); - } - } -} - -//======================================================================= -//function : insertInternalVerticesCone -//purpose : -//======================================================================= -void BRepMesh_FastDiscretFace::insertInternalVerticesCone( - BRepMesh::ListOfVertex& theNewVertices) -{ - const Standard_Real umax = myAttribute->GetUMax(); - const Standard_Real umin = myAttribute->GetUMin(); - const Standard_Real vmax = myAttribute->GetVMax(); - const Standard_Real vmin = myAttribute->GetVMin(); - - gp_Cone aCone = myAttribute->Surface()->Cone(); - Standard_Real RefR = aCone.RefRadius(); - Standard_Real SAng = aCone.SemiAngle(); - Standard_Real aRadius = Max(Abs(RefR + vmin*Sin(SAng)), Abs(RefR + vmax*Sin(SAng))); - - Standard_Real Du = GCPnts_TangentialDeflection::ArcAngularStep( - aRadius, myAttribute->GetDefFace(), myAngle, myMinSize); - - Standard_Real Dv, pasu, pasv; - Standard_Integer nbU = (Standard_Integer)((umax - umin) / Du); - Standard_Integer nbV = (Standard_Integer)(nbU*(vmax - vmin) / ((umax - umin)*aRadius)); - Du = (umax - umin) / (nbU + 1); - Dv = (vmax - vmin) / (nbV + 1); - - Standard_Real pasvmax = vmax - Dv*0.5, pasumax = umax - Du*0.5; - for (pasv = vmin + Dv; pasv < pasvmax; pasv += Dv) - { - for (pasu = umin + Du; pasu < pasumax; pasu += Du) - { - tryToInsertAnalyticVertex(gp_Pnt2d(pasu, pasv), aCone, theNewVertices); - } - } -} - -//======================================================================= -//function : insertInternalVerticesTorus -//purpose : -//======================================================================= -void BRepMesh_FastDiscretFace::insertInternalVerticesTorus( - BRepMesh::ListOfVertex& theNewVertices) -{ - const Standard_Real umax = myAttribute->GetUMax(); - const Standard_Real umin = myAttribute->GetUMin(); - const Standard_Real vmax = myAttribute->GetVMax(); - const Standard_Real vmin = myAttribute->GetVMin(); - const Standard_Real deltaX = myAttribute->GetDeltaX(); - const Standard_Real deltaY = myAttribute->GetDeltaY(); - const Standard_Real aDefFace = myAttribute->GetDefFace(); - - gp_Torus T = myAttribute->Surface()->Torus(); - - Standard_Boolean insert; - Standard_Integer i, j, ParamULength, ParamVLength; - Standard_Real pp, pasu, pasv; - Standard_Real r = T.MinorRadius(), R = T.MajorRadius(); - - BRepMesh::SequenceOfReal ParamU, ParamV; - - Standard_Real oldDv = GCPnts_TangentialDeflection::ArcAngularStep( - r, aDefFace, myAngle, myMinSize); - - Standard_Real Dv = 0.9*oldDv; //TWOTHIRD * oldDv; - Dv = oldDv; - - Standard_Real Du; - Standard_Integer nbV = Max((Standard_Integer)((vmax - vmin) / Dv), 2); - Dv = (vmax - vmin) / (nbV + 1); - Standard_Real ru = R + r; - if (ru > 1.e-16) - { - Du = GCPnts_TangentialDeflection::ArcAngularStep( - ru, aDefFace, myAngle, myMinSize); - - Standard_Real aa = sqrt(Du*Du + oldDv*oldDv); - if (aa < gp::Resolution()) - return; - Du *= Min(oldDv, Du) / aa; - } - else Du = Dv; - - Standard_Integer nbU = Max((Standard_Integer)((umax - umin) / Du), 2); - nbU = Max(nbU, (int)(nbV*(umax - umin)*R / ((vmax - vmin)*r) / 5.)); - Du = (umax - umin) / (nbU + 1); - - if (R < r) - { - // As the points of edges are returned. - // in this case, the points are not representative. - - //-- Choose DeltaX and DeltaY so that to avoid skipping points on the grid - for (i = 0; i <= nbU; i++) ParamU.Append(umin + i* Du); - }//R r - { - //--ofv: U - // Number of mapped U parameters - const Standard_Integer LenU = myUParam.Extent(); - // Fill array of U parameters - TColStd_Array1OfReal Up(1, LenU); - for (j = 1; j <= LenU; j++) Up(j) = myUParam(j); - - // Calculate DU, leave array of parameters - Standard_Real aDU = FUN_CalcAverageDUV(Up, LenU); - aDU = Max(aDU, Abs(umax - umin) / (Standard_Real)nbU / 2.); - Standard_Real dUstd = Abs(umax - umin) / (Standard_Real)LenU; - if (aDU > dUstd) dUstd = aDU; - // Add U parameters - for (j = 1; j <= LenU; j++) - { - pp = Up(j); - insert = Standard_True; - ParamULength = ParamU.Length(); - for (i = 1; i <= ParamULength && insert; i++) - { - insert = (Abs(ParamU.Value(i) - pp) > (0.5*dUstd)); - } - if (insert) ParamU.Append(pp); - } - } - - //--ofv: V - // Number of mapped V parameters - const Standard_Integer LenV = myVParam.Extent(); - // Fill array of V parameters - TColStd_Array1OfReal Vp(1, LenV); - for (j = 1; j <= LenV; j++) Vp(j) = myVParam(j); - // Calculate DV, sort array of parameters - Standard_Real aDV = FUN_CalcAverageDUV(Vp, LenV); - aDV = Max(aDV, Abs(vmax - vmin) / (Standard_Real)nbV / 2.); - - Standard_Real dVstd = Abs(vmax - vmin) / (Standard_Real)LenV; - if (aDV > dVstd) dVstd = aDV; - // Add V parameters - for (j = 1; j <= LenV; j++) - { - pp = Vp(j); - - insert = Standard_True; - ParamVLength = ParamV.Length(); - for (i = 1; i <= ParamVLength && insert; i++) - { - insert = (Abs(ParamV.Value(i) - pp) > (dVstd*2. / 3.)); - } - if (insert) ParamV.Append(pp); - } - - Standard_Integer Lu = ParamU.Length(), Lv = ParamV.Length(); - Standard_Real uminnew = umin + deltaY*0.1; - Standard_Real vminnew = vmin + deltaX*0.1; - Standard_Real umaxnew = umax - deltaY*0.1; - Standard_Real vmaxnew = vmax - deltaX*0.1; - - for (i = 1; i <= Lu; i++) - { - pasu = ParamU.Value(i); - if (pasu >= uminnew && pasu < umaxnew) - { - for (j = 1; j <= Lv; j++) - { - pasv = ParamV.Value(j); - if (pasv >= vminnew && pasv < vmaxnew) - { - tryToInsertAnalyticVertex(gp_Pnt2d(pasu, pasv), T, theNewVertices); - } - } - } - } -} - -//======================================================================= -//function : insertInternalVerticesOther -//purpose : -//======================================================================= -void BRepMesh_FastDiscretFace::insertInternalVerticesOther( - BRepMesh::ListOfVertex& theNewVertices) -{ - const Standard_Real aRange[2][2] = { - { myAttribute->GetUMax(), myAttribute->GetUMin() }, - { myAttribute->GetVMax(), myAttribute->GetVMin() } - }; - - const Standard_Real aDelta[2] = { - myAttribute->GetDeltaX(), - myAttribute->GetDeltaY() - }; - - const Standard_Real aDefFace = myAttribute->GetDefFace(); - const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface(); - - Handle(NCollection_IncAllocator) anAlloc = new NCollection_IncAllocator; - BRepMesh::SequenceOfReal aParams[2] = { BRepMesh::SequenceOfReal(anAlloc), - BRepMesh::SequenceOfReal(anAlloc) }; - for (Standard_Integer i = 0; i < 2; ++i) - { - Standard_Boolean isU = (i == 0); - Standard_Real aRes = isU ? - gFace->UResolution(aDefFace) : - gFace->VResolution(aDefFace); - - // Sort and filter sequence of parameters - Standard_Real aMinDiff = Precision::PConfusion(); - if (aDelta[i] < 1.) - aMinDiff /= aDelta[i]; - - aMinDiff = Max(myMinSize, aMinDiff); - - Standard_Real aRangeDiff = aRange[i][0] - aRange[i][1]; - Standard_Real aDiffMaxLim = 0.1 * aRangeDiff; - Standard_Real aDiffMinLim = Max(0.005 * aRangeDiff, 2. * aRes); - Standard_Real aDiff = Max(myMinSize, Min(aDiffMaxLim, aDiffMinLim)); - filterParameters(isU ? myUParam : myVParam, aMinDiff, aDiff, aParams[i]); - } - - // check intermediate isolines - Handle (Geom_Surface) aSurface = gFace->ChangeSurface ().Surface ().Surface (); - - BRepMesh::MapOfReal aParamsToRemove[2] = { BRepMesh::MapOfReal(1, anAlloc), - BRepMesh::MapOfReal(1, anAlloc) }; - BRepMesh::MapOfReal aParamsForbiddenToRemove[2] = { BRepMesh::MapOfReal(1, anAlloc), - BRepMesh::MapOfReal(1, anAlloc) }; - - // insert additional points where it is needed to conform criteria. - // precision for normals calculation - const Standard_Real aNormPrec = Precision::Confusion(); - for (Standard_Integer k = 0; k < 2; ++k) - { - const Standard_Integer aOtherIndex = (k + 1) % 2; - BRepMesh::SequenceOfReal& aParams1 = aParams[k]; - BRepMesh::SequenceOfReal& aParams2 = aParams[aOtherIndex]; - const Standard_Boolean isU = (k == 0); - for (Standard_Integer i = 2; i < aParams1.Length(); ++i) - { - const Standard_Real aParam1 = aParams1(i); - GeomAdaptor_Curve aIso(isU ? - aSurface->UIso(aParam1) : aSurface->VIso(aParam1)); - - Standard_Real aPrevParam2 = aParams2(1); - gp_Pnt aPrevPnt2; - gp_Vec aPrevVec2; - aIso.D1(aPrevParam2, aPrevPnt2, aPrevVec2); - for (Standard_Integer j = 2; j <= aParams2.Length();) - { - Standard_Real aParam2 = aParams2(j); - gp_Pnt aPnt2; - gp_Vec aVec2; - aIso.D1(aParam2, aPnt2, aVec2); - - Standard_Real aMidParam = 0.5 * (aPrevParam2 + aParam2); - gp_Pnt aMidPnt = aIso.Value(aMidParam); - - Standard_Real aDist = deflectionOfSegment(aPrevPnt2, aPnt2, aMidPnt); - if (aDist > aDefFace && aDist > myMinSize) - { - // insertion - aParams2.InsertBefore(j, aMidParam); - continue; - } - //put regular grig for normals - gp_Pnt2d aStPnt1, aStPnt2; - if (isU) - { - aStPnt1 = gp_Pnt2d(aParam1, aPrevParam2); - aStPnt2 = gp_Pnt2d(aParam1, aMidParam); - } - else - { - aStPnt1 = gp_Pnt2d(aPrevParam2, aParam1); - aStPnt2 = gp_Pnt2d(aMidParam, aParam1); - } - - gp_Dir N1(0, 0, 1), N2(0, 0, 1); - Standard_Integer aSt1 = GeomLib::NormEstim(aSurface, aStPnt1, aNormPrec, N1); - Standard_Integer aSt2 = GeomLib::NormEstim(aSurface, aStPnt2, aNormPrec, N2); - - const Standard_Real aAngle = N2.Angle(N1); - if (aSt1 < 1 && aSt2 < 1 && aAngle > myAngle) - { - const Standard_Real aLen = GCPnts_AbscissaPoint::Length( - aIso, aPrevParam2, aMidParam, aDefFace); - - if (aLen > myMinSize) - { - // insertion - aParams2.InsertBefore(j, aMidParam); - continue; - } - } - aPrevParam2 = aParam2; - aPrevPnt2 = aPnt2; - aPrevVec2 = aVec2; - - ++j; - } - } - } -#ifdef DEBUG_InsertInternal - // output numbers of parameters along U and V - cout << "aParams: " << aParams[0].Length() << " " << aParams[1].Length() << endl; -#endif - // try to reduce number of points evaluating of isolines sampling - for (Standard_Integer k = 0; k < 2; ++k) - { - const Standard_Integer aOtherIndex = (k + 1) % 2; - BRepMesh::SequenceOfReal& aParams1 = aParams[k]; - BRepMesh::SequenceOfReal& aParams2 = aParams[aOtherIndex]; - const Standard_Boolean isU = (k == 0); - BRepMesh::MapOfReal& aToRemove2 = aParamsToRemove[aOtherIndex]; - BRepMesh::MapOfReal& aForbiddenToRemove1 = aParamsForbiddenToRemove[k]; - BRepMesh::MapOfReal& aForbiddenToRemove2 = aParamsForbiddenToRemove[aOtherIndex]; - for (Standard_Integer i = 2; i < aParams1.Length(); ++i) - { - const Standard_Real aParam1 = aParams1(i); - GeomAdaptor_Curve aIso(isU ? - aSurface->UIso (aParam1) : aSurface->VIso (aParam1)); -#ifdef DEBUG_InsertInternal - // write polyline containing initial parameters to the file - { - ofstream ff(DEBUG_InsertInternal, std::ios_base::app); - ff << "polyline " << (k == 0 ? "u" : "v") << i << " "; - for (Standard_Integer j = 1; j <= aParams2.Length(); j++) - { - gp_Pnt aP; - aIso.D0(aParams2(j), aP); - ff << aP.X() << " " << aP.Y() << " " << aP.Z() << " "; - } - ff << endl; - } -#endif - - Standard_Real aPrevParam2 = aParams2(1); - gp_Pnt aPrevPnt2; - gp_Vec aPrevVec2; - aIso.D1 (aPrevParam2, aPrevPnt2, aPrevVec2); - for (Standard_Integer j = 2; j <= aParams2.Length();) - { - Standard_Real aParam2 = aParams2(j); - gp_Pnt aPnt2; - gp_Vec aVec2; - aIso.D1 (aParam2, aPnt2, aVec2); - - // Here we should leave at least 3 parameters as far as - // we must have at least one parameter related to surface - // internals in order to prevent movement of triangle body - // outside the surface in case of highly curved ones, e.g. - // BSpline springs. - if (aParams2.Length() > 3 && j < aParams2.Length()) - { - // Remove too dense points - const Standard_Real aNextParam = aParams2(j + 1); - gp_Pnt aNextPnt; - gp_Vec aNextVec; - aIso.D1(aNextParam, aNextPnt, aNextVec); - - // Lets check current parameter. - // If it fits deflection, we can remove it. - Standard_Real aDist = deflectionOfSegment(aPrevPnt2, aNextPnt, aPnt2); - if (aDist < aDefFace) - { - // Lets check parameters for angular deflection. - if (aPrevVec2.SquareMagnitude() > gp::Resolution() && - aNextVec.SquareMagnitude() > gp::Resolution() && - aPrevVec2.Angle(aNextVec) < myAngle) - { - // For current Iso line we can remove this parameter. -#ifdef DEBUG_InsertInternal - // write point of removed parameter - { - ofstream ff(DEBUG_InsertInternal, std::ios_base::app); - ff << "point " << (k == 0 ? "u" : "v") << i << "r_" << j << " " - << aPnt2.X() << " " << aPnt2.Y() << " " << aPnt2.Z() << endl; - } -#endif - aToRemove2.Add(aParam2); - aPrevParam2 = aNextParam; - aPrevPnt2 = aNextPnt; - aPrevVec2 = aNextVec; - j += 2; - continue; - } - else { - // We have found a place on the surface refusing - // removement of this parameter. -#ifdef DEBUG_InsertInternal - // write point of forbidden to remove parameter - { - ofstream ff(DEBUG_InsertInternal, std::ios_base::app); - ff << "vertex " << (k == 0 ? "u" : "v") << i << "f_" << j << " " - << aPnt2.X() << " " << aPnt2.Y() << " " << aPnt2.Z() << endl; - } -#endif - aForbiddenToRemove1.Add(aParam1); - aForbiddenToRemove2.Add(aParam2); - } - } - } - aPrevParam2 = aParam2; - aPrevPnt2 = aPnt2; - aPrevVec2 = aVec2; - ++j; - } - } - } - // remove filtered out parameters - for (Standard_Integer k = 0; k < 2; ++k) - { - BRepMesh::SequenceOfReal& aParamsk = aParams[k]; - for (Standard_Integer i = 1; i <= aParamsk.Length();) - { - const Standard_Real aParam = aParamsk.Value(i); - if (aParamsToRemove[k].Contains(aParam) && - !aParamsForbiddenToRemove[k].Contains(aParam)) - { - aParamsk.Remove(i); - } - else - i++; - } - } -#ifdef DEBUG_InsertInternal - // write polylines containing remaining parameters - { - ofstream ff(DEBUG_InsertInternal, std::ios_base::app); - for (Standard_Integer k = 0; k < 2; ++k) - { - for (Standard_Integer i = 1; i <= aParams[k].Length(); i++) - { - ff << "polyline " << (k == 0 ? "uo" : "vo") << i << " "; - for (Standard_Integer j = 1; j <= aParams[1 - k].Length(); j++) - { - gp_Pnt aP; - if (k == 0) - gFace->D0(aParams[k](i), aParams[1 - k](j), aP); - else - gFace->D0(aParams[1 - k](j), aParams[k](i), aP); - ff << aP.X() << " " << aP.Y() << " " << aP.Z() << " "; - } - ff << endl; - } - } - } -#endif - - // insert nodes of the regular grid - const BRepMesh::HClassifier& aClassifier = myAttribute->ChangeClassifier(); - for (Standard_Integer i = 1; i <= aParams[0].Length(); ++i) - { - const Standard_Real aParam1 = aParams[0].Value (i); - for (Standard_Integer j = 1; j <= aParams[1].Length(); ++j) - { - const Standard_Real aParam2 = aParams[1].Value (j); - gp_Pnt2d aPnt2d(aParam1, aParam2); - - // Classify intersection point - if (aClassifier->Perform(aPnt2d) == TopAbs_IN) - { - gp_Pnt aPnt; - gFace->D0(aPnt2d.X(), aPnt2d.Y(), aPnt); - insertVertex(aPnt, aPnt2d.Coord(), theNewVertices); - } - } - } -} - -//======================================================================= -//function : checkDeflectionAndInsert -//purpose : -//======================================================================= -Standard_Boolean BRepMesh_FastDiscretFace::checkDeflectionAndInsert( - const gp_Pnt& thePnt3d, - const gp_XY& theUV, - const Standard_Boolean isDeflectionCheckOnly, - const Standard_Real theTriangleDeflection, - const Standard_Real theFaceDeflection, - const BRepMesh_CircleTool& theCircleTool, - BRepMesh::ListOfVertex& theVertices, - Standard_Real& theMaxTriangleDeflection, - const Handle(NCollection_IncAllocator)& theTempAlloc) -{ - if (theTriangleDeflection > theMaxTriangleDeflection) - theMaxTriangleDeflection = theTriangleDeflection; - - if (theTriangleDeflection < theFaceDeflection) - return Standard_True; - - if (myMinSize > Precision::Confusion()) - { - // Iterator in the list of indexes of circles containing the node - BRepMesh::ListOfInteger& aCirclesList = - const_cast(theCircleTool).Select( - myAttribute->Scale(theUV, Standard_True)); - - BRepMesh::MapOfInteger aUsedNodes(10, theTempAlloc); - BRepMesh::ListOfInteger::Iterator aCircleIt(aCirclesList); - for (; aCircleIt.More(); aCircleIt.Next()) - { - const BRepMesh_Triangle& aTriangle = - myStructure->GetElement(aCircleIt.Value()); - - Standard_Integer aNodes[3]; - myStructure->ElementNodes(aTriangle, aNodes); - - for (Standard_Integer i = 0; i < 3; ++i) - { - const Standard_Integer aNodeId = aNodes[i]; - if (aUsedNodes.Contains(aNodeId)) - continue; - - aUsedNodes.Add(aNodeId); - const BRepMesh_Vertex& aNode = myStructure->GetNode(aNodeId); - const gp_Pnt& aPoint = myAttribute->GetPoint(aNode); - - if (thePnt3d.SquareDistance(aPoint) < myMinSize * myMinSize) - return Standard_True; - } - } - } - - if (isDeflectionCheckOnly) - return Standard_False; - - insertVertex(thePnt3d, theUV, theVertices); - return Standard_True; -} - -//======================================================================= -//function : control -//purpose : -//======================================================================= -Standard_Real BRepMesh_FastDiscretFace::control( - BRepMesh_Delaun& theTrigu, - const Standard_Boolean theIsFirst, - Message_ProgressSentry* theProgressEntry) -{ - Standard_Integer aTrianglesNb = myStructure->ElementsOfDomain().Extent(); - if (aTrianglesNb < 1) - return -1.0; - - //IMPORTANT: Constants used in calculations - const Standard_Real MinimalArea2d = 1.e-9; - const Standard_Real MinimalSqLength3d = 1.e-12; - const Standard_Real aSqDefFace = myAttribute->GetDefFace() * myAttribute->GetDefFace(); - - const Handle(BRepAdaptor_HSurface)& gFace = myAttribute->Surface(); - - Handle(Geom_Surface) aBSpline; - const GeomAbs_SurfaceType aSurfType = gFace->GetType (); - if (IsCompexSurface (aSurfType) && aSurfType != GeomAbs_SurfaceOfExtrusion) - aBSpline = gFace->ChangeSurface ().Surface().Surface(); - - Handle(NCollection_IncAllocator) anAlloc = - new NCollection_IncAllocator(BRepMesh::MEMORY_BLOCK_SIZE_HUGE); - NCollection_DataMap aNorMap(1, anAlloc); - BRepMesh::MapOfIntegerInteger aStatMap(1, anAlloc); - NCollection_Map aCouples(3 * aTrianglesNb, anAlloc); - const BRepMesh_CircleTool& aCircles = theTrigu.Circles(); - - // Perform refinement passes - // Define the number of iterations - Standard_Integer aIterationsNb = 11; - const Standard_Integer aPassesNb = (theIsFirst ? 1 : aIterationsNb); - // Initialize stop condition - Standard_Real aMaxSqDef = -1.; - Standard_Integer aPass = 1, aInsertedNb = 1; - Standard_Boolean isAllDegenerated = Standard_False; - Handle(NCollection_IncAllocator) aTempAlloc = - new NCollection_IncAllocator(BRepMesh::MEMORY_BLOCK_SIZE_HUGE); - for (; aPass <= aPassesNb && aInsertedNb && !isAllDegenerated; ++aPass) - { - if (theProgressEntry != NULL && !theProgressEntry->More()) - { - return 0; - } - - aTempAlloc->Reset(Standard_False); - BRepMesh::ListOfVertex aNewVertices(aTempAlloc); - - // Reset stop condition - aInsertedNb = 0; - aMaxSqDef = -1.; - isAllDegenerated = Standard_True; - - aTrianglesNb = myStructure->ElementsOfDomain().Extent(); - if (aTrianglesNb < 1) - break; - - // Iterate on current triangles - const BRepMesh::MapOfInteger& aTriangles = myStructure->ElementsOfDomain(); - BRepMesh::MapOfInteger::Iterator aTriangleIt(aTriangles); - for (; aTriangleIt.More(); aTriangleIt.Next()) - { - if (theProgressEntry != NULL && !theProgressEntry->More()) - { - return 0; - } - - const Standard_Integer aTriangleId = aTriangleIt.Key(); - const BRepMesh_Triangle& aCurrentTriangle = myStructure->GetElement(aTriangleId); - - if (aCurrentTriangle.Movability() == BRepMesh_Deleted) - continue; - - Standard_Integer v[3]; - myStructure->ElementNodes(aCurrentTriangle, v); - - Standard_Integer e[3]; - Standard_Boolean o[3]; - aCurrentTriangle.Edges(e, o); - - gp_XY xy[3]; - gp_XYZ p[3]; - Standard_Boolean m[3]; - for (Standard_Integer i = 0; i < 3; ++i) - { - m[i] = (myStructure->GetLink(e[i]).Movability() == BRepMesh_Frontier); - - const BRepMesh_Vertex& aVertex = myStructure->GetNode(v[i]); - xy[i] = myAttribute->Scale(aVertex.Coord(), Standard_False); - p [i] = myAttribute->GetPoint(aVertex).Coord(); - } - - gp_XYZ aLinkVec[3]; - Standard_Boolean isDegeneratedTri = Standard_False; - for (Standard_Integer i = 0; i < 3 && !isDegeneratedTri; ++i) - { - aLinkVec[i] = p[(i + 1) % 3] - p[i]; - isDegeneratedTri = (aLinkVec[i].SquareModulus() < MinimalSqLength3d); - } - - if (isDegeneratedTri) - continue; - - isAllDegenerated = Standard_False; - - // Check triangle area in 2d - if (Abs((xy[1]-xy[0])^(xy[2]-xy[1])) < MinimalArea2d) - continue; - - // Check triangle normal - gp_Pnt pDef; - Standard_Real aSqDef = -1.; - Standard_Boolean isSkipped = Standard_False; - gp_XYZ normal(aLinkVec[0] ^ aLinkVec[1]); - if (normal.SquareModulus () < gp::Resolution()) - continue; - - normal.Normalize(); - - // Check deflection at triangle centroid - gp_XY aCenter2d = (xy[0] + xy[1] + xy[2]) / 3.0; - gFace->D0(aCenter2d.X(), aCenter2d.Y(), pDef); - aSqDef = Abs(normal * (pDef.XYZ() - p[0])); - aSqDef *= aSqDef; - - isSkipped = !checkDeflectionAndInsert(pDef, aCenter2d, theIsFirst, - aSqDef, aSqDefFace, aCircles, aNewVertices, aMaxSqDef, aTempAlloc); - - if (isSkipped) - break; - - // Check deflection at triangle links - for (Standard_Integer i = 0; i < 3 && !isSkipped; ++i) - { - if (m[i]) // is a boundary - continue; - - // Check if this link was already processed - if (aCouples.Add(myStructure->GetLink(e[i]))) - { - // Check deflection on edge 1 - Standard_Integer j = (i + 1) % 3; - gp_XY mi2d = (xy[i] + xy[j]) * 0.5; - gFace->D0(mi2d.X(), mi2d.Y(), pDef); - gp_Lin aLin(p[i], gp_Vec(p[i], p[j])); - aSqDef = aLin.SquareDistance(pDef); - - isSkipped = !checkDeflectionAndInsert(pDef, mi2d, theIsFirst, - aSqDef, aSqDefFace, aCircles, aNewVertices, aMaxSqDef, aTempAlloc); - } - } - - if (isSkipped) - break; - - //check normal on bsplines - if (theIsFirst && !aBSpline.IsNull()) - { - gp_Dir N[3] = { gp::DZ(), gp::DZ(), gp::DZ() }; - Standard_Integer aSt[3]; - - for (Standard_Integer i = 0; i < 3; ++i) - { - if (aNorMap.IsBound(v[i])) - { - aSt[i] = aStatMap.Find(v[i]); - N[i] = aNorMap.Find(v[i]); - } - else - { - aSt[i] = GeomLib::NormEstim(aBSpline, gp_Pnt2d(xy[i]), Precision::Confusion(), N[i]); - aStatMap.Bind(v[i], aSt[i]); - aNorMap.Bind(v[i], N[i]); - } - } - - Standard_Real aAngle[3]; - for (Standard_Integer i = 0; i < 3; ++i) - aAngle[i] = N[(i + 1) % 3].Angle(N[i]); - - if (aSt[0] < 1 && aSt[1] < 1 && aSt[2] < 1) - { - if (aAngle[0] > myAngle || aAngle[1] > myAngle || aAngle[2] > myAngle) - { - aMaxSqDef = -1.; - break; - } - } - } - } - - if (theIsFirst) - continue; - -#ifdef DEBUG_MESH - // append to the file triangles in the form of polyline commands; - // so the file can be sourced in draw to analyze triangles on each pass of the algorithm. - // write triangles - ofstream ftt(DEBUG_MESH, std::ios_base::app); - Standard_Integer nbElem = myStructure->NbElements(); - for (Standard_Integer i = 1; i <= nbElem; i++) - { - const BRepMesh_Triangle& aTri = myStructure->GetElement(i); - if (aTri.Movability() == BRepMesh_Deleted) - continue; - Standard_Integer n[3]; - myStructure->ElementNodes(aTri, n); - const BRepMesh_Vertex& aV1 = myStructure->GetNode(n[0]); - const BRepMesh_Vertex& aV2 = myStructure->GetNode(n[1]); - const BRepMesh_Vertex& aV3 = myStructure->GetNode(n[2]); - const gp_Pnt& aP1 = myAttribute->GetPoint(aV1); - const gp_Pnt& aP2 = myAttribute->GetPoint(aV2); - const gp_Pnt& aP3 = myAttribute->GetPoint(aV3); - ftt << "polyline t" << aPass << "_" << i << " " - << aP1.X() << " " << aP1.Y() << " " << aP1.Z() << " " - << aP2.X() << " " << aP2.Y() << " " << aP2.Z() << " " - << aP3.X() << " " << aP3.Y() << " " << aP3.Z() << " " - << aP1.X() << " " << aP1.Y() << " " << aP1.Z() << endl; - } - // write points to insert on the current pass - BRepMesh::ListOfVertex::Iterator it(aNewVertices); - for (Standard_Integer i=1; it.More(); it.Next(), i++) - { - const BRepMesh_Vertex& aVertex = it.Value(); - const gp_Pnt& aP = myAttribute->GetPoint(aVertex); - ftt << "vertex vt" << aPass << "_" << i << " " - << aP.X() << " " << aP.Y() << " " << aP.Z() << endl; - } -#endif - if (theProgressEntry != NULL && !theProgressEntry->More()) - { - return 0; - } - - if (addVerticesToMesh(aNewVertices, theTrigu, theProgressEntry)) - ++aInsertedNb; - } - - return (aMaxSqDef < 0) ? aMaxSqDef : Sqrt(aMaxSqDef); -} - -//======================================================================= -//function : add -//purpose : -//======================================================================= -void BRepMesh_FastDiscretFace::add(const TopoDS_Vertex& theVertex) -{ - if (theVertex.Orientation() != TopAbs_INTERNAL) - return; - - try - { - OCC_CATCH_SIGNALS - - gp_Pnt2d aPnt2d = BRep_Tool::Parameters(theVertex, myAttribute->Face()); - // check UV values for internal vertices - if (myAttribute->ChangeClassifier()->Perform(aPnt2d) != TopAbs_IN) - return; - - NCollection_Handle aFixedVExplorer = new FixedVExplorer(theVertex); - Standard_Integer aIndex = myAttribute->GetVertexIndex(aFixedVExplorer); - gp_XY anUV = BRepMesh_ShapeTool::FindUV(aIndex, aPnt2d, - BRep_Tool::Tolerance(theVertex), myAttribute); - - Standard_Integer aTmpId1, aTmpId2; - anUV = myAttribute->Scale(anUV, Standard_True); - myAttribute->AddNode(aIndex, anUV, BRepMesh_Fixed, aTmpId1, aTmpId2); - } - catch (Standard_Failure) - { - } -} - -//======================================================================= -//function : insertVertex -//purpose : -//======================================================================= -void BRepMesh_FastDiscretFace::insertVertex( - const gp_Pnt& thePnt3d, - const gp_XY& theUV, - BRepMesh::ListOfVertex& theVertices) -{ - Standard_Integer aNbLocat = myAttribute->LastPointId(); - myAttribute->ChangeSurfacePoints()->Bind(++aNbLocat, thePnt3d); - - gp_XY aPnt2d = myAttribute->Scale(theUV, Standard_True); - BRepMesh_Vertex aVertex(aPnt2d, aNbLocat, BRepMesh_Free); - theVertices.Append(aVertex); -} - -//======================================================================= -//function : commitSurfaceTriangulation -//purpose : -//======================================================================= -void BRepMesh_FastDiscretFace::commitSurfaceTriangulation() -{ - if (myAttribute.IsNull() || !myAttribute->IsValid()) - return; - - const TopoDS_Face& aFace = myAttribute->Face(); - BRepMesh_ShapeTool::NullifyFace(aFace); - - Handle(BRepMesh_DataStructureOfDelaun)& aStructure = myAttribute->ChangeStructure(); - const BRepMesh::MapOfInteger& aTriangles = aStructure->ElementsOfDomain(); - - if (aTriangles.IsEmpty()) - { - myAttribute->SetStatus(BRepMesh_Failure); - return; - } - - BRepMesh::HIMapOfInteger& aVetrexEdgeMap = myAttribute->ChangeVertexEdgeMap(); - - // Store triangles - Standard_Integer aVerticesNb = aVetrexEdgeMap->Extent(); - Standard_Integer aTrianglesNb = aTriangles.Extent(); - Handle(Poly_Triangulation) aNewTriangulation = - new Poly_Triangulation(aVerticesNb, aTrianglesNb, Standard_True); - - Poly_Array1OfTriangle& aPolyTrianges = aNewTriangulation->ChangeTriangles(); - - Standard_Integer aTriangeId = 1; - BRepMesh::MapOfInteger::Iterator aTriIt(aTriangles); - for (; aTriIt.More(); aTriIt.Next()) - { - const BRepMesh_Triangle& aCurElem = aStructure->GetElement(aTriIt.Key()); - - Standard_Integer aNode[3]; - aStructure->ElementNodes(aCurElem, aNode); - - Standard_Integer aNodeId[3]; - for (Standard_Integer i = 0; i < 3; ++i) - aNodeId[i] = aVetrexEdgeMap->FindIndex(aNode[i]); - - aPolyTrianges(aTriangeId++).Set(aNodeId[0], aNodeId[1], aNodeId[2]); - } - - // Store mesh nodes - TColgp_Array1OfPnt& aNodes = aNewTriangulation->ChangeNodes(); - TColgp_Array1OfPnt2d& aNodes2d = aNewTriangulation->ChangeUVNodes(); - - for (Standard_Integer i = 1; i <= aVerticesNb; ++i) - { - Standard_Integer aVertexId = aVetrexEdgeMap->FindKey(i); - const BRepMesh_Vertex& aVertex = aStructure->GetNode(aVertexId); - const gp_Pnt& aPoint = myAttribute->GetPoint(aVertex); - - aNodes(i) = aPoint; - aNodes2d(i) = aVertex.Coord(); - } - - aNewTriangulation->Deflection(myAttribute->GetDefFace()); - BRepMesh_ShapeTool::AddInFace(aFace, aNewTriangulation); - - // Delete unused data - myUParam.Clear(0L); - myVParam.Clear(0L); - myAttribute->ChangeStructure().Nullify(); - myAttribute->ChangeSurfacePoints().Nullify(); - myAttribute->ChangeSurfaceVertices().Nullify(); - - myAttribute->ChangeClassifier().Nullify(); - myAttribute->ChangeLocation2D().Nullify(); - myAttribute->ChangeVertexEdgeMap().Nullify(); -} diff --git a/src/BRepMesh/BRepMesh_FastDiscretFace.hxx b/src/BRepMesh/BRepMesh_FastDiscretFace.hxx deleted file mode 100644 index dbf301965f..0000000000 --- a/src/BRepMesh/BRepMesh_FastDiscretFace.hxx +++ /dev/null @@ -1,201 +0,0 @@ -// Copyright (c) 2013 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 _BRepMesh_FastDiscretFace_HeaderFile -#define _BRepMesh_FastDiscretFace_HeaderFile - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -class BRepMesh_DataStructureOfDelaun; -class BRepMesh_FaceAttribute; -class TopoDS_Face; -class TopoDS_Vertex; -class BRepAdaptor_HSurface; -class TopoDS_Edge; -class Poly_Triangulation; -class TopLoc_Location; -class gp_XY; -class gp_Pnt2d; -class BRepMesh_Edge; -class BRepMesh_Vertex; -class gp_Pnt; -class Message_ProgressSentry; - -//! Algorithm to mesh a face with respect of the frontier -//! the deflection and by option the shared components. -class BRepMesh_FastDiscretFace : public Standard_Transient -{ -public: - - //! Constructor. - //! @param theAngle deviation angle to be used for surface tessellation. - //! @param isInternalVerticesMode flag enabling/disabling internal - //! vertices mode. - //! @param isControlSurfaceDeflection enables/disables adaptive - //! reconfiguration of mesh. - Standard_EXPORT BRepMesh_FastDiscretFace( - const Standard_Real theAngle, - const Standard_Real theMinSize, - const Standard_Boolean isInternalVerticesMode, - const Standard_Boolean isControlSurfaceDeflection); - - Standard_EXPORT void Perform(const Handle(BRepMesh_FaceAttribute)& theAttribute); - - Standard_EXPORT void Perform (const Handle(BRepMesh_FaceAttribute)& theAttribute, - Message_ProgressSentry* theProgressEntry); - - DEFINE_STANDARD_RTTIEXT(BRepMesh_FastDiscretFace,Standard_Transient) - -private: - - void add(const Handle(BRepMesh_FaceAttribute)& theAttribute, Message_ProgressSentry* theProgressEntry); - void add(const TopoDS_Vertex& theVertex); - - Standard_Real control(BRepMesh_Delaun& theMeshBuilder, - const Standard_Boolean theIsFirst, - Message_ProgressSentry* theProgressEntry); - - //! Registers the given nodes in mesh data structure and - //! performs refinement of existing mesh. - //! @param theVertices nodes to be inserted. - //! @param theMeshBuilder initialized tool refining mesh - //! in respect to inserting nodes. - //! @return TRUE if vertices were been inserted, FALSE elewhere. - Standard_Boolean addVerticesToMesh( - const BRepMesh::ListOfVertex& theVertices, - BRepMesh_Delaun& theMeshBuilder, - Message_ProgressSentry* theProgressEntry); - - //! Calculates nodes lying on face's surface and inserts them to a mesh. - //! @param theMeshBuilder initialized tool refining mesh - //! in respect to inserting nodes. - void insertInternalVertices(BRepMesh_Delaun& theMeshBuilder, - Message_ProgressSentry* theProgressEntry); - - //! Calculates nodes lying on spherical surface. - //! @param theNewVertices list of vertices to be extended and added to mesh. - void insertInternalVerticesSphere(BRepMesh::ListOfVertex& theNewVertices); - - //! Calculates nodes lying on cylindrical surface. - //! @param theNewVertices list of vertices to be extended and added to mesh. - void insertInternalVerticesCylinder(BRepMesh::ListOfVertex& theNewVertices); - - //! Calculates nodes lying on conical surface. - //! @param theNewVertices list of vertices to be extended and added to mesh. - void insertInternalVerticesCone(BRepMesh::ListOfVertex& theNewVertices); - - //! Calculates nodes lying on toroidal surface. - //! @param theNewVertices list of vertices to be extended and added to mesh. - void insertInternalVerticesTorus(BRepMesh::ListOfVertex& theNewVertices); - - //! Calculates nodes lying on custom-type surface. - //! @param theNewVertices list of vertices to be extended and added to mesh. - void insertInternalVerticesOther(BRepMesh::ListOfVertex& theNewVertices); - - //! Template method trying to insert new internal vertex corresponded to - //! the given 2d point. Calculates 3d position analytically using the given - //! surface. - //! @param thePnt2d 2d point to be inserted to the list. - //! @param theAnalyticSurface analytic surface to calculate 3d point. - //! @param[out] theVertices list of vertices to be updated. - template - void tryToInsertAnalyticVertex(const gp_Pnt2d& thePnt2d, - const AnalyticSurface& theAnalyticSurface, - BRepMesh::ListOfVertex& theVertices) - { - const BRepMesh::HClassifier& aClassifier = myAttribute->ChangeClassifier(); - if (aClassifier->Perform(thePnt2d) != TopAbs_IN) - return; - - gp_Pnt aPnt; - ElSLib::D0(thePnt2d.X(), thePnt2d.Y(), theAnalyticSurface, aPnt); - insertVertex(aPnt, thePnt2d.Coord(), theVertices); - } - - //! Creates new vertex with the given parameters. - //! @param thePnt3d 3d point corresponded to the vertex. - //! @param theUV UV point corresponded to the vertex. - //! @param[out] theVertices list of vertices to be updated. - void insertVertex(const gp_Pnt& thePnt3d, - const gp_XY& theUV, - BRepMesh::ListOfVertex& theVertices); - - //! Stores mesh into the face (without internal edges). - void commitSurfaceTriangulation(); - - //! Performs initialization of data structure using existing data. - void initDataStructure(); - - //! Adds new link to the mesh data structure. - //! Movability of the link and order of nodes depend on orientation parameter. - void addLinkToMesh(const Standard_Integer theFirstNodeId, - const Standard_Integer theLastNodeId, - const TopAbs_Orientation theOrientation); - - //! Inserts new node into a mesh in case if smoothed region build - //! using the given node has better deflection metrics than source state. - //! @param thePnt3d 3d point corresponded to the vertex. - //! @param theUV UV point corresponded to the vertex. - //! @param isDeflectionCheckOnly if TRUE new node will not be added to a mesh - //! even if deflection parameter is better. - //! @param theTriangleDeflection deflection of a triangle from real geometry. - //! @param theFaceDeflection deflection to be achieved. - //! @param theCircleTool tool used for fast extraction of triangles - //! touched by the given point. - //! @param[out] theVertices list of vertices to be updated. - //! @param[in out] theMaxTriangleDeflection maximal deflection of a mesh. - //! @return TRUE in case if the given deflection of triangle is fine and - //! there is no necessity to insert new node or new node was being inserted - //! successfully, FALSE in case if new configuration is better but - //! isDeflectionCheckOnly flag is set. - Standard_Boolean checkDeflectionAndInsert( - const gp_Pnt& thePnt3d, - const gp_XY& theUV, - const Standard_Boolean isDeflectionCheckOnly, - const Standard_Real theTriangleDeflection, - const Standard_Real theFaceDeflection, - const BRepMesh_CircleTool& theCircleTool, - BRepMesh::ListOfVertex& theVertices, - Standard_Real& theMaxTriangleDeflection, - const Handle(NCollection_IncAllocator)& theTempAlloc); - -private: - - Standard_Real myAngle; - Standard_Boolean myInternalVerticesMode; - BRepMesh::IMapOfReal myUParam; - BRepMesh::IMapOfReal myVParam; - - // Fast access to attributes of current face - Handle(BRepMesh_FaceAttribute) myAttribute; - Handle(BRepMesh_DataStructureOfDelaun) myStructure; - - Standard_Real myMinSize; - Standard_Boolean myIsControlSurfaceDeflection; -}; - -DEFINE_STANDARD_HANDLE (BRepMesh_FastDiscretFace, Standard_Transient) - -#endif diff --git a/src/BRepMesh/BRepMesh_GeomTool.cxx b/src/BRepMesh/BRepMesh_GeomTool.cxx index 16c34331b2..ae3126741c 100644 --- a/src/BRepMesh/BRepMesh_GeomTool.cxx +++ b/src/BRepMesh/BRepMesh_GeomTool.cxx @@ -16,15 +16,134 @@ #include +#include + #include #include #include #include +#include #include #include #include #include +namespace +{ + void ComputeErrFactors (const Standard_Real theDeflection, + const Handle(Adaptor3d_HSurface)& theFace, + Standard_Real& theErrFactorU, + Standard_Real& theErrFactorV) + { + theErrFactorU = theDeflection * 10.; + theErrFactorV = theDeflection * 10.; + + switch (theFace->GetType ()) + { + case GeomAbs_Cylinder: + case GeomAbs_Cone: + case GeomAbs_Sphere: + case GeomAbs_Torus: + break; + + case GeomAbs_SurfaceOfExtrusion: + case GeomAbs_SurfaceOfRevolution: + { + Handle(Adaptor3d_HCurve) aCurve = theFace->BasisCurve (); + if (aCurve->GetType () == GeomAbs_BSplineCurve && aCurve->Degree () > 2) + { + theErrFactorV /= (aCurve->Degree () * aCurve->NbKnots ()); + } + break; + } + case GeomAbs_BezierSurface: + { + if (theFace->UDegree () > 2) + { + theErrFactorU /= (theFace->UDegree ()); + } + if (theFace->VDegree () > 2) + { + theErrFactorV /= (theFace->VDegree ()); + } + break; + } + case GeomAbs_BSplineSurface: + { + if (theFace->UDegree () > 2) + { + theErrFactorU /= (theFace->UDegree () * theFace->NbUKnots ()); + } + if (theFace->VDegree () > 2) + { + theErrFactorV /= (theFace->VDegree () * theFace->NbVKnots ()); + } + break; + } + + case GeomAbs_Plane: + default: + theErrFactorU = theErrFactorV = 1.; + } + } + + void AdjustCellsCounts (const Handle(Adaptor3d_HSurface)& theFace, + const Standard_Integer theNbVertices, + Standard_Integer& theCellsCountU, + Standard_Integer& theCellsCountV) + { + const GeomAbs_SurfaceType aType = theFace->GetType (); + if (aType == GeomAbs_OtherSurface) + { + // fallback to the default behavior + theCellsCountU = theCellsCountV = -1; + return; + } + + Standard_Real aSqNbVert = theNbVertices; + if (aType == GeomAbs_Plane) + { + theCellsCountU = theCellsCountV = (Standard_Integer)Ceiling (Pow (2, Log10 (aSqNbVert))); + } + else if (aType == GeomAbs_Cylinder || aType == GeomAbs_Cone) + { + theCellsCountV = (Standard_Integer)Ceiling (Pow (2, Log10 (aSqNbVert))); + } + else if (aType == GeomAbs_SurfaceOfExtrusion || aType == GeomAbs_SurfaceOfRevolution) + { + Handle (Adaptor3d_HCurve) aCurve = theFace->BasisCurve (); + if (aCurve->GetType () == GeomAbs_Line || + (aCurve->GetType () == GeomAbs_BSplineCurve && aCurve->Degree () < 2)) + { + // planar, cylindrical, conical cases + if (aType == GeomAbs_SurfaceOfExtrusion) + theCellsCountU = (Standard_Integer)Ceiling (Pow (2, Log10 (aSqNbVert))); + else + theCellsCountV = (Standard_Integer)Ceiling (Pow (2, Log10 (aSqNbVert))); + } + if (aType == GeomAbs_SurfaceOfExtrusion) + { + // V is always a line + theCellsCountV = (Standard_Integer)Ceiling (Pow (2, Log10 (aSqNbVert))); + } + } + else if (aType == GeomAbs_BezierSurface || aType == GeomAbs_BSplineSurface) + { + if (theFace->UDegree () < 2) + { + theCellsCountU = (Standard_Integer)Ceiling (Pow (2, Log10 (aSqNbVert))); + } + if (theFace->VDegree () < 2) + { + theCellsCountV = (Standard_Integer)Ceiling (Pow (2, Log10 (aSqNbVert))); + } + } + + theCellsCountU = Max (theCellsCountU, 2); + theCellsCountV = Max (theCellsCountV, 2); + } +} + //======================================================================= //function : Constructor //purpose : @@ -76,8 +195,10 @@ BRepMesh_GeomTool::BRepMesh_GeomTool( //======================================================================= Standard_Boolean BRepMesh_GeomTool::Value( const Standard_Integer theIndex, + const Handle(BRepAdaptor_HSurface)& theSurface, Standard_Real& theParam, - gp_Pnt& thePoint) const + gp_Pnt& thePoint, + gp_Pnt2d& theUV) const { if (theIndex < 1 || theIndex > NbPoints()) return Standard_False; @@ -88,6 +209,14 @@ Standard_Boolean BRepMesh_GeomTool::Value( thePoint = myDiscretTool.Value(theIndex); theParam = myDiscretTool.Parameter(theIndex); + const TopoDS_Face& aFace = ((BRepAdaptor_Surface*)&(theSurface->Surface()))->Face(); + + Standard_Real aFirst, aLast; + Handle(Geom2d_Curve) aCurve = + BRep_Tool::CurveOnSurface(*myEdge, aFace, aFirst, aLast); + + aCurve->D0(theParam, theUV); + return Standard_True; } @@ -95,11 +224,12 @@ Standard_Boolean BRepMesh_GeomTool::Value( //function : Value //purpose : //======================================================================= -Standard_Boolean BRepMesh_GeomTool::Value(const Standard_Integer theIndex, - const Standard_Real theIsoParam, - Standard_Real& theParam, - gp_Pnt& thePoint, - gp_Pnt2d& theUV) const +Standard_Boolean BRepMesh_GeomTool::Value( + const Standard_Integer theIndex, + const Standard_Real theIsoParam, + Standard_Real& theParam, + gp_Pnt& thePoint, + gp_Pnt2d& theUV) const { if (theIndex < 1 || theIndex > NbPoints()) return Standard_False; @@ -286,13 +416,63 @@ BRepMesh_GeomTool::IntFlag BRepMesh_GeomTool::IntSegSeg( const Standard_Real aEndPrec = 1 - aPrec; for (Standard_Integer i = 0; i < 2; ++i) { - if( aParam[i] < aPrec || aParam[i] > aEndPrec ) + if(aParam[i] < aPrec || aParam[i] > aEndPrec ) return BRepMesh_GeomTool::NoIntersection; } return BRepMesh_GeomTool::Cross; } +//============================================================================= +//function : CellsCount +//purpose : +//============================================================================= +std::pair BRepMesh_GeomTool::CellsCount ( + const Handle (Adaptor3d_HSurface)& theSurface, + const Standard_Integer theVerticesNb, + const Standard_Real theDeflection, + const BRepMesh_DefaultRangeSplitter* theRangeSplitter) +{ + if (theRangeSplitter == NULL) + return std::pair(-1, -1); + + const GeomAbs_SurfaceType aType = theSurface->GetType (); + + Standard_Real anErrFactorU, anErrFactorV; + ComputeErrFactors(theDeflection, theSurface, anErrFactorU, anErrFactorV); + + const std::pair& aRangeU = theRangeSplitter->GetRangeU(); + const std::pair& aRangeV = theRangeSplitter->GetRangeV(); + const std::pair& aDelta = theRangeSplitter->GetDelta (); + + Standard_Integer aCellsCountU, aCellsCountV; + if (aType == GeomAbs_Torus) + { + aCellsCountU = (Standard_Integer)Ceiling(Pow(2, Log10( + (aRangeU.second - aRangeU.first) / aDelta.first))); + aCellsCountV = (Standard_Integer)Ceiling(Pow(2, Log10( + (aRangeV.second - aRangeV.first) / aDelta.second))); + } + else if (aType == GeomAbs_Cylinder) + { + aCellsCountU = (Standard_Integer)Ceiling(Pow(2, Log10( + (aRangeU.second - aRangeU.first) / aDelta.first / + (aRangeV.second - aRangeV.first)))); + aCellsCountV = (Standard_Integer)Ceiling(Pow(2, Log10( + (aRangeV.second - aRangeV.first) / anErrFactorV))); + } + else + { + aCellsCountU = (Standard_Integer)Ceiling(Pow(2, Log10( + (aRangeU.second - aRangeU.first) / aDelta.first / anErrFactorU))); + aCellsCountV = (Standard_Integer)Ceiling(Pow(2, Log10( + (aRangeV.second - aRangeV.first) / aDelta.second / anErrFactorV))); + } + + AdjustCellsCounts(theSurface, theVerticesNb, aCellsCountU, aCellsCountV); + return std::pair(aCellsCountU, aCellsCountV); +} + //============================================================================= //function : classifyPoint //purpose : diff --git a/src/BRepMesh/BRepMesh_GeomTool.hxx b/src/BRepMesh/BRepMesh_GeomTool.hxx index 047cb188c0..6d69c4bd76 100644 --- a/src/BRepMesh/BRepMesh_GeomTool.hxx +++ b/src/BRepMesh/BRepMesh_GeomTool.hxx @@ -27,6 +27,8 @@ class BRepAdaptor_HSurface; class gp_Pnt; class gp_Pnt2d; class gp_Dir; +class BRepMesh_DefaultRangeSplitter; +class Adaptor3d_HSurface; //! Tool class accumulating common geometrical functions as well as //! functionality using shape geometry to produce data necessary for @@ -60,13 +62,14 @@ public: //! @param theLinDeflection linear deflection. //! @param theAngDeflection angular deflection. //! @param theMinPointsNb minimum nuber of points to be produced. - Standard_EXPORT BRepMesh_GeomTool(const BRepAdaptor_Curve& theCurve, - const Standard_Real theFirstParam, - const Standard_Real theLastParam, - const Standard_Real theLinDeflection, - const Standard_Real theAngDeflection, - const Standard_Integer theMinPointsNb = 2, - const Standard_Real theMinSize = Precision::Confusion()); + Standard_EXPORT BRepMesh_GeomTool( + const BRepAdaptor_Curve& theCurve, + const Standard_Real theFirstParam, + const Standard_Real theLastParam, + const Standard_Real theLinDeflection, + const Standard_Real theAngDeflection, + const Standard_Integer theMinPointsNb = 2, + const Standard_Real theMinSize = Precision::Confusion()); //! Constructor. //! Initiates discretization of geometric curve corresponding @@ -79,15 +82,16 @@ public: //! @param theLinDeflection linear deflection. //! @param theAngDeflection angular deflection. //! @param theMinPointsNb minimum nuber of points to be produced. - Standard_EXPORT BRepMesh_GeomTool(const Handle(BRepAdaptor_HSurface)& theSurface, - const GeomAbs_IsoType theIsoType, - const Standard_Real theParamIso, - const Standard_Real theFirstParam, - const Standard_Real theLastParam, - const Standard_Real theLinDeflection, - const Standard_Real theAngDeflection, - const Standard_Integer theMinPointsNb = 2, - const Standard_Real theMinSize = Precision::Confusion()); + Standard_EXPORT BRepMesh_GeomTool( + const Handle(BRepAdaptor_HSurface)& theSurface, + const GeomAbs_IsoType theIsoType, + const Standard_Real theParamIso, + const Standard_Real theFirstParam, + const Standard_Real theLastParam, + const Standard_Real theLinDeflection, + const Standard_Real theAngDeflection, + const Standard_Integer theMinPointsNb = 2, + const Standard_Real theMinSize = Precision::Confusion()); //! Adds point to already calculated points (or replaces existing). //! @param thePoint point to be added. @@ -124,12 +128,16 @@ public: //! Gets parameters of discretization point with the given index. //! @param theIndex index of discretization point. + //! @param theSurface surface the curve is lying onto. //! @param theParam[out] parameter of the point on the curve. //! @param thePoint[out] discretization point. + //! @param theUV[out] discretization point in parametric space of the surface. //! @return TRUE on success, FALSE elsewhere. Standard_EXPORT Standard_Boolean Value(const Standard_Integer theIndex, + const Handle(BRepAdaptor_HSurface)& theSurface, Standard_Real& theParam, - gp_Pnt& thePoint) const; + gp_Pnt& thePoint, + gp_Pnt2d& theUV) const; public: //! @name static API @@ -188,6 +196,38 @@ public: //! @name static API const Standard_Boolean isConsiderPointOnSegment, gp_Pnt2d& theIntPnt); + //! Compute deflection of the given segment. + static Standard_Real SquareDeflectionOfSegment( + const gp_Pnt& theFirstPoint, + const gp_Pnt& theLastPoint, + const gp_Pnt& theMidPoint) + { + // 23.03.2010 skl for OCC21645 - change precision for comparison + if (theFirstPoint.SquareDistance(theLastPoint) > Precision::SquareConfusion()) + { + gp_Lin aLin(theFirstPoint, gp_Dir(gp_Vec(theFirstPoint, theLastPoint))); + return aLin.SquareDistance(theMidPoint); + } + + return theFirstPoint.SquareDistance(theMidPoint); + } + + // For better meshing performance we try to estimate the acceleration circles grid structure sizes: + // For each parametric direction (U, V) we estimate firstly an approximate distance between the future points - + // this estimation takes into account the required face deflection and the complexity of the face. + // Particularly, the complexity of the faces based on BSpline curves and surfaces requires much more points. + // At the same time, for planar faces and linear parts of the arbitrary surfaces usually no intermediate points + // are necessary. + // The general idea for each parametric direction: + // cells_count = 2 ^ log10 ( estimated_points_count ) + // For linear parametric direction we fall back to the initial vertex count: + // cells_count = 2 ^ log10 ( initial_vertex_count ) + Standard_EXPORT static std::pair CellsCount ( + const Handle (Adaptor3d_HSurface)& theSurface, + const Standard_Integer theVerticesNb, + const Standard_Real theDeflection, + const BRepMesh_DefaultRangeSplitter* theRangeSplitter); + private: //! Classifies the point in case of coincidence of two vectors. diff --git a/src/BRepMesh/BRepMesh_IEdgeTool.cxx b/src/BRepMesh/BRepMesh_IEdgeTool.cxx deleted file mode 100644 index f343c21829..0000000000 --- a/src/BRepMesh/BRepMesh_IEdgeTool.cxx +++ /dev/null @@ -1,20 +0,0 @@ -// Created on: 2014-08-13 -// Created by: Oleg AGASHIN -// Copyright (c) 2011-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 - - - -IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_IEdgeTool,Standard_Transient) \ No newline at end of file diff --git a/src/BRepMesh/BRepMesh_IncrementalMesh.cxx b/src/BRepMesh/BRepMesh_IncrementalMesh.cxx index e44d979ffb..24d3fd3658 100644 --- a/src/BRepMesh/BRepMesh_IncrementalMesh.cxx +++ b/src/BRepMesh/BRepMesh_IncrementalMesh.cxx @@ -15,48 +15,12 @@ // commercial license or contractual agreement. #include - -#include -#include -#include - -#include -#include +#include #include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -IMPLEMENT_STANDARD_RTTIEXT(BRepMesh_IncrementalMesh,BRepMesh_DiscretRoot) +#include +#include +#include +#include namespace { @@ -65,60 +29,13 @@ namespace static Standard_Boolean IS_IN_PARALLEL = Standard_False; } -class BRepMesh_IncrementalMesh::FaceListFunctor -{ -public: - FaceListFunctor (BRepMesh_IncrementalMesh* theAlgo, - const Handle(Message_ProgressIndicator)& theProgress, - Standard_Boolean theParallel) - : myAlgo (theAlgo), - mySentry (theProgress, "Mesh faces", 0, theAlgo->myFaces.Size(), 1), - myThreadId (OSD_Thread::Current()), - myIsParallel (theParallel), - myHasProgress (!theProgress.IsNull()) - { - } - - void operator() (const Standard_Integer theFaceIndex) const - { - if (!mySentry.More()) - { - return; - } - - TopoDS_Face& aFace = myAlgo->myFaces.ChangeValue (theFaceIndex); - myAlgo->myMesh->Process (aFace, &mySentry); - - if (myIsParallel) - { - // use a trick to avoid mutex locks - increment the progress only within main thread - if (myHasProgress && myThreadId == OSD_Thread::Current()) - { - mySentry.Next (OSD_Parallel::NbLogicalProcessors()); - } - } - else - { - mySentry.Next(); - } - } - -private: - mutable BRepMesh_IncrementalMesh* myAlgo; - mutable Message_ProgressSentry mySentry; - Standard_ThreadId myThreadId; - Standard_Boolean myIsParallel; - Standard_Boolean myHasProgress; -}; - //======================================================================= //function : Default constructor //purpose : //======================================================================= BRepMesh_IncrementalMesh::BRepMesh_IncrementalMesh() -: myMaxShapeSize(0.), - myModified(Standard_False), - myStatus(0) +: myModified(Standard_False), + myStatus(IMeshData_NoError) { } @@ -130,17 +47,14 @@ BRepMesh_IncrementalMesh::BRepMesh_IncrementalMesh( const TopoDS_Shape& theSh const Standard_Real theLinDeflection, const Standard_Boolean isRelative, const Standard_Real theAngDeflection, - const Standard_Boolean isInParallel, - const Standard_Boolean adaptiveMin) -: myMaxShapeSize(0.), - myModified(Standard_False), - myStatus(0) + const Standard_Boolean isInParallel) +: myModified(Standard_False), + myStatus(IMeshData_NoError) { myParameters.Deflection = theLinDeflection; - myParameters.Relative = isRelative; - myParameters.Angle = theAngDeflection; + myParameters.Angle = theAngDeflection; + myParameters.Relative = isRelative; myParameters.InParallel = isInParallel; - myParameters.AdaptiveMin = adaptiveMin; myShape = theShape; Perform(); @@ -150,12 +64,12 @@ BRepMesh_IncrementalMesh::BRepMesh_IncrementalMesh( const TopoDS_Shape& theSh //function : Constructor //purpose : //======================================================================= -BRepMesh_IncrementalMesh::BRepMesh_IncrementalMesh(const TopoDS_Shape& theShape, - const BRepMesh_FastDiscret::Parameters& theParameters) +BRepMesh_IncrementalMesh::BRepMesh_IncrementalMesh( + const TopoDS_Shape& theShape, + const IMeshTools_Parameters& theParameters) : myParameters(theParameters) { - myShape = theShape; - + myShape = theShape; Perform(); } @@ -167,490 +81,46 @@ BRepMesh_IncrementalMesh::~BRepMesh_IncrementalMesh() { } -//======================================================================= -//function : clear -//purpose : -//======================================================================= -void BRepMesh_IncrementalMesh::clear() -{ - // the allocator will be alive while the structures are alive - Handle(NCollection_BaseAllocator) anAlloc = - new NCollection_IncAllocator(BRepMesh::MEMORY_BLOCK_SIZE_HUGE); - myEdges.Clear(anAlloc); - myEdgeDeflection.Clear(anAlloc); - myFaces.Clear(); - myMesh.Nullify(); -} - -//======================================================================= -//function : init -//purpose : -//======================================================================= -void BRepMesh_IncrementalMesh::init() -{ - myStatus = 0; - myModified = Standard_False; - - setDone(); - clear(); - - collectFaces(); - - Bnd_Box aBox; - if ( myParameters.Relative ) - { - BRepBndLib::Add(myShape, aBox, Standard_False); - - if (aBox.IsVoid()) - { - // Nothing to mesh. - return; - } - - BRepMesh_ShapeTool::BoxMaxDimension(aBox, myMaxShapeSize); - } - - myMesh = new BRepMesh_FastDiscret (aBox, myParameters); - - myMesh->InitSharedFaces(myShape); -} - -//======================================================================= -//function : collectFaces -//purpose : -//======================================================================= -void BRepMesh_IncrementalMesh::collectFaces() -{ - Handle(NCollection_IncAllocator) anAlloc = new NCollection_IncAllocator; - TopTools_ListOfShape aFaceList(anAlloc); - BRepLib::ReverseSortFaces(myShape, aFaceList); - TColStd_MapOfTransient aTFaceMap(1, anAlloc); - - // make array of faces suitable for processing (excluding faces without surface) - TopLoc_Location aDummyLoc; - TopTools_ListIteratorOfListOfShape aFaceIter(aFaceList); - for (; aFaceIter.More(); aFaceIter.Next()) - { - const TopoDS_Face& aFace = TopoDS::Face(aFaceIter.Value()); - const Handle(TopoDS_TShape)& aTFace = aFace.TShape(); - if (!aTFaceMap.Add (aTFace)) - continue; // already processed - - const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface(aFace, aDummyLoc); - if (aSurf.IsNull()) - continue; - - myFaces.Append(aFace); - } -} - //======================================================================= //function : Perform //purpose : //======================================================================= void BRepMesh_IncrementalMesh::Perform() { - Perform (Handle(Message_ProgressIndicator)()); + Handle(BRepMesh_Context) aContext = new BRepMesh_Context; + Perform (aContext); } //======================================================================= //function : Perform -//purpose : -//======================================================================= -void BRepMesh_IncrementalMesh::Perform (const Handle(Message_ProgressIndicator)& theProgress) -{ - init(); - - if (myMesh.IsNull()) - return; - - update (theProgress); -} - -//======================================================================= -//function : update() -//purpose : -//======================================================================= -void BRepMesh_IncrementalMesh::update (const Handle(Message_ProgressIndicator)& theProgress) -{ - Message_ProgressSentry anOuterSentry (theProgress, "Updating", 0, 100, 1); - - // Update edges data - anOuterSentry.Next(9); - { - int aNbEdges = 0; - for (TopExp_Explorer aExplorer (myShape, TopAbs_EDGE); aExplorer.More(); aExplorer.Next()) - { - ++aNbEdges; - } - - Message_ProgressSentry anEdgeSentry (theProgress, "Update edges data", 0, aNbEdges, 1); - for (TopExp_Explorer aExplorer (myShape, TopAbs_EDGE); - aExplorer.More() && anEdgeSentry.More(); aExplorer.Next(), anEdgeSentry.Next()) - { - const TopoDS_Edge& aEdge = TopoDS::Edge(aExplorer.Current()); - if(!BRep_Tool::IsGeometric(aEdge)) - continue; - - update(aEdge); - } - } - - if (!anOuterSentry.More()) - { - myStatus = BRepMesh_UserBreak; - return; - } - anOuterSentry.Next(5); - - // Update faces data - NCollection_Vector::Iterator aFaceIt(myFaces); - for (Message_ProgressSentry aFacesSentry (theProgress, "Update faces data", 0, myFaces.Size(), 1); - aFaceIt.More() && aFacesSentry.More(); aFaceIt.Next(), aFacesSentry.Next()) - { - update(aFaceIt.Value()); - } - - if (!anOuterSentry.More()) - { - myStatus = BRepMesh_UserBreak; - return; - } - - anOuterSentry.Next(80); - - { - // Mesh faces - FaceListFunctor aFacesFunctor (this, theProgress, myParameters.InParallel); - OSD_Parallel::For (0, myFaces.Size(), aFacesFunctor, !myParameters.InParallel); - } - - if (!anOuterSentry.More()) - { - myStatus = BRepMesh_UserBreak; - return; - } - - anOuterSentry.Next(5); - { - Message_ProgressSentry aSentry (theProgress, "Commit", 0, myFaces.Size(), 1); - commit (aSentry); - } - anOuterSentry.Next(); - clear(); -} - -//======================================================================= -//function : discretizeFreeEdges //purpose : //======================================================================= -void BRepMesh_IncrementalMesh::discretizeFreeEdges() +void BRepMesh_IncrementalMesh::Perform(const Handle(IMeshTools_Context)& theContext) { - TopExp_Explorer aExplorer(myShape ,TopAbs_EDGE, TopAbs_FACE); - for (; aExplorer.More(); aExplorer.Next()) - { - const TopoDS_Edge& aEdge = TopoDS::Edge(aExplorer.Current()); - if(!BRep_Tool::IsGeometric(aEdge)) - continue; - - TopLoc_Location aLoc; - Standard_Real aEdgeDeflection = edgeDeflection(aEdge); - Handle(Poly_Polygon3D) aPoly3D = BRep_Tool::Polygon3D(aEdge, aLoc); - if (!aPoly3D.IsNull() && aPoly3D->Deflection() < 1.1 * aEdgeDeflection) - continue; - - BRepAdaptor_Curve aCurve(aEdge); - GCPnts_TangentialDeflection aDiscret(aCurve, aCurve.FirstParameter(), - aCurve.LastParameter(), myParameters.Angle, aEdgeDeflection, 2, - Precision::PConfusion(), myParameters.MinSize); - - Standard_Integer aNodesNb = aDiscret.NbPoints(); - TColgp_Array1OfPnt aNodes (1, aNodesNb); - TColStd_Array1OfReal aUVNodes(1, aNodesNb); - for (Standard_Integer i = 1; i <= aNodesNb; ++i) - { - aNodes (i) = aDiscret.Value(i); - aUVNodes(i) = aDiscret.Parameter(i); - } - - aPoly3D = new Poly_Polygon3D(aNodes, aUVNodes); - aPoly3D->Deflection(myParameters.Deflection); - - BRep_Builder aBuilder; - aBuilder.UpdateEdge(aEdge, aPoly3D); - } -} - -//======================================================================= -//function : edgeDeflection -//purpose : -//======================================================================= -Standard_Real BRepMesh_IncrementalMesh::edgeDeflection( - const TopoDS_Edge& theEdge) -{ - const Standard_Real* pDef = myEdgeDeflection.Seek(theEdge); - if (pDef) - return *pDef; - - Standard_Real aEdgeDeflection; - if ( myParameters.Relative ) - { - Standard_Real aScale; - aEdgeDeflection = BRepMesh_ShapeTool::RelativeEdgeDeflection(theEdge, - myParameters.Deflection, myMaxShapeSize, aScale); - } - else - aEdgeDeflection = myParameters.Deflection; - - myEdgeDeflection.Bind(theEdge, aEdgeDeflection); - return aEdgeDeflection; -} - -//======================================================================= -//function : faceDeflection -//purpose : -//======================================================================= -Standard_Real BRepMesh_IncrementalMesh::faceDeflection( - const TopoDS_Face& theFace) -{ - if ( !myParameters.Relative ) - return myParameters.Deflection; - - Standard_Integer aEdgesNb = 0; - Standard_Real aFaceDeflection = 0.; - - TopExp_Explorer aEdgeIt(theFace, TopAbs_EDGE); - for (; aEdgeIt.More(); aEdgeIt.Next(), ++aEdgesNb) - { - const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Current()); - aFaceDeflection += edgeDeflection(aEdge); - } - - return (aEdgesNb == 0) ? myParameters.Deflection : (aFaceDeflection / aEdgesNb); -} - -//======================================================================= -//function : update(edge) -//purpose : -//======================================================================= -void BRepMesh_IncrementalMesh::update(const TopoDS_Edge& theEdge) -{ - if (!myEdges.IsBound(theEdge)) - myEdges.Bind(theEdge, BRepMesh::DMapOfTriangulationBool(3, myEdges.Allocator())); - - Standard_Real aEdgeDeflection = edgeDeflection(theEdge); - // Check that triangulation relies to face of the given shape. - const TopTools_IndexedDataMapOfShapeListOfShape& aMapOfSharedFaces = - myMesh->SharedFaces(); - - const TopTools_ListOfShape& aSharedFaces = - aMapOfSharedFaces.FindFromKey(theEdge); - - TopTools_ListIteratorOfListOfShape aSharedFaceIt(aSharedFaces); - for (; aSharedFaceIt.More(); aSharedFaceIt.Next()) - { - TopLoc_Location aLoc; - const TopoDS_Face& aFace = TopoDS::Face(aSharedFaceIt.Value()); - const Handle(Poly_Triangulation)& aFaceTriangulation = - BRep_Tool::Triangulation(aFace, aLoc); - - if (aFaceTriangulation.IsNull()) - continue; - - Standard_Boolean isConsistent = Standard_False; - const Handle(Poly_PolygonOnTriangulation)& aPolygon = - BRep_Tool::PolygonOnTriangulation(theEdge, aFaceTriangulation, aLoc); - - if (!aPolygon.IsNull()) - { - isConsistent = aPolygon->Deflection() < 1.1 * aEdgeDeflection && - aPolygon->HasParameters(); - - if (!isConsistent) - { - myModified = Standard_True; - BRepMesh_ShapeTool::NullifyEdge(theEdge, aFaceTriangulation, aLoc); - } - } - - myEdges(theEdge).Bind(aFaceTriangulation, isConsistent); - } -} - -//======================================================================= -//function : isToBeMeshed -//purpose : -//======================================================================= -Standard_Boolean BRepMesh_IncrementalMesh::toBeMeshed( - const TopoDS_Face& theFace, - const Standard_Boolean isWithCheck) -{ - TopLoc_Location aLoc; - const Handle(Poly_Triangulation)& aTriangulation = - BRep_Tool::Triangulation(theFace, aLoc); - - if (aTriangulation.IsNull()) - return Standard_True; + initParameters(); - if (isWithCheck) - { - Standard_Real aFaceDeflection = faceDeflection(theFace); - if (aTriangulation->Deflection() < 1.1 * aFaceDeflection) - { - Standard_Boolean isEdgesConsistent = Standard_True; - TopExp_Explorer aEdgeIt(theFace, TopAbs_EDGE); - for (; aEdgeIt.More() && isEdgesConsistent; aEdgeIt.Next()) - { - const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Current()); - if (!myEdges.IsBound(aEdge)) - continue; + theContext->SetShape(Shape()); + theContext->ChangeParameters() = myParameters; + theContext->ChangeParameters().CleanModel = Standard_False; - BRepMesh::DMapOfTriangulationBool& aTriMap = myEdges(aEdge); - isEdgesConsistent &= aTriMap.IsBound(aTriangulation) && - aTriMap(aTriangulation); - } + IMeshTools_MeshBuilder aIncMesh(theContext); + aIncMesh.Perform(); - if (isEdgesConsistent) - { - // #25080: check that indices of links forming triangles are in range. - Standard_Boolean isTriangulationConsistent = Standard_True; - const Standard_Integer aNodesNb = aTriangulation->NbNodes(); - const Poly_Array1OfTriangle& aTriangles = aTriangulation->Triangles(); - Standard_Integer i = aTriangles.Lower(); - for (; i <= aTriangles.Upper() && isTriangulationConsistent; ++i) - { - const Poly_Triangle& aTriangle = aTriangles(i); - Standard_Integer n[3]; - aTriangle.Get(n[0], n[1], n[2]); - for (Standard_Integer j = 0; j < 3 && isTriangulationConsistent; ++j) - isTriangulationConsistent = (n[j] >= 1 && n[j] <= aNodesNb); - } - - if (isTriangulationConsistent) - return Standard_False; - } - } - } - - // Nullify edges - TopExp_Explorer aEdgeIt(theFace, TopAbs_EDGE); - for (; aEdgeIt.More(); aEdgeIt.Next()) + myStatus = IMeshData_NoError; + const Handle(IMeshData_Model)& aModel = theContext->GetModel(); + for (Standard_Integer aFaceIt = 0; aFaceIt < aModel->FacesNb(); ++aFaceIt) { - const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Current()); - BRepMesh_ShapeTool::NullifyEdge(aEdge, aTriangulation, aLoc); - } - - BRepMesh_ShapeTool::NullifyFace(theFace); - return Standard_True; -} - -//======================================================================= -//function : update(face) -//purpose : -//======================================================================= -void BRepMesh_IncrementalMesh::update(const TopoDS_Face& theFace) -{ - if (!toBeMeshed(theFace, Standard_True)) - return; - - myModified = Standard_True; - Standard_Integer aStatus = myMesh->Add(theFace); - - myStatus |= aStatus; - if (aStatus != BRepMesh_ReMesh) - return; - - BRepMesh::MapOfShape aUsedFaces; - aUsedFaces.Add(theFace); - - const TopTools_IndexedDataMapOfShapeListOfShape& aMapOfSharedFaces = - myMesh->SharedFaces(); + const IMeshData::IFaceHandle& aDFace = aModel->GetFace(aFaceIt); + myStatus |= aDFace->GetStatusMask(); - TopExp_Explorer aEdgeIt(theFace, TopAbs_EDGE); - for (; aEdgeIt.More(); aEdgeIt.Next()) - { - const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Current()); - if (aMapOfSharedFaces.FindIndex(aEdge) == 0) - continue; - - const TopTools_ListOfShape& aSharedFaces = aMapOfSharedFaces.FindFromKey(aEdge); - TopTools_ListIteratorOfListOfShape aSharedFaceIt(aSharedFaces); - for (; aSharedFaceIt.More(); aSharedFaceIt.Next()) + for (Standard_Integer aWireIt = 0; aWireIt < aDFace->WiresNb(); ++aWireIt) { - const TopoDS_Face& aFace = TopoDS::Face(aSharedFaceIt.Value()); - if (aUsedFaces.Contains(aFace)) - continue; - - aUsedFaces.Add(aFace); - toBeMeshed(aFace, Standard_False); - - myStatus |= myMesh->Add(aFace); + const IMeshData::IWireHandle& aDWire = aDFace->GetWire(aWireIt); + myStatus |= aDWire->GetStatusMask(); } } -} -//======================================================================= -//function : commit -//purpose : -//======================================================================= -void BRepMesh_IncrementalMesh::commit (Message_ProgressSentry& theSentry) -{ - NCollection_Vector::Iterator aFaceIt(myFaces); - for (; aFaceIt.More() && theSentry.More(); aFaceIt.Next(), theSentry.Next()) - commitEdges(aFaceIt.Value()); - - discretizeFreeEdges(); -} - -//======================================================================= -//function : commitEdges -//purpose : -//======================================================================= -void BRepMesh_IncrementalMesh::commitEdges(const TopoDS_Face& theFace) -{ - TopoDS_Face aFace = theFace; - aFace.Orientation(TopAbs_FORWARD); - - Handle(BRepMesh_FaceAttribute) aFaceAttribute; - if (!myMesh->GetFaceAttribute(aFace, aFaceAttribute)) - return; - - if (!aFaceAttribute->IsValid()) - { - myStatus |= aFaceAttribute->GetStatus(); - return; - } - - TopLoc_Location aLoc; - Handle(Poly_Triangulation) aTriangulation = BRep_Tool::Triangulation(aFace, aLoc); - - if (aTriangulation.IsNull()) - return; - - try - { - OCC_CATCH_SIGNALS - - // Store discretization of edges - BRepMesh::HDMapOfShapePairOfPolygon& aInternalEdges = aFaceAttribute->ChangeInternalEdges(); - BRepMesh::DMapOfShapePairOfPolygon::Iterator aEdgeIt(*aInternalEdges); - for (; aEdgeIt.More(); aEdgeIt.Next()) - { - const TopoDS_Edge& aEdge = TopoDS::Edge(aEdgeIt.Key()); - const BRepMesh_PairOfPolygon& aPolyPair = aEdgeIt.Value(); - const Handle(Poly_PolygonOnTriangulation)& aPolygon1 = aPolyPair.First(); - const Handle(Poly_PolygonOnTriangulation)& aPolygon2 = aPolyPair.Last(); - - if (aPolygon1 == aPolygon2) - BRepMesh_ShapeTool::UpdateEdge(aEdge, aPolygon1, aTriangulation, aLoc); - else - BRepMesh_ShapeTool::UpdateEdge(aEdge, aPolygon1, aPolygon2, aTriangulation, aLoc); - } - } - catch (Standard_Failure) - { - myStatus |= BRepMesh_Failure; - } + setDone(); } //======================================================================= @@ -665,9 +135,9 @@ Standard_Integer BRepMesh_IncrementalMesh::Discret( { BRepMesh_IncrementalMesh* anAlgo = new BRepMesh_IncrementalMesh(); anAlgo->ChangeParameters().Deflection = theDeflection; - anAlgo->ChangeParameters().Angle = theAngle; + anAlgo->ChangeParameters().Angle = theAngle; anAlgo->ChangeParameters().InParallel = IS_IN_PARALLEL; - anAlgo->SetShape (theShape); + anAlgo->SetShape (theShape); theAlgo = anAlgo; return 0; // no error } diff --git a/src/BRepMesh/BRepMesh_IncrementalMesh.hxx b/src/BRepMesh/BRepMesh_IncrementalMesh.hxx index 84541536f9..4831ffa434 100644 --- a/src/BRepMesh/BRepMesh_IncrementalMesh.hxx +++ b/src/BRepMesh/BRepMesh_IncrementalMesh.hxx @@ -14,22 +14,9 @@ #ifndef _BRepMesh_IncrementalMesh_HeaderFile #define _BRepMesh_IncrementalMesh_HeaderFile -#include -#include - -#include -#include -#include #include -#include - -#include - -class Message_ProgressIndicator; -class Poly_Triangulation; -class TopoDS_Shape; -class TopoDS_Edge; -class TopoDS_Face; +#include +#include //! Builds the mesh of a shape with respect of their //! correctly triangulated parts @@ -52,41 +39,39 @@ public: //! @name mesher API //! used for the faces will be the maximum deflection of their edges. //! @param theAngDeflection angular deflection. //! @param isInParallel if TRUE shape will be meshed in parallel. - Standard_EXPORT BRepMesh_IncrementalMesh( - const TopoDS_Shape& theShape, - const Standard_Real theLinDeflection, - const Standard_Boolean isRelative = Standard_False, - const Standard_Real theAngDeflection = 0.5, - const Standard_Boolean isInParallel = Standard_False, - const Standard_Boolean adaptiveMin = Standard_False); + Standard_EXPORT BRepMesh_IncrementalMesh(const TopoDS_Shape& theShape, + const Standard_Real theLinDeflection, + const Standard_Boolean isRelative = Standard_False, + const Standard_Real theAngDeflection = 0.5, + const Standard_Boolean isInParallel = Standard_False); //! Constructor. //! Automatically calls method Perform. //! @param theShape shape to be meshed. //! @param theParameters - parameters of meshing - Standard_EXPORT BRepMesh_IncrementalMesh (const TopoDS_Shape& theShape, - const BRepMesh_FastDiscret::Parameters& theParameters); + Standard_EXPORT BRepMesh_IncrementalMesh(const TopoDS_Shape& theShape, + const IMeshTools_Parameters& theParameters); //! Performs meshing ot the shape. Standard_EXPORT virtual void Perform() Standard_OVERRIDE; - //! Performs meshing ot the shape. - Standard_EXPORT void Perform(const Handle(Message_ProgressIndicator)& theProgress); - + //! Performs meshing using custom context; + Standard_EXPORT void Perform(const Handle(IMeshTools_Context)& theContext); + public: //! @name accessing to parameters. //! Returns meshing parameters - inline const BRepMesh_FastDiscret::Parameters& Parameters() const + inline const IMeshTools_Parameters& Parameters() const { return myParameters; } //! Returns modifiable meshing parameters - inline BRepMesh_FastDiscret::Parameters& ChangeParameters() + inline IMeshTools_Parameters& ChangeParameters() { return myParameters; } - + //! Returns modified flag. inline Standard_Boolean IsModified() const { @@ -99,6 +84,29 @@ public: //! @name accessing to parameters. return myStatus; } +private: + + //! Initializes specific parameters + inline void initParameters() + { + if (myParameters.DeflectionInterior < Precision::Confusion()) + { + myParameters.DeflectionInterior = myParameters.Deflection; + } + + if (myParameters.MinSize < Precision::Confusion()) + { + myParameters.MinSize = + Max(IMeshTools_Parameters::RelMinSize() * Min(myParameters.Deflection, + myParameters.DeflectionInterior), + Precision::Confusion()); + } + + if (myParameters.AngleInterior < Precision::Angular()) + { + myParameters.AngleInterior = 2.0 * myParameters.Angle; + } + } public: //! @name plugin API @@ -121,81 +129,13 @@ public: //! @name plugin API //! Discret() static method (thus applied only to Mesh Factories). Standard_EXPORT static void SetParallelDefault(const Standard_Boolean isInParallel); - DEFINE_STANDARD_RTTIEXT(BRepMesh_IncrementalMesh,BRepMesh_DiscretRoot) + DEFINE_STANDARD_RTTI_INLINE(BRepMesh_IncrementalMesh, BRepMesh_DiscretRoot) protected: - Standard_EXPORT virtual void init() Standard_OVERRIDE; - -private: - - //! Builds the incremental mesh for the shape. - void update(const Handle(Message_ProgressIndicator)& theProgress); - - //! Checks triangulation of the given face for consistency - //! with the chosen tolerance. If some edge of face has no - //! discrete representation triangulation will be calculated. - //! @param theFace face to be checked. - void update(const TopoDS_Face& theFace); - - //! Checks discretization of the given edge for consistency - //! with the chosen tolerance. - //! @param theEdge edge to be checked. - void update(const TopoDS_Edge& theEdge); - - //! Collects faces suitable for meshing. - void collectFaces(); - - //! Discretizes edges that have no associations with faces. - void discretizeFreeEdges(); - - //! Returns deflection of the given edge. - //! @param theEdge edge which tolerance should be taken. - Standard_Real edgeDeflection(const TopoDS_Edge& theEdge); - - //! Returns deflection of the given face. - //! If relative flag is set, calculates relative deflection of the face - //! as an average value of relative deflection regarding face's edges. - //! Returns value of deflection set by user elsewhere. - Standard_Real faceDeflection(const TopoDS_Face& theFace); - - //! Prepares the given face for meshing. - //! Nullifies triangulation of face and polygons of face's edges. - //! @param theFace face to be checked. - //! @param isWithCheck if TRUE, checks parameters of triangulation - //! existing in face. If its deflection satisfies the given value and - //! each edge of face has polygon corresponded to this triangulation, - //! method return FALSE. - //! @return TRUE in case if the given face should be meshed. - Standard_Boolean toBeMeshed(const TopoDS_Face& theFace, - const Standard_Boolean isWithCheck); - - //! Stores mesh to the shape. - void commit(Message_ProgressSentry& theSentry); - - //! Stores mesh of internal edges to the face. - void commitEdges(const TopoDS_Face& theFace); - - //! Clears internal data structures. - void clear(); - -private: - class FaceListFunctor; - -protected: - - BRepMesh::DMapOfEdgeListOfTriangulationBool myEdges; - Handle(BRepMesh_FastDiscret) myMesh; - TopTools_DataMapOfShapeReal myEdgeDeflection; - NCollection_Vector myFaces; - - BRepMesh_FastDiscret::Parameters myParameters; - - Standard_Real myMaxShapeSize; - Standard_Boolean myModified; - Standard_Integer myStatus; + IMeshTools_Parameters myParameters; + Standard_Boolean myModified; + Standard_Integer myStatus; }; -DEFINE_STANDARD_HANDLE(BRepMesh_IncrementalMesh,BRepMesh_DiscretRoot) - #endif diff --git a/src/BRepMesh/BRepMesh_MeshAlgoFactory.cxx b/src/BRepMesh/BRepMesh_MeshAlgoFactory.cxx new file mode 100644 index 0000000000..891448a1cf --- /dev/null +++ b/src/BRepMesh/BRepMesh_MeshAlgoFactory.cxx @@ -0,0 +1,105 @@ +// Created on: 2016-04-19 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace +{ + struct BaseMeshAlgo + { + typedef BRepMesh_DelaunayBaseMeshAlgo Type; + }; + + template + struct NodeInsertionMeshAlgo + { + typedef BRepMesh_DelaunayNodeInsertionMeshAlgo Type; + }; + + template + struct DeflectionControlMeshAlgo + { + typedef BRepMesh_DelaunayDeflectionControlMeshAlgo Type; + }; +} + +//======================================================================= +// Function: Constructor +// Purpose : +//======================================================================= +BRepMesh_MeshAlgoFactory::BRepMesh_MeshAlgoFactory() +{ +} + +//======================================================================= +// Function: Destructor +// Purpose : +//======================================================================= +BRepMesh_MeshAlgoFactory::~BRepMesh_MeshAlgoFactory() +{ +} + +//======================================================================= +// Function: GetAlgo +// Purpose : +//======================================================================= +Handle(IMeshTools_MeshAlgo) BRepMesh_MeshAlgoFactory::GetAlgo( + const GeomAbs_SurfaceType theSurfaceType, + const IMeshTools_Parameters& theParameters) const +{ + switch (theSurfaceType) + { + case GeomAbs_Plane: + return theParameters.InternalVerticesMode ? + new NodeInsertionMeshAlgo::Type : + new BaseMeshAlgo::Type; + break; + + case GeomAbs_Sphere: + return new NodeInsertionMeshAlgo::Type; + break; + + case GeomAbs_Cylinder: + return theParameters.InternalVerticesMode ? + new NodeInsertionMeshAlgo::Type : + new BaseMeshAlgo::Type; + break; + + case GeomAbs_Cone: + return new NodeInsertionMeshAlgo::Type; + break; + + case GeomAbs_Torus: + return new NodeInsertionMeshAlgo::Type; + break; + + case GeomAbs_SurfaceOfRevolution: + return new DeflectionControlMeshAlgo::Type; + break; + + default: + return new DeflectionControlMeshAlgo::Type; + } +} diff --git a/src/BRepMesh/BRepMesh_MeshAlgoFactory.hxx b/src/BRepMesh/BRepMesh_MeshAlgoFactory.hxx new file mode 100644 index 0000000000..72a27c5587 --- /dev/null +++ b/src/BRepMesh/BRepMesh_MeshAlgoFactory.hxx @@ -0,0 +1,44 @@ +// Created on: 2016-07-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _BRepMesh_MeshAlgoFactory_HeaderFile +#define _BRepMesh_MeshAlgoFactory_HeaderFile + +#include +#include +#include +#include + +//! Default implementation of IMeshTools_MeshAlgoFactory providing algorithms +//! of different compexity depending on type of target surface. +class BRepMesh_MeshAlgoFactory : public IMeshTools_MeshAlgoFactory +{ +public: + + //! Constructor. + Standard_EXPORT BRepMesh_MeshAlgoFactory(); + + //! Destructor. + Standard_EXPORT virtual ~BRepMesh_MeshAlgoFactory(); + + //! Creates instance of meshing algorithm for the given type of surface. + Standard_EXPORT virtual Handle(IMeshTools_MeshAlgo) GetAlgo( + const GeomAbs_SurfaceType theSurfaceType, + const IMeshTools_Parameters& theParameters) const Standard_OVERRIDE; + + DEFINE_STANDARD_RTTI_INLINE(BRepMesh_MeshAlgoFactory, IMeshTools_MeshAlgoFactory) +}; + +#endif \ No newline at end of file diff --git a/src/BRepMesh/BRepMesh_MeshTool.cxx b/src/BRepMesh/BRepMesh_MeshTool.cxx new file mode 100644 index 0000000000..31a304f883 --- /dev/null +++ b/src/BRepMesh/BRepMesh_MeshTool.cxx @@ -0,0 +1,368 @@ +// Created on: 2016-08-22 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace +{ + //! Returns index of triangle node opposite to the given link. + inline Standard_Integer findApexIndex( + const Standard_Integer(&aNodes)[3], + const BRepMesh_Edge& theLink) + { + Standard_Integer i = 0; + for (; i < 3; ++i) + { + if (aNodes[i] != theLink.FirstNode() && + aNodes[i] != theLink.LastNode()) + { + break; + } + } + + return i; + } +} + +//======================================================================= +// Function: Constructor +// Purpose : +//======================================================================= +BRepMesh_MeshTool::BRepMesh_MeshTool( + const Handle(BRepMesh_DataStructureOfDelaun)& theStructure) + : myStructure(theStructure) +{ +} + +//======================================================================= +// Function: Destructor +// Purpose : +//======================================================================= +BRepMesh_MeshTool::~BRepMesh_MeshTool() +{ +} + +//======================================================================= +//function : Legalize +//purpose : +//======================================================================= +void BRepMesh_MeshTool::Legalize(const Standard_Integer theLinkIndex) +{ + std::stack aStack; + aStack.push(theLinkIndex); + + IMeshData::MapOfInteger aUsedLinks; + while (!aStack.empty()) + { + const Standard_Integer aLinkIndex = aStack.top(); + aStack.pop(); + + aUsedLinks.Add(aLinkIndex); + const BRepMesh_Edge& aLink = myStructure->GetLink(aLinkIndex); + if (aLink.Movability() != BRepMesh_Frontier) + { + const BRepMesh_PairOfIndex& aPair = myStructure->ElementsConnectedTo(aLinkIndex); + if (aPair.Extent() == 2) + { + const BRepMesh_Triangle& aTriangle1 = myStructure->GetElement(aPair.FirstIndex()); + const BRepMesh_Triangle& aTriangle2 = myStructure->GetElement(aPair.LastIndex()); + + Standard_Integer aNodes[2][3]; + myStructure->ElementNodes(aTriangle1, aNodes[0]); + myStructure->ElementNodes(aTriangle2, aNodes[1]); + + const Standard_Integer aApexIndex[2] = { + findApexIndex(aNodes[0], aLink), + findApexIndex(aNodes[1], aLink) + }; + + if (checkCircle(aNodes[0], aNodes[1][aApexIndex[1]]) || + checkCircle(aNodes[1], aNodes[0][aApexIndex[0]])) + { + myStructure->RemoveElement(aPair.FirstIndex()); + myStructure->RemoveElement(aPair.LastIndex()); + myStructure->RemoveLink(aLinkIndex); + + addTriangleAndUpdateStack( + aNodes[0][(aApexIndex[0])], + aNodes[0][(aApexIndex[0] + 1) % 3], + aNodes[1][(aApexIndex[1])], + aUsedLinks, aStack); + + addTriangleAndUpdateStack( + aNodes[1][(aApexIndex[1])], + aNodes[1][(aApexIndex[1] + 1) % 3], + aNodes[0][(aApexIndex[0])], + aUsedLinks, aStack); + } + } + } + } +} + +//======================================================================= +//function : EraseItemsConnectedTo +//purpose : +//======================================================================= +void BRepMesh_MeshTool::EraseItemsConnectedTo( + const Standard_Integer theNodeIndex) +{ + BRepMesh_SelectorOfDataStructureOfDelaun aSelector(myStructure); + aSelector.NeighboursOfNode(theNodeIndex); + + IMeshData::MapOfIntegerInteger aLoopEdges(1, new NCollection_IncAllocator); + EraseTriangles(aSelector.Elements(), aLoopEdges); + EraseFreeLinks(aLoopEdges); + myStructure->RemoveNode(theNodeIndex); +} + +//======================================================================= +//function : CleanFrontierLinks +//purpose : +//======================================================================= +void BRepMesh_MeshTool::CleanFrontierLinks() +{ + Handle(NCollection_IncAllocator) aAlloc = new NCollection_IncAllocator; + IMeshData::MapOfInteger aTrianglesToErase; + IMeshData::MapOfIntegerInteger aLoopEdges(1, aAlloc); + + Handle(IMeshData::MapOfInteger) aFrontier = GetEdgesByType(BRepMesh_Frontier); + IMeshData::IteratorOfMapOfInteger aFrontierIt(*aFrontier); + for (; aFrontierIt.More(); aFrontierIt.Next()) + { + Standard_Integer aFrontierId = aFrontierIt.Key(); + const BRepMesh_Edge& aLink = myStructure->GetLink(aFrontierId); + + Standard_Boolean isTriangleFound = Standard_False; + const BRepMesh_PairOfIndex& aPair = myStructure->ElementsConnectedTo(aFrontierId); + for (Standard_Integer aElemIt = 1; aElemIt <= aPair.Extent() && !isTriangleFound; ++aElemIt) + { + const Standard_Integer aPriorElemId = aPair.Index(aElemIt); + const BRepMesh_Triangle& aElement = myStructure->GetElement(aPriorElemId); + const Standard_Integer(&e)[3] = aElement.myEdges; + const Standard_Boolean(&o)[3] = aElement.myOrientations; + + for (Standard_Integer n = 0; n < 3 && !isTriangleFound; ++n) + { + if (aFrontierId == e[n] && !o[n]) + { + // Destruction of external triangles on boundary edges + isTriangleFound = Standard_True; + aTrianglesToErase.Add(aPriorElemId); + + collectTrianglesOnFreeLinksAroundNodesOf(aLink, e[(n + 1) % 3], aTrianglesToErase); + collectTrianglesOnFreeLinksAroundNodesOf(aLink, e[(n + 2) % 3], aTrianglesToErase); + } + } + } + } + + EraseTriangles(aTrianglesToErase, aLoopEdges); + EraseFreeLinks(aLoopEdges); +} + +//======================================================================= +//function : EraseTriangles +//purpose : +//======================================================================= +void BRepMesh_MeshTool::EraseTriangles( + const IMeshData::MapOfInteger& theTriangles, + IMeshData::MapOfIntegerInteger& theLoopEdges) +{ + IMeshData::IteratorOfMapOfInteger aFreeTriangles(theTriangles); + for (; aFreeTriangles.More(); aFreeTriangles.Next()) + { + EraseTriangle(aFreeTriangles.Key(), theLoopEdges); + } +} + +//======================================================================= +//function : EraseTriangle +//purpose : +//======================================================================= +void BRepMesh_MeshTool::EraseTriangle( + const Standard_Integer theTriangleIndex, + IMeshData::MapOfIntegerInteger& theLoopEdges) +{ + const BRepMesh_Triangle& aElement = myStructure->GetElement(theTriangleIndex); + const Standard_Integer(&e)[3] = aElement.myEdges; + const Standard_Boolean(&o)[3] = aElement.myOrientations; + + myStructure->RemoveElement(theTriangleIndex); + + for (Standard_Integer i = 0; i < 3; ++i) + { + if (!theLoopEdges.Bind(e[i], o[i])) + { + theLoopEdges.UnBind(e[i]); + myStructure->RemoveLink(e[i]); + } + } +} + +//======================================================================= +//function : EraseFreeLinks +//purpose : +//======================================================================= +void BRepMesh_MeshTool::EraseFreeLinks() +{ + for (Standard_Integer i = 1; i <= myStructure->NbLinks(); i++) + { + if (myStructure->ElementsConnectedTo(i).IsEmpty()) + { + BRepMesh_Edge& anEdge = (BRepMesh_Edge&) myStructure->GetLink(i); + if (anEdge.Movability() == BRepMesh_Deleted) + { + continue; + } + + anEdge.SetMovability(BRepMesh_Free); + myStructure->RemoveLink(i); + } + } +} + +//======================================================================= +//function : collectTrianglesOnFreeLinksAroundNodesOf +//purpose : +//======================================================================= +void BRepMesh_MeshTool::collectTrianglesOnFreeLinksAroundNodesOf( + const BRepMesh_Edge& theConstraint, + const Standard_Integer theStartLink, + IMeshData::MapOfInteger& theTriangles) +{ + IMeshData::MapOfInteger aUsedLinks; + std::stack aStack; + aStack.push(theStartLink); + aUsedLinks.Add(theStartLink); + + while (!aStack.empty()) + { + const Standard_Integer aLinkIndex = aStack.top(); + aStack.pop(); + + const BRepMesh_Edge& aLink = myStructure->GetLink(aLinkIndex); + if (aLink.Movability() == BRepMesh_Free && + (aLink.FirstNode() == theConstraint.FirstNode() || + aLink.LastNode () == theConstraint.FirstNode() || + aLink.FirstNode() == theConstraint.LastNode () || + aLink.LastNode () == theConstraint.LastNode ())) + { + const BRepMesh_PairOfIndex& aPair = myStructure->ElementsConnectedTo(aLinkIndex); + for (Standard_Integer aElemIt = 1; aElemIt <= aPair.Extent(); ++aElemIt) + { + const Standard_Integer aIndex = aPair.Index(aElemIt); + theTriangles.Add(aIndex); + + const BRepMesh_Triangle& aElement = myStructure->GetElement(aIndex); + const Standard_Integer(&aEdges)[3] = aElement.myEdges; + + for (Standard_Integer i = 0; i < 3; ++i) + { + if (aEdges[i] != aLinkIndex && !aUsedLinks.Contains(aEdges[i])) + { + aUsedLinks.Add(aEdges[i]); + aStack .push(aEdges[i]); + } + } + } + } + } +} + +//======================================================================= +//function : EraseFreeLinks +//purpose : +//======================================================================= +void BRepMesh_MeshTool::EraseFreeLinks( + const IMeshData::MapOfIntegerInteger& theLinks) +{ + IMeshData::MapOfIntegerInteger::Iterator aFreeEdges(theLinks); + for (; aFreeEdges.More(); aFreeEdges.Next()) + { + if (myStructure->ElementsConnectedTo(aFreeEdges.Key()).IsEmpty()) + { + myStructure->RemoveLink(aFreeEdges.Key()); + } + } +} + +//======================================================================= +//function : GetEdgesByType +//purpose : +//======================================================================= +Handle(IMeshData::MapOfInteger) BRepMesh_MeshTool::GetEdgesByType( + const BRepMesh_DegreeOfFreedom theEdgeType) const +{ + Handle(IMeshData::MapOfInteger) aResult = new IMeshData::MapOfInteger; + IMeshData::IteratorOfMapOfInteger aEdgeIt(myStructure->LinksOfDomain()); + + for (; aEdgeIt.More(); aEdgeIt.Next()) + { + const BRepMesh_Edge& aEdge = myStructure->GetLink(aEdgeIt.Key()); + if (aEdge.Movability() == theEdgeType) + { + aResult->Add(aEdgeIt.Key()); + } + } + + return aResult; +} + +//======================================================================= +//function : DumpStruct +//purpose : +//======================================================================= +void BRepMesh_MeshTool::DumpTriangles(const Standard_CString theFileName, + IMeshData::MapOfInteger* theTriangles) +{ + BRep_Builder aBuilder; + TopoDS_Compound aResult; + aBuilder.MakeCompound(aResult); + + const IMeshData::MapOfInteger& aTriangles = myStructure->ElementsOfDomain(); + for (IMeshData::IteratorOfMapOfInteger aIt(aTriangles); aIt.More(); aIt.Next()) + { + if (theTriangles != NULL && !theTriangles->Contains(aIt.Key())) + continue; + + Standard_Integer aNodes[3]; + const BRepMesh_Triangle& aTri = myStructure->GetElement(aIt.Key()); + myStructure->ElementNodes(aTri, aNodes); + + const gp_XY& aV1 = myStructure->GetNode(aNodes[0]).Coord(); + const gp_XY& aV2 = myStructure->GetNode(aNodes[1]).Coord(); + const gp_XY& aV3 = myStructure->GetNode(aNodes[2]).Coord(); + + BRepBuilderAPI_MakePolygon aPoly(gp_Pnt(aV1.X(), aV1.Y(), 0.), + gp_Pnt(aV2.X(), aV2.Y(), 0.), + gp_Pnt(aV3.X(), aV3.Y(), 0.), + Standard_True); + + BRepBuilderAPI_MakeFace aFaceBuilder(gp_Pln(gp::XOY()), aPoly.Wire()); + aBuilder.Add(aResult, aFaceBuilder.Shape()); + } + + BRepTools::Write(aResult, theFileName); +} diff --git a/src/BRepMesh/BRepMesh_MeshTool.hxx b/src/BRepMesh/BRepMesh_MeshTool.hxx new file mode 100644 index 0000000000..7ca02940aa --- /dev/null +++ b/src/BRepMesh/BRepMesh_MeshTool.hxx @@ -0,0 +1,235 @@ +// Created on: 2016-08-22 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _BRepMesh_MeshTool_HeaderFile +#define _BRepMesh_MeshTool_HeaderFile + +#include +#include +#include +#include +#include +#include +#include + +#include + +//! Auxiliary tool providing API for manipulation with BRepMesh_DataStructureOfDelaun. +class BRepMesh_MeshTool : public Standard_Transient +{ +public: + + //! Helper functor intended to separate points to left and right from the constraint. + class NodeClassifier + { + public: + + NodeClassifier( + const BRepMesh_Edge& theConstraint, + const Handle(BRepMesh_DataStructureOfDelaun)& theStructure) + : myStructure(theStructure) + { + const BRepMesh_Vertex& aVertex1 = myStructure->GetNode(theConstraint.FirstNode()); + const BRepMesh_Vertex& aVertex2 = myStructure->GetNode(theConstraint.LastNode()); + + myConstraint.SetLocation(aVertex1.Coord()); + myConstraint.SetDirection(gp_Vec2d(aVertex1.Coord(), aVertex2.Coord())); + mySign = myConstraint.Direction().X() > 0; + } + + inline Standard_Boolean IsAbove(const Standard_Integer theNodeIndex) const + { + const BRepMesh_Vertex& aVertex = myStructure->GetNode(theNodeIndex); + const gp_Vec2d aNodeVec(myConstraint.Location(), aVertex.Coord()); + if (aNodeVec.SquareMagnitude() > gp::Resolution()) + { + const Standard_Real aCross = aNodeVec.Crossed(myConstraint.Direction()); + if (Abs(aCross) > gp::Resolution()) + { + return mySign ? + aCross < 0. : + aCross > 0.; + } + } + + return Standard_False; + } + + private: + + NodeClassifier (const NodeClassifier& theOther); + + void operator=(const NodeClassifier& theOther); + + private: + + const Handle(BRepMesh_DataStructureOfDelaun)& myStructure; + gp_Lin2d myConstraint; + Standard_Boolean mySign; + }; + + //! Constructor. + //! Initializes tool by the given data structure. + Standard_EXPORT BRepMesh_MeshTool(const Handle(BRepMesh_DataStructureOfDelaun)& theStructure); + + //! Destructor. + Standard_EXPORT virtual ~BRepMesh_MeshTool(); + + //! Returns data structure manipulated by this tool. + inline const Handle(BRepMesh_DataStructureOfDelaun)& GetStructure() const + { + return myStructure; + } + + //! Dumps triangles to specified file. + void DumpTriangles(const Standard_CString theFileName, IMeshData::MapOfInteger* theTriangles); + + //! Adds new triangle with specified nodes to mesh. + //! Legalizes triangle in case if it violates circle criteria. + inline void AddAndLegalizeTriangle( + const Standard_Integer thePoint1, + const Standard_Integer thePoint2, + const Standard_Integer thePoint3) + { + Standard_Integer aEdges[3]; + AddTriangle(thePoint1, thePoint2, thePoint3, aEdges); + + Legalize(aEdges[0]); + Legalize(aEdges[1]); + Legalize(aEdges[2]); + } + + //! Adds new triangle with specified nodes to mesh. + inline void AddTriangle( + const Standard_Integer thePoint1, + const Standard_Integer thePoint2, + const Standard_Integer thePoint3, + Standard_Integer (&theEdges)[3]) + { + Standard_Boolean aOri[3]; + AddLink(thePoint1, thePoint2, theEdges[0], aOri[0]); + AddLink(thePoint2, thePoint3, theEdges[1], aOri[1]); + AddLink(thePoint3, thePoint1, theEdges[2], aOri[2]); + + myStructure->AddElement(BRepMesh_Triangle(theEdges, aOri, BRepMesh_Free)); + } + + //! Adds new link to mesh. + //! Updates link index and link orientaion parameters. + inline void AddLink(const Standard_Integer theFirstNode, + const Standard_Integer theLastNode, + Standard_Integer& theLinkIndex, + Standard_Boolean& theLinkOri) + { + const Standard_Integer aLinkIt = myStructure->AddLink( + BRepMesh_Edge(theFirstNode, theLastNode, BRepMesh_Free)); + + theLinkIndex = Abs(aLinkIt); + theLinkOri = (aLinkIt > 0); + } + + //! Performs legalization of triangles connected to the specified link. + Standard_EXPORT void Legalize(const Standard_Integer theLinkIndex); + + //! Erases all elements connected to the specified artificial node. + //! In addition, erases the artificial node itself. + Standard_EXPORT void EraseItemsConnectedTo(const Standard_Integer theNodeIndex); + + //! Cleans frontier links from triangles to the right. + Standard_EXPORT void CleanFrontierLinks(); + + //! Erases the given set of triangles. + //! Fills map of loop edges forming the countour surrounding the erased triangles. + void EraseTriangles(const IMeshData::MapOfInteger& theTriangles, + IMeshData::MapOfIntegerInteger& theLoopEdges); + + //! Erases triangle with the given index and adds the free edges into the map. + //! When an edge is suppressed more than one time it is destroyed. + Standard_EXPORT void EraseTriangle(const Standard_Integer theTriangleIndex, + IMeshData::MapOfIntegerInteger& theLoopEdges); + + //! Erases all links that have no elements connected to them. + Standard_EXPORT void EraseFreeLinks(); + + //! Erases links from the specified map that have no elements connected to them. + Standard_EXPORT void EraseFreeLinks(const IMeshData::MapOfIntegerInteger& theLinks); + + //! Gives the list of edges with type defined by input parameter. + Standard_EXPORT Handle(IMeshData::MapOfInteger) GetEdgesByType(const BRepMesh_DegreeOfFreedom theEdgeType) const; + + DEFINE_STANDARD_RTTI_INLINE(BRepMesh_MeshTool, Standard_Transient) + +private: + + //! Returns True if the given point lies within circumcircle of the given triangle. + inline Standard_Boolean checkCircle( + const Standard_Integer(&aNodes)[3], + const Standard_Integer thePoint) + { + const BRepMesh_Vertex& aVertex0 = myStructure->GetNode(aNodes[0]); + const BRepMesh_Vertex& aVertex1 = myStructure->GetNode(aNodes[1]); + const BRepMesh_Vertex& aVertex2 = myStructure->GetNode(aNodes[2]); + + gp_XY aLocation; + Standard_Real aRadius; + const Standard_Boolean isOk = BRepMesh_CircleTool::MakeCircle( + aVertex0.Coord(), aVertex1.Coord(), aVertex2.Coord(), + aLocation, aRadius); + + if (isOk) + { + const BRepMesh_Vertex& aVertex = myStructure->GetNode(thePoint); + const Standard_Real aDist = (aVertex.Coord() - aLocation).SquareModulus() - (aRadius * aRadius); + return (aDist < Precision::SquareConfusion()); + } + + return Standard_False; + } + + //! Adds new triangle with the given nodes and updates + //! links stack by ones are not in used map. + inline void addTriangleAndUpdateStack( + const Standard_Integer theNode0, + const Standard_Integer theNode1, + const Standard_Integer theNode2, + const IMeshData::MapOfInteger& theUsedLinks, + std::stack& theStack) + { + Standard_Integer aEdges[3]; + AddTriangle(theNode0, theNode1, theNode2, aEdges); + + for (Standard_Integer i = 0; i < 3; ++i) + { + if (!theUsedLinks.Contains(aEdges[i])) + { + theStack.push(aEdges[i]); + } + } + } + + //! Iteratively erases triangles and their neighbours consisting + //! of free links using the given link as starting front. + //! Only triangles around the constraint's saddle nodes will be removed. + void collectTrianglesOnFreeLinksAroundNodesOf( + const BRepMesh_Edge& theConstraint, + const Standard_Integer theStartLink, + IMeshData::MapOfInteger& theTriangles); + +private: + + Handle(BRepMesh_DataStructureOfDelaun) myStructure; +}; + +#endif diff --git a/src/BRepMesh/BRepMesh_ModelBuilder.cxx b/src/BRepMesh/BRepMesh_ModelBuilder.cxx new file mode 100644 index 0000000000..1a15482cdf --- /dev/null +++ b/src/BRepMesh/BRepMesh_ModelBuilder.cxx @@ -0,0 +1,84 @@ +// Created on: 2016-04-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 +#include +#include +#include +#include + +#include +#include + +//======================================================================= +// Function: Constructor +// Purpose : +//======================================================================= +BRepMesh_ModelBuilder::BRepMesh_ModelBuilder () +{ +} + +//======================================================================= +// Function: Destructor +// Purpose : +//======================================================================= +BRepMesh_ModelBuilder::~BRepMesh_ModelBuilder () +{ +} + +//======================================================================= +// Function: Perform +// Purpose : +//======================================================================= +Handle (IMeshData_Model) BRepMesh_ModelBuilder::performInternal ( + const TopoDS_Shape& theShape, + const IMeshTools_Parameters& theParameters) +{ + Handle (BRepMeshData_Model) aModel; + + Bnd_Box aBox; + BRepBndLib::Add (theShape, aBox, Standard_False); + + if (!aBox.IsVoid ()) + { + // Build data model for further processing. + aModel = new BRepMeshData_Model (theShape); + + if (theParameters.Relative) + { + Standard_Real aMaxSize; + BRepMesh_ShapeTool::BoxMaxDimension (aBox, aMaxSize); + aModel->SetMaxSize(aMaxSize); + } + else + { + aModel->SetMaxSize(Max(theParameters.Deflection, + theParameters.DeflectionInterior)); + } + + Handle (IMeshTools_ShapeVisitor) aVisitor = + new BRepMesh_ShapeVisitor (aModel); + + IMeshTools_ShapeExplorer aExplorer (theShape); + aExplorer.Accept (aVisitor); + SetStatus (Message_Done1); + } + else + { + SetStatus (Message_Fail1); + } + + return aModel; +} diff --git a/src/BRepMesh/BRepMesh_ModelBuilder.hxx b/src/BRepMesh/BRepMesh_ModelBuilder.hxx new file mode 100644 index 0000000000..56898a1eeb --- /dev/null +++ b/src/BRepMesh/BRepMesh_ModelBuilder.hxx @@ -0,0 +1,50 @@ +// Created on: 2016-04-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _BRepMesh_ModelBuilder_HeaderFile +#define _BRepMesh_ModelBuilder_HeaderFile + +#include +#include +#include + +//! Class implements interface representing tool for discrete model building. +//! +//! The following statuses should be used by default: +//! Message_Done1 - model has been sucessfully built. +//! Message_Fail1 - empty shape. +//! Message_Fail2 - model has not been build due to unexpected reason. +class BRepMesh_ModelBuilder : public IMeshTools_ModelBuilder +{ +public: + + //! Constructor. + Standard_EXPORT BRepMesh_ModelBuilder (); + + //! Destructor. + Standard_EXPORT virtual ~BRepMesh_ModelBuilder (); + + DEFINE_STANDARD_RTTI_INLINE(BRepMesh_ModelBuilder, IMeshTools_ModelBuilder) + +protected: + + //! Creates discrete model for the given shape. + //! Returns nullptr in case of failure. + Standard_EXPORT virtual Handle (IMeshData_Model) performInternal ( + const TopoDS_Shape& theShape, + const IMeshTools_Parameters& theParameters) Standard_OVERRIDE; +}; + +#endif \ No newline at end of file diff --git a/src/BRepMesh/BRepMesh_ModelHealer.cxx b/src/BRepMesh/BRepMesh_ModelHealer.cxx new file mode 100644 index 0000000000..6ad9b83f56 --- /dev/null +++ b/src/BRepMesh/BRepMesh_ModelHealer.cxx @@ -0,0 +1,499 @@ +// Created on: 2016-06-23 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef DEBUG_HEALER +#include +#include +#include +#include +#endif + +namespace +{ + //! Decreases deflection of the given edge and tries to update discretization. + class EdgeAmplifier + { + public: + //! Constructor. + EdgeAmplifier(const IMeshTools_Parameters& theParameters) + : myParameters(theParameters) + { + } + + //! Main operator. + void operator()(const IMeshData::IEdgePtr& theDEdge) const + { + const IMeshData::IEdgeHandle aDEdge = theDEdge; + aDEdge->Clear(Standard_True); + aDEdge->SetDeflection(Max(aDEdge->GetDeflection() / 3., Precision::Confusion())); + + const IMeshData::IPCurveHandle& aPCurve = aDEdge->GetPCurve(0); + const IMeshData::IFaceHandle aDFace = aPCurve->GetFace(); + Handle(IMeshTools_CurveTessellator) aTessellator = + BRepMesh_EdgeDiscret::CreateEdgeTessellator( + aDEdge, aPCurve->GetOrientation(), aDFace, myParameters); + + BRepMesh_EdgeDiscret::Tessellate3d(aDEdge, aTessellator, Standard_False); + BRepMesh_EdgeDiscret::Tessellate2d(aDEdge, Standard_False); + } + + private: + + EdgeAmplifier (const EdgeAmplifier& theOther); + + void operator=(const EdgeAmplifier& theOther); + + private: + const IMeshTools_Parameters& myParameters; + }; + + //! Returns True if some of two vertcies is same with reference one. + inline Standard_Boolean isSameWithSomeOf( + const TopoDS_Vertex& theRefVertex, + const TopoDS_Vertex& theVertex1, + const TopoDS_Vertex& theVertex2) + { + return (theRefVertex.IsSame(theVertex1) || + theRefVertex.IsSame(theVertex2)); + } + + //! Returns True if some of two vertcies is within tolerance of reference one. + inline Standard_Boolean isInToleranceWithSomeOf( + const gp_Pnt& theRefPoint, + const gp_Pnt& thePoint1, + const gp_Pnt& thePoint2, + const Standard_Real theTol) + { + const Standard_Real aSqTol = theTol * theTol; + return (theRefPoint.SquareDistance(thePoint1) < aSqTol || + theRefPoint.SquareDistance(thePoint2) < aSqTol); + } +} + +//======================================================================= +// Function: Constructor +// Purpose : +//======================================================================= +BRepMesh_ModelHealer::BRepMesh_ModelHealer() +{ +} + +//======================================================================= +// Function: Destructor +// Purpose : +//======================================================================= +BRepMesh_ModelHealer::~BRepMesh_ModelHealer() +{ +} + +//======================================================================= +// Function: Perform +// Purpose : +//======================================================================= +Standard_Boolean BRepMesh_ModelHealer::performInternal( + const Handle(IMeshData_Model)& theModel, + const IMeshTools_Parameters& theParameters) +{ + myModel = theModel; + myParameters = theParameters; + if (myModel.IsNull()) + { + return Standard_False; + } + + // MinSize is made as a constant. It is connected with + // the fact that too rude discretisation can lead to + // self-intersecting polygon, which cannot be fixed. + // As result the face will not be triangulated at all. + // E.g. see "Test mesh standard_mesh C7", the face #17. + myParameters.MinSize = Precision::Confusion(); + + myFaceIntersectingEdges = new IMeshData::DMapOfIFacePtrsMapOfIEdgePtrs; + for (Standard_Integer aFaceIt = 0; aFaceIt < myModel->FacesNb(); ++aFaceIt) + { + myFaceIntersectingEdges->Bind(myModel->GetFace(aFaceIt).get(), Handle(IMeshData::MapOfIEdgePtr)()); + } + + // TODO: Here we can process edges in order to remove close discrete points. + OSD_Parallel::For(0, myModel->FacesNb(), *this, !isParallel()); + amplifyEdges(); + + IMeshData::DMapOfIFacePtrsMapOfIEdgePtrs::Iterator aFaceIt(*myFaceIntersectingEdges); + for (; aFaceIt.More(); aFaceIt.Next()) + { + if (!aFaceIt.Value().IsNull()) + { + const IMeshData::IFaceHandle aDFace = aFaceIt.Key(); + aDFace->SetStatus(IMeshData_SelfIntersectingWire); + aDFace->SetStatus(IMeshData_Failure); + } + } + + myFaceIntersectingEdges.Nullify(); + myModel.Nullify(); // Do not hold link to model. + return Standard_True; +} + +//======================================================================= +// Function: amplifyEdges +// Purpose : +//======================================================================= +void BRepMesh_ModelHealer::amplifyEdges() +{ + Handle(NCollection_IncAllocator) aTmpAlloc = + new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE); + + Standard_Integer aAmpIt = 0; + const Standard_Real aIterNb = 5; + IMeshData::MapOfIEdgePtr aEdgesToUpdate(1, aTmpAlloc); + while (aAmpIt++ < aIterNb && popEdgesToUpdate(aEdgesToUpdate)) + { + // Try to update discretization by decreasing deflection of problematic edges. + OSD_Parallel::ForEach(aEdgesToUpdate.cbegin(), aEdgesToUpdate.cend(), + EdgeAmplifier(myParameters), + !(myParameters.InParallel && aEdgesToUpdate.Size() > 1), + aEdgesToUpdate.Size()); + + IMeshData::MapOfIFacePtr aFacesToCheck(1, aTmpAlloc); + IMeshData::MapOfIEdgePtr::Iterator aEdgeIt(aEdgesToUpdate); + for (; aEdgeIt.More(); aEdgeIt.Next()) + { + const IMeshData::IEdgeHandle aDEdge = aEdgeIt.Value(); + for (Standard_Integer aPCurveIt = 0; aPCurveIt < aDEdge->PCurvesNb(); ++aPCurveIt) + { + aFacesToCheck.Add(aDEdge->GetPCurve(aPCurveIt)->GetFace()); + } + } + + OSD_Parallel::ForEach(aFacesToCheck.cbegin(), aFacesToCheck.cend(), + *this, !(myParameters.InParallel && aFacesToCheck.Size() > 1), + aFacesToCheck.Size()); + + aEdgesToUpdate.Clear(); + aTmpAlloc->Reset(Standard_False); + } +} + +//======================================================================= +// Function: popEdgesToUpdate +// Purpose : +//======================================================================= +Standard_Boolean BRepMesh_ModelHealer::popEdgesToUpdate( + IMeshData::MapOfIEdgePtr& theEdgesToUpdate) +{ + IMeshData::DMapOfIFacePtrsMapOfIEdgePtrs::Iterator aFaceIt(*myFaceIntersectingEdges); + for (; aFaceIt.More(); aFaceIt.Next()) + { + Handle(IMeshData::MapOfIEdgePtr)& aIntersections = aFaceIt.ChangeValue(); + if (!aIntersections.IsNull()) + { + theEdgesToUpdate.Unite(*aIntersections); + aIntersections.Nullify(); + } + } + + return !theEdgesToUpdate.IsEmpty(); +} + +//======================================================================= +// Function: process +// Purpose : +//======================================================================= +void BRepMesh_ModelHealer::process(const IMeshData::IFaceHandle& theDFace) const +{ + try + { + OCC_CATCH_SIGNALS + + Handle(IMeshData::MapOfIEdgePtr)& aIntersections = myFaceIntersectingEdges->ChangeFind(theDFace.get()); + aIntersections.Nullify(); + + fixFaceBoundaries(theDFace); + + if (!theDFace->IsSet(IMeshData_Failure)) + { + BRepMesh_FaceChecker aChecker(theDFace, myParameters); + if (!aChecker.Perform()) + { +#ifdef DEBUG_HEALER + std::cout << "Failed : #" << aChecker.GetIntersectingEdges()->Size() << std::endl; +#endif + aIntersections = aChecker.GetIntersectingEdges(); + } + else + { + if (theDFace->WiresNb () == 1) + { + const IMeshData::IWireHandle& aDWire = theDFace->GetWire (0); + + if (aDWire->EdgesNb () == 2) + { + const IMeshData::IEdgePtr& aDEdge0 = aDWire->GetEdge (0); + const IMeshData::IEdgePtr& aDEdge1 = aDWire->GetEdge (1); + + const IMeshData::IPCurveHandle& aPCurve0 = aDEdge0->GetPCurve (theDFace.get (), aDWire->GetEdgeOrientation (0)); + const IMeshData::IPCurveHandle& aPCurve1 = aDEdge1->GetPCurve (theDFace.get (), aDWire->GetEdgeOrientation (1)); + + if (aPCurve0->ParametersNb () == 2 && aPCurve1->ParametersNb () == 2) + { + aIntersections = new IMeshData::MapOfIEdgePtr; + // a kind of degenerated face - 1 wire, 2 edges and both edges are very small + aIntersections->Add (aDEdge0); + aIntersections->Add (aDEdge1); + } + } + } + } + } + } + catch (Standard_Failure const&) + { + theDFace->SetStatus (IMeshData_Failure); + } +} + +//======================================================================= +// Function: fixFaceBoundaries +// Purpose : +//======================================================================= +void BRepMesh_ModelHealer::fixFaceBoundaries(const IMeshData::IFaceHandle& theDFace) const +{ +#ifdef DEBUG_HEALER + TopoDS_Compound aComp; + BRep_Builder aBuilder; + aBuilder.MakeCompound(aComp); +#endif + + for (int aWireIt = 0; aWireIt < theDFace->WiresNb(); ++aWireIt) + { + const IMeshData::IWireHandle& aDWire = theDFace->GetWire(aWireIt); + BRepMesh_Deflection::ComputeDeflection(aDWire, myParameters); + for (int aEdgeIt = 0; aEdgeIt < aDWire->EdgesNb(); ++aEdgeIt) + { + const int aPrevEdgeIt = (aEdgeIt + aDWire->EdgesNb() - 1) % aDWire->EdgesNb(); + const int aNextEdgeIt = (aEdgeIt + 1) % aDWire->EdgesNb(); + + const IMeshData::IEdgeHandle aPrevEdge = aDWire->GetEdge(aPrevEdgeIt); + const IMeshData::IEdgeHandle aCurrEdge = aDWire->GetEdge(aEdgeIt); + const IMeshData::IEdgeHandle aNextEdge = aDWire->GetEdge(aNextEdgeIt); + + Standard_Boolean isConnected = !getCommonVertex(aCurrEdge, aNextEdge).IsNull() && + !getCommonVertex(aPrevEdge, aCurrEdge).IsNull(); + + if (isConnected) + { + const IMeshData::IPCurveHandle& aPrevPCurve = + aPrevEdge->GetPCurve(theDFace.get(), aDWire->GetEdgeOrientation(aPrevEdgeIt)); + + const IMeshData::IPCurveHandle& aCurrPCurve = + aCurrEdge->GetPCurve(theDFace.get(), aDWire->GetEdgeOrientation(aEdgeIt)); + + const IMeshData::IPCurveHandle& aNextPCurve = + aNextEdge->GetPCurve(theDFace.get(), aDWire->GetEdgeOrientation(aNextEdgeIt)); + + isConnected = connectClosestPoints(aPrevPCurve, aCurrPCurve, aNextPCurve); + +#ifdef DEBUG_HEALER + BRepBuilderAPI_MakePolygon aPoly; + for (int i = 0; i < aCurrPCurve->ParametersNb(); ++i) + { + const gp_Pnt2d& aPnt = aCurrPCurve->GetPoint(i); + aPoly.Add(gp_Pnt(aPnt.X(), aPnt.Y(), 0.)); + } + + if (aPoly.IsDone()) + { + aBuilder.Add(aComp, aPoly.Shape()); + } + TCollection_AsciiString aName("face_discr.brep"); + BRepTools::Write(aComp, aName.ToCString()); +#endif + } + + if (!isConnected || aCurrEdge->IsSet(IMeshData_Outdated)) + { + // We have to clean face from triangulation. + theDFace->SetStatus(IMeshData_Outdated); + + if (!isConnected) + { + // Just mark wire as open, but continue fixing other inconsistencies + // in hope that this data could be suitable to build mesh somehow. + aDWire->SetStatus(IMeshData_OpenWire); + } + } + } + } + +#ifdef DEBUG_HEALER + TCollection_AsciiString aName ("face_discr.brep"); + TCollection_AsciiString aFaceName("face_geom.brep"); + BRepTools::Write(aComp, aName.ToCString()); + BRepTools::Write(theDFace->GetFace(), aFaceName.ToCString()); +#endif + + BRepMesh_Deflection::ComputeDeflection(theDFace, myParameters); +} + +//======================================================================= +// Function: hasCommonVertex +// Purpose : +//======================================================================= +TopoDS_Vertex BRepMesh_ModelHealer::getCommonVertex( + const IMeshData::IEdgeHandle& theEdge1, + const IMeshData::IEdgeHandle& theEdge2) const +{ + TopoDS_Vertex aVertex1_1, aVertex1_2; + TopExp::Vertices(theEdge1->GetEdge(), aVertex1_1, aVertex1_2); + + //Test bugs moddata_2 bug428. + // restore [locate_data_file OCC428.brep] rr + // explode rr f + // explode rr_91 w + // explode rr_91_2 e + // nbshapes rr_91_2_2 + // # 0 vertices; 1 edge + + //This shape is invalid and can lead to exception in this code. + + if (aVertex1_1.IsNull() || aVertex1_2.IsNull()) + return TopoDS_Vertex(); + + if (theEdge1->GetEdge().IsSame(theEdge2->GetEdge())) + { + return aVertex1_1.IsSame(aVertex1_2) ? aVertex1_1 : TopoDS_Vertex(); + } + + TopoDS_Vertex aVertex2_1, aVertex2_2; + TopExp::Vertices(theEdge2->GetEdge(), aVertex2_1, aVertex2_2); + + if (aVertex2_1.IsNull() || aVertex2_2.IsNull()) + return TopoDS_Vertex(); + + if (isSameWithSomeOf(aVertex1_1, aVertex2_1, aVertex2_2)) + { + return aVertex1_1; + } + else if (isSameWithSomeOf(aVertex1_2, aVertex2_1, aVertex2_2)) + { + return aVertex1_2; + } + + const gp_Pnt aPnt1_1 = BRep_Tool::Pnt(aVertex1_1); + const gp_Pnt aPnt1_2 = BRep_Tool::Pnt(aVertex1_2); + const Standard_Real aTol1_1 = BRep_Tool::Tolerance(aVertex1_1); + const Standard_Real aTol1_2 = BRep_Tool::Tolerance(aVertex1_2); + + const gp_Pnt aPnt2_1 = BRep_Tool::Pnt(aVertex2_1); + const gp_Pnt aPnt2_2 = BRep_Tool::Pnt(aVertex2_2); + const Standard_Real aTol2_1 = BRep_Tool::Tolerance(aVertex2_1); + const Standard_Real aTol2_2 = BRep_Tool::Tolerance(aVertex2_2); + + if (isInToleranceWithSomeOf(aPnt1_1, aPnt2_1, aPnt2_2, aTol1_1 + Max(aTol2_1, aTol2_2))) + { + return aVertex1_1; + } + else if (isInToleranceWithSomeOf(aPnt1_2, aPnt2_1, aPnt2_2, aTol1_2 + Max(aTol2_1, aTol2_2))) + { + return aVertex1_2; + } + + return TopoDS_Vertex(); +} + +//======================================================================= +// Function: connectClosestPoints +// Purpose : +//======================================================================= +Standard_Boolean BRepMesh_ModelHealer::connectClosestPoints( + const IMeshData::IPCurveHandle& thePrevDEdge, + const IMeshData::IPCurveHandle& theCurrDEdge, + const IMeshData::IPCurveHandle& theNextDEdge) const +{ + if (thePrevDEdge->IsInternal() || + theCurrDEdge->IsInternal() || + theNextDEdge->IsInternal()) + { + return Standard_True; + } + + gp_Pnt2d& aPrevFirstUV = thePrevDEdge->GetPoint(0); + gp_Pnt2d& aPrevLastUV = thePrevDEdge->GetPoint(thePrevDEdge->ParametersNb() - 1); + + if (thePrevDEdge == theCurrDEdge) + { + // Wire consists of a single edge. + aPrevFirstUV = aPrevLastUV; + return Standard_True; + } + + gp_Pnt2d& aCurrFirstUV = theCurrDEdge->GetPoint(0); + gp_Pnt2d& aCurrLastUV = theCurrDEdge->GetPoint(theCurrDEdge->ParametersNb() - 1); + + gp_Pnt2d *aPrevUV = NULL, *aCurrPrevUV = NULL; + const Standard_Real aPrevSqDist = closestPoints(aPrevFirstUV, aPrevLastUV, + aCurrFirstUV, aCurrLastUV, + aPrevUV, aCurrPrevUV); + + gp_Pnt2d *aNextUV = NULL, *aCurrNextUV = NULL; + if (thePrevDEdge == theNextDEdge) + { + // Wire consists of two edges. Connect both ends. + aNextUV = (aPrevUV == &aPrevFirstUV) ? &aPrevLastUV : &aPrevFirstUV; + aCurrNextUV = (aCurrPrevUV == &aCurrFirstUV) ? &aCurrLastUV : &aCurrFirstUV; + + *aNextUV = *aCurrNextUV; + *aPrevUV = *aCurrPrevUV; + return Standard_True; + } + + gp_Pnt2d& aNextFirstUV = theNextDEdge->GetPoint(0); + gp_Pnt2d& aNextLastUV = theNextDEdge->GetPoint(theNextDEdge->ParametersNb() - 1); + + const Standard_Real aNextSqDist = closestPoints(aNextFirstUV, aNextLastUV, + aCurrFirstUV, aCurrLastUV, + aNextUV, aCurrNextUV); + +#ifdef DEBUG_HEALER + std::cout << "PrevSqDist = " << aPrevSqDist << std::endl; + std::cout << "NextSqDist = " << aNextSqDist << std::endl; +#endif + + // Connect closest points first. This can help to identify + // which ends should be connected in case of gap. + if (aPrevSqDist - aNextSqDist > gp::Resolution()) + { + adjustSamePoints(aCurrNextUV, aNextUV, aCurrPrevUV, aPrevUV, aCurrFirstUV, aCurrLastUV, aPrevFirstUV, aPrevLastUV); + } + else + { + adjustSamePoints(aCurrPrevUV, aPrevUV, aCurrNextUV, aNextUV, aCurrFirstUV, aCurrLastUV, aNextFirstUV, aNextLastUV); + } + + return Standard_True; +} diff --git a/src/BRepMesh/BRepMesh_ModelHealer.hxx b/src/BRepMesh/BRepMesh_ModelHealer.hxx new file mode 100644 index 0000000000..2e95c02da4 --- /dev/null +++ b/src/BRepMesh/BRepMesh_ModelHealer.hxx @@ -0,0 +1,185 @@ +// Created on: 2016-06-23 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _BRepMesh_ModelHealer_HeaderFile +#define _BRepMesh_ModelHealer_HeaderFile + +#include +#include +#include +#include +#include + +//! Class implements functionality of model healer tool. +//! Iterates over model's faces and checks consistency of their wires, +//! i.e.whether wires are closed and do not contain self - intersections. +//! In case if wire contains disconnected parts, ends of adjacent edges +//! forming the gaps are connected in parametric space forcibly. The notion +//! of this operation is to create correct discrete model defined relatively +//! parametric space of target face taking into account connectivity and +//! tolerances of 3D space only. This means that there are no specific +//! computations are made for the sake of determination of U and V tolerance. +//! Registers intersections on edges forming the face's shape and tries to +//! amplify discrete represenation by decreasing of deflection for the target edge. +//! Checks can be performed in parallel mode. +class BRepMesh_ModelHealer : public IMeshTools_ModelAlgo +{ +public: + + //! Constructor. + Standard_EXPORT BRepMesh_ModelHealer(); + + //! Destructor. + Standard_EXPORT virtual ~BRepMesh_ModelHealer(); + + //! Functor API to discretize the given edge. + inline void operator() (const Standard_Integer theEdgeIndex) const { + process(theEdgeIndex); + } + + //! Functor API to discretize the given edge. + inline void operator() (const IMeshData::IFaceHandle& theDFace) const { + process(theDFace); + } + + DEFINE_STANDARD_RTTI_INLINE(BRepMesh_ModelHealer, IMeshTools_ModelAlgo) + +protected: + + //! Performs processing of edges of the given model. + Standard_EXPORT virtual Standard_Boolean performInternal ( + const Handle(IMeshData_Model)& theModel, + const IMeshTools_Parameters& theParameters) Standard_OVERRIDE; + +private: + + //! Checks existing discretization of the face and updates data model. + inline void process(const Standard_Integer theFaceIndex) const + { + const IMeshData::IFaceHandle& aDFace = myModel->GetFace(theFaceIndex); + process(aDFace); + } + + //! Checks existing discretization of the face and updates data model. + void process(const IMeshData::IFaceHandle& theDFace) const; + + //! Amplifies discretization of edges in case if self-intersection problem has been found. + void amplifyEdges(); + + //! Returns common vertex of two edges or null ptr in case if there is no such vertex. + TopoDS_Vertex getCommonVertex( + const IMeshData::IEdgeHandle& theEdge1, + const IMeshData::IEdgeHandle& theEdge2) const; + + //! Connects pcurves of previous and current edge on the specified face + //! according to topological connectivity. Uses next edge in order to + //! identify closest point in case of signle vertex shared between both + //! ends of edge (degenerative edge) + Standard_Boolean connectClosestPoints( + const IMeshData::IPCurveHandle& thePrevDEdge, + const IMeshData::IPCurveHandle& theCurrDEdge, + const IMeshData::IPCurveHandle& theNextDEdge) const; + + //! Chooses the most closest point to reference one from the given pair. + //! Returns square distance between reference point and closest one as + //! well as pointer to closest point. + inline Standard_Real closestPoint( + gp_Pnt2d& theRefPnt, + gp_Pnt2d& theFristPnt, + gp_Pnt2d& theSecondPnt, + gp_Pnt2d*& theClosestPnt) const + { + // Find the most closest end-points. + const Standard_Real aSqDist1 = theRefPnt.SquareDistance(theFristPnt); + const Standard_Real aSqDist2 = theRefPnt.SquareDistance(theSecondPnt); + if (aSqDist1 < aSqDist2) + { + theClosestPnt = &theFristPnt; + return aSqDist1; + } + + theClosestPnt = &theSecondPnt; + return aSqDist2; + } + + //! Chooses the most closest points among the given to reference one from the given pair. + //! Returns square distance between reference point and closest one as + //! well as pointer to closest point. + inline Standard_Real closestPoints( + gp_Pnt2d& theFirstPnt1, + gp_Pnt2d& theSecondPnt1, + gp_Pnt2d& theFirstPnt2, + gp_Pnt2d& theSecondPnt2, + gp_Pnt2d*& theClosestPnt1, + gp_Pnt2d*& theClosestPnt2) const + { + gp_Pnt2d *aCurrPrevUV1 = NULL, *aCurrPrevUV2 = NULL; + const Standard_Real aSqDist1 = closestPoint(theFirstPnt1, theFirstPnt2, theSecondPnt2, aCurrPrevUV1); + const Standard_Real aSqDist2 = closestPoint(theSecondPnt1, theFirstPnt2, theSecondPnt2, aCurrPrevUV2); + if (aSqDist1 - aSqDist2 < gp::Resolution()) + { + theClosestPnt1 = &theFirstPnt1; + theClosestPnt2 = aCurrPrevUV1; + return aSqDist1; + } + + theClosestPnt1 = &theSecondPnt1; + theClosestPnt2 = aCurrPrevUV2; + return aSqDist2; + } + + //! Adjusts the given pair of points supposed to be the same. + //! In addition, adjusts another end-point of an edge in order + //! to perform correct matching in case of gap. + inline void adjustSamePoints( + gp_Pnt2d*& theMajorSamePnt1, + gp_Pnt2d*& theMinorSamePnt1, + gp_Pnt2d*& theMajorSamePnt2, + gp_Pnt2d*& theMinorSamePnt2, + gp_Pnt2d& theMajorFirstPnt, + gp_Pnt2d& theMajorLastPnt, + gp_Pnt2d& theMinorFirstPnt, + gp_Pnt2d& theMinorLastPnt) const + { + if (theMajorSamePnt2 == theMajorSamePnt1) + { + theMajorSamePnt2 = (theMajorSamePnt2 == &theMajorFirstPnt) ? &theMajorLastPnt : &theMajorFirstPnt; + closestPoint(*theMajorSamePnt2, theMinorFirstPnt, theMinorLastPnt, theMinorSamePnt2); + } + + *theMajorSamePnt1 = *theMinorSamePnt1; + *theMajorSamePnt2 = *theMinorSamePnt2; + } + + //! Connects ends of pcurves of face's wires according to topological coherency. + void fixFaceBoundaries(const IMeshData::IFaceHandle& theDFace) const; + + //! Returns True if check can be done in parallel. + inline Standard_Boolean isParallel() const + { + return (myParameters.InParallel && myModel->FacesNb() > 1); + } + + //! Collects unique edges to be updated from face map. Clears data stored in face map. + Standard_Boolean popEdgesToUpdate(IMeshData::MapOfIEdgePtr& theEdgesToUpdate); + +private: + + Handle(IMeshData_Model) myModel; + IMeshTools_Parameters myParameters; + Handle(IMeshData::DMapOfIFacePtrsMapOfIEdgePtrs) myFaceIntersectingEdges; +}; + +#endif \ No newline at end of file diff --git a/src/BRepMesh/BRepMesh_ModelPostProcessor.cxx b/src/BRepMesh/BRepMesh_ModelPostProcessor.cxx new file mode 100644 index 0000000000..23150517d5 --- /dev/null +++ b/src/BRepMesh/BRepMesh_ModelPostProcessor.cxx @@ -0,0 +1,192 @@ +// Created on: 2016-07-04 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 +#include +#include +#include +#include +#include + +namespace +{ + //! Commits 3D polygons and polygons on triangulations for corresponding edges. + class PolygonCommitter + { + public: + //! Constructor + PolygonCommitter(const Handle(IMeshData_Model)& theModel) + : myModel(theModel) + { + } + + //! Main functor. + void operator()(const Standard_Integer theEdgeIndex) const + { + const IMeshData::IEdgeHandle& aDEdge = myModel->GetEdge(theEdgeIndex); + if (aDEdge->GetCurve()->ParametersNb() == 0) + return; + + if (aDEdge->IsFree()) + { + if (!aDEdge->IsSet(IMeshData_Reused)) + { + commitPolygon3D(aDEdge); + } + } + else + { + commitPolygons(aDEdge); + } + } + + private: + + //! Commits 3d polygon to topological edge + void commitPolygon3D(const IMeshData::IEdgeHandle& theDEdge) const + { + const IMeshData::ICurveHandle& aCurve = theDEdge->GetCurve(); + + TColgp_Array1OfPnt aNodes (1, aCurve->ParametersNb()); + TColStd_Array1OfReal aUVNodes(1, aCurve->ParametersNb()); + for (Standard_Integer i = 1; i <= aCurve->ParametersNb(); ++i) + { + aNodes (i) = aCurve->GetPoint (i - 1); + aUVNodes(i) = aCurve->GetParameter(i - 1); + } + + Handle(Poly_Polygon3D) aPoly3D = new Poly_Polygon3D(aNodes, aUVNodes); + aPoly3D->Deflection(theDEdge->GetDeflection()); + + BRepMesh_ShapeTool::UpdateEdge(theDEdge->GetEdge(), aPoly3D); + } + + //! Commits all polygons on triangulations correspondent to the given edge. + void commitPolygons(const IMeshData::IEdgeHandle& theDEdge) const + { + // Collect pcurves associated with the given edge on the specific surface. + IMeshData::IDMapOfIFacePtrsListOfIPCurves aMapOfPCurves; + for (Standard_Integer aPCurveIt = 0; aPCurveIt < theDEdge->PCurvesNb(); ++aPCurveIt) + { + const IMeshData::IPCurveHandle& aPCurve = theDEdge->GetPCurve(aPCurveIt); + const IMeshData::IFacePtr& aDFacePtr = aPCurve->GetFace(); + const IMeshData::IFaceHandle aDFace = aDFacePtr; + if (aDFace->IsSet(IMeshData_Failure) || + aDFace->IsSet(IMeshData_Reused)) + { + continue; + } + + if (!aMapOfPCurves.Contains(aDFacePtr)) + { + aMapOfPCurves.Add(aDFacePtr, IMeshData::ListOfIPCurves()); + } + + IMeshData::ListOfIPCurves& aPCurves = aMapOfPCurves.ChangeFromKey(aDFacePtr); + aPCurves.Append(aPCurve); + } + + // Commit polygons related to separate face. + const TopoDS_Edge& aEdge = theDEdge->GetEdge(); + IMeshData::IDMapOfIFacePtrsListOfIPCurves::Iterator aPolygonIt(aMapOfPCurves); + for (; aPolygonIt.More(); aPolygonIt.Next()) + { + const TopoDS_Face& aFace = aPolygonIt.Key()->GetFace(); + + TopLoc_Location aLoc; + const Handle(Poly_Triangulation)& aTriangulation = + BRep_Tool::Triangulation(aFace, aLoc); + + if (!aTriangulation.IsNull()) + { + const IMeshData::ListOfIPCurves& aPCurves = aPolygonIt.Value(); + if (aPCurves.Size() == 2) + { + BRepMesh_ShapeTool::UpdateEdge( + aEdge, + collectPolygon(aPCurves.First(), theDEdge->GetDeflection()), + collectPolygon(aPCurves.Last (), theDEdge->GetDeflection()), + aTriangulation, aLoc); + } + else + { + BRepMesh_ShapeTool::UpdateEdge( + aEdge, + collectPolygon(aPCurves.First(), theDEdge->GetDeflection()), + aTriangulation, aLoc); + } + } + } + } + + //! Collects polygonal data for the given pcurve + Handle(Poly_PolygonOnTriangulation) collectPolygon( + const IMeshData::IPCurveHandle& thePCurve, + const Standard_Real theDeflection) const + { + TColStd_Array1OfInteger aNodes (1, thePCurve->ParametersNb()); + TColStd_Array1OfReal aParams(1, thePCurve->ParametersNb()); + for (Standard_Integer i = 1; i <= thePCurve->ParametersNb(); ++i) + { + aNodes (i) = thePCurve->GetIndex (i - 1); + aParams(i) = thePCurve->GetParameter(i - 1); + } + + Handle(Poly_PolygonOnTriangulation) aPolygon = + new Poly_PolygonOnTriangulation(aNodes, aParams); + + aPolygon->Deflection(theDeflection); + return aPolygon; + } + + private: + + Handle(IMeshData_Model) myModel; + }; +} + +//======================================================================= +// Function: Constructor +// Purpose : +//======================================================================= +BRepMesh_ModelPostProcessor::BRepMesh_ModelPostProcessor() +{ +} + +//======================================================================= +// Function: Destructor +// Purpose : +//======================================================================= +BRepMesh_ModelPostProcessor::~BRepMesh_ModelPostProcessor() +{ +} + +//======================================================================= +// Function: Perform +// Purpose : +//======================================================================= +Standard_Boolean BRepMesh_ModelPostProcessor::performInternal( + const Handle(IMeshData_Model)& theModel, + const IMeshTools_Parameters& /*theParameters*/) +{ + if (theModel.IsNull()) + { + return Standard_False; + } + + // TODO: Force single threaded solution due to data races on edges sharing the same TShape + OSD_Parallel::For(0, theModel->EdgesNb(), PolygonCommitter(theModel), Standard_True/*!theParameters.InParallel*/); + return Standard_True; +} diff --git a/src/BRepMesh/BRepMesh_ModelPostProcessor.hxx b/src/BRepMesh/BRepMesh_ModelPostProcessor.hxx new file mode 100644 index 0000000000..129ba74b9e --- /dev/null +++ b/src/BRepMesh/BRepMesh_ModelPostProcessor.hxx @@ -0,0 +1,45 @@ +// Created on: 2016-07-22 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _BRepMesh_ModelPostProcessor_HeaderFile +#define _BRepMesh_ModelPostProcessor_HeaderFile + +#include +#include +#include + +//! Class implements functionality of model post-processing tool. +//! Stores polygons on triangulations to TopoDS_Edge. +class BRepMesh_ModelPostProcessor : public IMeshTools_ModelAlgo +{ +public: + + //! Constructor. + Standard_EXPORT BRepMesh_ModelPostProcessor(); + + //! Destructor. + Standard_EXPORT virtual ~BRepMesh_ModelPostProcessor(); + + DEFINE_STANDARD_RTTI_INLINE(BRepMesh_ModelPostProcessor, IMeshTools_ModelAlgo) + +protected: + + //! Performs processing of edges of the given model. + Standard_EXPORT virtual Standard_Boolean performInternal ( + const Handle(IMeshData_Model)& theModel, + const IMeshTools_Parameters& theParameters) Standard_OVERRIDE; +}; + +#endif diff --git a/src/BRepMesh/BRepMesh_ModelPreProcessor.cxx b/src/BRepMesh/BRepMesh_ModelPreProcessor.cxx new file mode 100644 index 0000000000..c9d02d486b --- /dev/null +++ b/src/BRepMesh/BRepMesh_ModelPreProcessor.cxx @@ -0,0 +1,307 @@ +// Created on: 2016-07-04 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 +#include +#include +#include +#include +#include +#include +#include +#include + +namespace +{ + //! Checks consistency of triangulation stored in topological face. + class TriangulationConsistency + { + public: + //! Constructor + TriangulationConsistency(const Handle(IMeshData_Model)& theModel) + : myModel (theModel) + { + } + + //! Main functor. + void operator()(const Standard_Integer theFaceIndex) const + { + const IMeshData::IFaceHandle& aDFace = myModel->GetFace(theFaceIndex); + if (aDFace->IsSet(IMeshData_Outdated)) + { + return; + } + + TopLoc_Location aLoc; + const Handle(Poly_Triangulation)& aTriangulation = + BRep_Tool::Triangulation(aDFace->GetFace(), aLoc); + + if (!aTriangulation.IsNull()) + { + Standard_Boolean isTriangulationConsistent = + aTriangulation->Deflection() < 1.1 * aDFace->GetDeflection(); + + if (isTriangulationConsistent) + { + // #25080: check that indices of links forming triangles are in range. + const Standard_Integer aNodesNb = aTriangulation->NbNodes(); + const Poly_Array1OfTriangle& aTriangles = aTriangulation->Triangles(); + + Standard_Integer i = aTriangles.Lower(); + for (; i <= aTriangles.Upper() && isTriangulationConsistent; ++i) + { + const Poly_Triangle& aTriangle = aTriangles(i); + + Standard_Integer aNode[3]; + aTriangle.Get(aNode[0], aNode[1], aNode[2]); + for (Standard_Integer j = 0; j < 3 && isTriangulationConsistent; ++j) + { + isTriangulationConsistent = (aNode[j] >= 1 && aNode[j] <= aNodesNb); + } + } + } + + if (isTriangulationConsistent) + { + aDFace->SetStatus(IMeshData_Reused); + aDFace->SetDeflection(aTriangulation->Deflection()); + } + else + { + aDFace->SetStatus(IMeshData_Outdated); + } + } + } + + private: + + Handle(IMeshData_Model) myModel; + }; + + //! Adds additional points to seam edges on specific surfaces. + class SeamEdgeAmplifier + { + public: + //! Constructor + SeamEdgeAmplifier(const Handle(IMeshData_Model)& theModel, + const IMeshTools_Parameters& theParameters) + : myModel (theModel) + , myParameters (theParameters) + { + } + + //! Main functor. + void operator()(const Standard_Integer theFaceIndex) const + { + const IMeshData::IFaceHandle& aDFace = myModel->GetFace(theFaceIndex); + if (aDFace->GetSurface()->GetType() != GeomAbs_Cone) + { + return; + } + + const IMeshData::IWireHandle& aDWire = aDFace->GetWire (0); + for (Standard_Integer aEdgeIdx = 0; aEdgeIdx < aDWire->EdgesNb() - 1; ++aEdgeIdx) + { + const IMeshData::IEdgePtr& aDEdge = aDWire->GetEdge (aEdgeIdx); + + if (aDEdge->GetPCurve(aDFace.get(), TopAbs_FORWARD) != aDEdge->GetPCurve(aDFace.get(), TopAbs_REVERSED)) + { + if (aDEdge->GetCurve()->ParametersNb() == 2) + { + if (splitEdge (aDEdge, Abs (getConeStep (aDFace)))) + { + TopLoc_Location aLoc; + const Handle (Poly_Triangulation)& aTriangulation = + BRep_Tool::Triangulation (aDFace->GetFace (), aLoc); + + if (!aTriangulation.IsNull ()) + { + aDFace->SetStatus (IMeshData_Outdated); + } + } + } + return; + } + } + } + + private: + + //! Returns step for splitting seam edge of a cone. + Standard_Real getConeStep(const IMeshData::IFaceHandle& theDFace) const + { + BRepMesh_ConeRangeSplitter aSplitter; + aSplitter.Reset (theDFace, myParameters); + + const IMeshData::IWireHandle& aDWire = theDFace->GetWire (0); + for (Standard_Integer aEdgeIt = 0; aEdgeIt < aDWire->EdgesNb(); ++aEdgeIt) + { + const IMeshData::IEdgeHandle aDEdge = aDWire->GetEdge(aEdgeIt); + const IMeshData::IPCurveHandle& aPCurve = aDEdge->GetPCurve( + theDFace.get(), aDWire->GetEdgeOrientation(aEdgeIt)); + + for (Standard_Integer aPointIt = 0; aPointIt < aPCurve->ParametersNb(); ++aPointIt) + { + const gp_Pnt2d& aPnt2d = aPCurve->GetPoint(aPointIt); + aSplitter.AddPoint(aPnt2d); + } + } + + std::pair aStepsNb; + std::pair aSteps = aSplitter.GetSplitSteps (myParameters, aStepsNb); + return aSteps.second; + } + + //! Splits 3D and all pcurves accoring using the specified step. + Standard_Boolean splitEdge(const IMeshData::IEdgePtr& theDEdge, + const Standard_Real theDU) const + { + if (!splitCurve (theDEdge->GetCurve (), theDU)) + { + return Standard_False; + } + + for (Standard_Integer aPCurveIdx = 0; aPCurveIdx < theDEdge->PCurvesNb(); ++aPCurveIdx) + { + splitCurve (theDEdge->GetPCurve (aPCurveIdx), theDU); + } + + return Standard_True; + } + + //! Splits the given curve using the specified step. + template + Standard_Boolean splitCurve(Curve& theCurve, const Standard_Real theDU) const + { + Standard_Boolean isUpdated = Standard_False; + PointType aDir = theCurve->GetPoint(theCurve->ParametersNb() - 1).Coord() - theCurve->GetPoint(0).Coord(); + const Standard_Real aModulus = aDir.Modulus(); + if (aModulus < gp::Resolution()) + { + return isUpdated; + } + aDir /= aModulus; + + const Standard_Real aLastParam = theCurve->GetParameter(theCurve->ParametersNb() - 1); + const Standard_Boolean isReversed = theCurve->GetParameter(0) > aLastParam; + for (Standard_Integer aPointIdx = 1; ; ++aPointIdx) + { + const Standard_Real aCurrParam = theCurve->GetParameter(0) + aPointIdx * theDU * (isReversed ? -1.0 : 1.0); + if (( isReversed && (aCurrParam < aLastParam)) || + (!isReversed && !(aCurrParam < aLastParam))) + { + break; + } + + theCurve->InsertPoint(theCurve->ParametersNb() - 1, + theCurve->GetPoint(0).Translated (aDir * aPointIdx * theDU), + aCurrParam); + + isUpdated = Standard_True; + } + + return isUpdated; + } + + private: + + Handle(IMeshData_Model) myModel; + IMeshTools_Parameters myParameters; + }; +} + +//======================================================================= +// Function: Constructor +// Purpose : +//======================================================================= +BRepMesh_ModelPreProcessor::BRepMesh_ModelPreProcessor() +{ +} + +//======================================================================= +// Function: Destructor +// Purpose : +//======================================================================= +BRepMesh_ModelPreProcessor::~BRepMesh_ModelPreProcessor() +{ +} + +//======================================================================= +// Function: Perform +// Purpose : +//======================================================================= +Standard_Boolean BRepMesh_ModelPreProcessor::performInternal( + const Handle(IMeshData_Model)& theModel, + const IMeshTools_Parameters& theParameters) +{ + if (theModel.IsNull()) + { + return Standard_False; + } + + OSD_Parallel::For(0, theModel->FacesNb(), SeamEdgeAmplifier(theModel, theParameters), !theParameters.InParallel); + OSD_Parallel::For(0, theModel->FacesNb(), TriangulationConsistency(theModel), !theParameters.InParallel); + + // Clean edges and faces from outdated polygons. + Handle(NCollection_IncAllocator) aTmpAlloc(new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE)); + NCollection_Map aUsedFaces(1, aTmpAlloc); + for (Standard_Integer aEdgeIt = 0; aEdgeIt < theModel->EdgesNb(); ++aEdgeIt) + { + const IMeshData::IEdgeHandle& aDEdge = theModel->GetEdge(aEdgeIt); + if (aDEdge->IsFree()) + { + if (aDEdge->IsSet(IMeshData_Outdated)) + { + TopLoc_Location aLoc; + BRep_Tool::Polygon3D(aDEdge->GetEdge(), aLoc); + BRepMesh_ShapeTool::NullifyEdge(aDEdge->GetEdge(), aLoc); + } + + continue; + } + + for (Standard_Integer aPCurveIt = 0; aPCurveIt < aDEdge->PCurvesNb(); ++aPCurveIt) + { + // Find adjacent outdated face. + const IMeshData::IFaceHandle aDFace = aDEdge->GetPCurve(aPCurveIt)->GetFace(); + if (!aUsedFaces.Contains(aDFace.get())) + { + aUsedFaces.Add(aDFace.get()); + if (aDFace->IsSet(IMeshData_Outdated)) + { + TopLoc_Location aLoc; + const Handle(Poly_Triangulation)& aTriangulation = + BRep_Tool::Triangulation(aDFace->GetFace(), aLoc); + + // Clean all edges of oudated face. + for (Standard_Integer aWireIt = 0; aWireIt < aDFace->WiresNb(); ++aWireIt) + { + const IMeshData::IWireHandle& aDWire = aDFace->GetWire(aWireIt); + for (Standard_Integer aWireEdgeIt = 0; aWireEdgeIt < aDWire->EdgesNb(); ++aWireEdgeIt) + { + const IMeshData::IEdgeHandle aTmpDEdge = aDWire->GetEdge(aWireEdgeIt); + BRepMesh_ShapeTool::NullifyEdge(aTmpDEdge->GetEdge(), aTriangulation, aLoc); + } + } + + BRepMesh_ShapeTool::NullifyFace(aDFace->GetFace()); + } + } + } + } + + return Standard_True; +} + diff --git a/src/BRepMesh/BRepMesh_ModelPreProcessor.hxx b/src/BRepMesh/BRepMesh_ModelPreProcessor.hxx new file mode 100644 index 0000000000..031053aa38 --- /dev/null +++ b/src/BRepMesh/BRepMesh_ModelPreProcessor.hxx @@ -0,0 +1,46 @@ +// Created on: 2016-07-04 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _BRepMesh_ModelPreProcessor_HeaderFile +#define _BRepMesh_ModelPreProcessor_HeaderFile + +#include +#include +#include + +//! Class implements functionality of model pre-processing tool. +//! Nullifies existing polygonal data in case if model elements +//! have IMeshData_Outdated status. +class BRepMesh_ModelPreProcessor : public IMeshTools_ModelAlgo +{ +public: + + //! Constructor. + Standard_EXPORT BRepMesh_ModelPreProcessor(); + + //! Destructor. + Standard_EXPORT virtual ~BRepMesh_ModelPreProcessor(); + + DEFINE_STANDARD_RTTI_INLINE(BRepMesh_ModelPreProcessor, IMeshTools_ModelAlgo) + +protected: + + //! Performs processing of edges of the given model. + Standard_EXPORT virtual Standard_Boolean performInternal ( + const Handle(IMeshData_Model)& theModel, + const IMeshTools_Parameters& theParameters) Standard_OVERRIDE; +}; + +#endif diff --git a/src/BRepMesh/BRepMesh_NURBSRangeSplitter.cxx b/src/BRepMesh/BRepMesh_NURBSRangeSplitter.cxx new file mode 100644 index 0000000000..332be97de3 --- /dev/null +++ b/src/BRepMesh/BRepMesh_NURBSRangeSplitter.cxx @@ -0,0 +1,583 @@ +// Created on: 2016-04-19 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 + +#include +#include +#include +#include +#include +#include +#include + +namespace +{ + class AnalyticalFilter + { + public: + //! Constructor. + AnalyticalFilter( + const IMeshData::IFaceHandle& theDFace, + const GeomAbs_IsoType theIsoType, + const Handle(IMeshData::SequenceOfReal)& theParams, + const Handle(IMeshData::SequenceOfReal)& theControlParams, + const Handle(IMeshData::MapOfReal)& theParamsForbiddenToRemove, + const Handle(IMeshData::MapOfReal)& theControlParamsForbiddenToRemove) + : myDFace(theDFace), + mySurface(myDFace->GetSurface()->ChangeSurface().Surface().Surface()), + myIsoU(theIsoType == GeomAbs_IsoU), + myParams(theParams), + myControlParams(theControlParams), + myParamsForbiddenToRemove(theParamsForbiddenToRemove), + myControlParamsForbiddenToRemove(theControlParamsForbiddenToRemove), + myAllocator(new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE)), + myControlParamsToRemove(new IMeshData::MapOfReal(1, myAllocator)) + { + } + + //! Returns map of parameters supposed to be removed. + const Handle(IMeshData::MapOfReal)& GetControlParametersToRemove( + const IMeshTools_Parameters& theParameters) + { + myParameters = theParameters; + + Standard_Integer aStartIndex, aEndIndex; + if (myIsoU) + { + aStartIndex = 1; + aEndIndex = myParams->Length(); + } + else + { + aStartIndex = 2; + aEndIndex = myParams->Length() - 1; + } + + for (Standard_Integer i = aStartIndex; i <= aEndIndex; ++i) + { + myCurrParam = myParams->Value(i); + myIso = new GeomAdaptor_Curve(myIsoU ? mySurface->UIso(myCurrParam) : mySurface->VIso(myCurrParam)); + + myPrevControlParam = myControlParams->Value(1); + myIso->D1(myPrevControlParam, myPrevControlPnt, myPrevControlVec); + for (Standard_Integer j = 2; j <= myControlParams->Length();) + { + j += checkControlPointAndMoveOn(j); + } + } + + return myControlParamsToRemove; + } + + private: + + //! Checks the given control point for deviation. + //! Returns number of steps to be used to move point iterator. + Standard_Integer checkControlPointAndMoveOn(const Standard_Integer theIndex) + { + Standard_Integer aMoveSteps = 0; + myCurrControlParam = myControlParams->Value(theIndex); + myIso->D1(myCurrControlParam, myCurrControlPnt, myCurrControlVec); + + const Standard_Real aMidParam = 0.5 * (myPrevControlParam + myCurrControlParam); + const gp_Pnt aMidPnt = myIso->Value(aMidParam); + + const Standard_Real aSqDist = BRepMesh_GeomTool::SquareDeflectionOfSegment( + myPrevControlPnt, myCurrControlPnt, aMidPnt); + + Standard_Real anAngle = 0.0; + + if ((myPrevControlVec.SquareMagnitude() > Precision::SquareConfusion()) && + (myCurrControlVec.SquareMagnitude() > Precision::SquareConfusion())) + { + anAngle = myPrevControlVec.Angle(myCurrControlVec); + } + + const Standard_Real aSqMaxDeflection = myDFace->GetDeflection() * + myDFace->GetDeflection(); + + if (((aSqDist > aSqMaxDeflection) || (anAngle > myParameters.AngleInterior)) && + aSqDist > myParameters.MinSize * myParameters.MinSize) + { + // insertion + myControlParams->InsertBefore(theIndex, aMidParam); + } + else + { + // Here we should leave at least 3 parameters as far as + // we must have at least one parameter related to surface + // internals in order to prevent movement of triangle body + // outside the surface in case of highly curved ones, e.g. + // BSpline springs. + if (((aSqDist < aSqMaxDeflection) || (anAngle < myParameters.AngleInterior)) && + myControlParams->Length() > 3 && theIndex < myControlParams->Length()) + { + // Remove too dense points + const Standard_Real aTmpParam = myControlParams->Value(theIndex + 1); + if (checkParameterForDeflectionAndUpdateCache(aTmpParam)) + { + ++aMoveSteps; + } + } + + myPrevControlParam = myCurrControlParam; + myPrevControlPnt = myCurrControlPnt; + myPrevControlVec = myCurrControlVec; + + ++aMoveSteps; + } + + return aMoveSteps; + } + + //! Checks whether the given param suits specified deflection. Updates cache. + Standard_Boolean checkParameterForDeflectionAndUpdateCache(const Standard_Real theParam) + { + gp_Pnt aTmpPnt; + gp_Vec aTmpVec; + myIso->D1(theParam, aTmpPnt, aTmpVec); + + const Standard_Real aTmpMidParam = 0.5 * (myPrevControlParam + theParam); + const gp_Pnt aTmpMidPnt = myIso->Value(aTmpMidParam); + + // Lets check next parameter. + // If it also fits deflection, we can remove previous parameter. + const Standard_Real aSqDist = BRepMesh_GeomTool::SquareDeflectionOfSegment( + myPrevControlPnt, aTmpPnt, aTmpMidPnt); + + if (aSqDist < myDFace->GetDeflection() * myDFace->GetDeflection()) + { + // Lets check parameters for angular deflection. + if (myPrevControlVec.SquareMagnitude() < gp::Resolution() || + aTmpVec.SquareMagnitude() < gp::Resolution() || + myPrevControlVec.Angle(aTmpVec) < myParameters.AngleInterior) + { + // For current Iso line we can remove this parameter. + myControlParamsToRemove->Add(myCurrControlParam); + myCurrControlParam = theParam; + myCurrControlPnt = aTmpPnt; + myCurrControlVec = aTmpVec; + return Standard_True; + } + else + { + // We have found a place on the surface refusing + // removement of this parameter. + myParamsForbiddenToRemove ->Add(myCurrParam); + myControlParamsForbiddenToRemove->Add(myCurrControlParam); + } + } + + return Standard_False; + } + + private: + + IMeshData::IFaceHandle myDFace; + Handle(Geom_Surface) mySurface; + Standard_Boolean myIsoU; + Handle(IMeshData::SequenceOfReal) myParams; + Handle(IMeshData::SequenceOfReal) myControlParams; + + Handle(IMeshData::MapOfReal) myParamsForbiddenToRemove; + Handle(IMeshData::MapOfReal) myControlParamsForbiddenToRemove; + + Handle(NCollection_IncAllocator) myAllocator; + Handle(IMeshData::MapOfReal) myControlParamsToRemove; + + + IMeshTools_Parameters myParameters; + NCollection_Handle myIso; + + Standard_Real myCurrParam; + + Standard_Real myCurrControlParam; + gp_Pnt myCurrControlPnt; + gp_Vec myCurrControlVec; + + Standard_Real myPrevControlParam; + gp_Pnt myPrevControlPnt; + gp_Vec myPrevControlVec; + }; + + //! Adds param to map if it fits specified range. + inline Standard_Boolean addParam( + const Standard_Real& theParam, + const std::pair& theRange, + IMeshData::IMapOfReal& theParams) + { + if (theParam < theRange.first || + theParam > theRange.second) + { + return Standard_False; + } + + theParams.Add(theParam); + return Standard_True; + } + + //! Initializes parameters map using CN intervals. + inline Standard_Boolean initParamsFromIntervals( + const TColStd_Array1OfReal& theIntervals, + const std::pair& theRange, + const Standard_Boolean isSplitIntervals, + IMeshData::IMapOfReal& theParams) + { + Standard_Boolean isAdded = Standard_False; + + for (Standard_Integer i = theIntervals.Lower(); i <= theIntervals.Upper(); ++i) + { + const Standard_Real aStartParam = theIntervals.Value(i); + if (addParam(aStartParam, theRange, theParams)) + { + isAdded = Standard_True; + } + + if (isSplitIntervals && i < theIntervals.Upper()) + { + const Standard_Real aMidParam = (aStartParam + theIntervals.Value(i + 1)) / 2.; + if (addParam(aMidParam, theRange, theParams)) + { + isAdded = Standard_True; + } + } + } + + return isAdded; + } + + //! Checks whether intervals should be split. + //! Returns true in case if it is impossible to compute normal + //! directly on intervals, false is returned elsewhere. + Standard_Boolean toSplitIntervals (const Handle (Geom_Surface)& theSurf, + const TColStd_Array1OfReal (&theIntervals)[2]) + { + Standard_Integer aIntervalU = theIntervals[0].Lower (); + for (; aIntervalU <= theIntervals[0].Upper (); ++aIntervalU) + { + const Standard_Real aParamU = theIntervals[0].Value(aIntervalU); + Standard_Integer aIntervalV = theIntervals[1].Lower (); + for (; aIntervalV <= theIntervals[1].Upper (); ++aIntervalV) + { + gp_Dir aNorm; + const Standard_Real aParamV = theIntervals[1].Value(aIntervalV); + if (GeomLib::NormEstim (theSurf, gp_Pnt2d (aParamU, aParamV), Precision::Confusion (), aNorm) != 0) + { + return Standard_True; + } + // TODO: do not split intervals if there is no normal in the middle of interval. + } + } + + return Standard_False; + } +} + +//======================================================================= +// Function: AdjustRange +// Purpose : +//======================================================================= +void BRepMesh_NURBSRangeSplitter::AdjustRange() +{ + BRepMesh_DefaultRangeSplitter::AdjustRange(); + mySurfaceType = GetSurface()->GetType(); + + if (mySurfaceType == GeomAbs_BezierSurface) + { + const std::pair& aRangeU = GetRangeU(); + const std::pair& aRangeV = GetRangeV(); + + myIsValid = !(aRangeU.first < -0.5 || + aRangeU.second > 1.5 || + aRangeV.first < -0.5 || + aRangeV.second > 1.5); + } +} + +//======================================================================= +// Function: GenerateSurfaceNodes +// Purpose : +//======================================================================= +Handle(IMeshData::ListOfPnt2d) BRepMesh_NURBSRangeSplitter::GenerateSurfaceNodes( + const IMeshTools_Parameters& theParameters) const +{ + if (!initParameters()) + { + return Handle(IMeshData::ListOfPnt2d)(); + } + + const std::pair& aRangeU = GetRangeU(); + const std::pair& aRangeV = GetRangeV(); + const std::pair& aDelta = GetDelta (); + + const Standard_Real aDefFace = GetDFace()->GetDeflection(); + const Handle(BRepAdaptor_HSurface)& gFace = GetSurface(); + Handle(Geom_Surface) aSurface = gFace->ChangeSurface().Surface().Surface(); + + const Handle(NCollection_IncAllocator) aTmpAlloc = + new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE); + + const Handle(IMeshData::SequenceOfReal) aParams[2] = { + computeGrainAndFilterParameters(GetParametersU(), gFace->UResolution(aDefFace), + (aRangeU.second - aRangeU.first), aDelta.first, theParameters, aTmpAlloc), + + computeGrainAndFilterParameters(GetParametersV(), gFace->VResolution(aDefFace), + (aRangeV.second - aRangeV.first), aDelta.second, theParameters, aTmpAlloc) + }; + + // check intermediate isolines + Handle(IMeshData::MapOfReal) aFixedParams[2] = { + new IMeshData::MapOfReal(1, aTmpAlloc), + new IMeshData::MapOfReal(1, aTmpAlloc) + }; + + const Handle(IMeshData::MapOfReal) aParamsToRemove[2] = { + AnalyticalFilter(GetDFace(), GeomAbs_IsoV, aParams[1], aParams[0], + aFixedParams[1], aFixedParams[0]).GetControlParametersToRemove(theParameters), + + AnalyticalFilter(GetDFace(), GeomAbs_IsoU, aParams[0], aParams[1], + aFixedParams[0], aFixedParams[1]).GetControlParametersToRemove(theParameters), + }; + + aParamsToRemove[0]->Subtract(*aFixedParams[0]); + aParamsToRemove[1]->Subtract(*aFixedParams[1]); + + // insert nodes of the regular grid + Handle(IMeshData::ListOfPnt2d) aNodes = new IMeshData::ListOfPnt2d( + new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE)); + + // insert nodes of the regular grid + for (Standard_Integer i = 1; i <= aParams[0]->Length(); ++i) + { + const Standard_Real aParam1 = aParams[0]->Value(i); + if (aParamsToRemove[0]->Contains(aParam1)) + { + continue; + } + + for (Standard_Integer j = 1; j <= aParams[1]->Length(); ++j) + { + const Standard_Real aParam2 = aParams[1]->Value(j); + if (aParamsToRemove[1]->Contains(aParam2)) + { + continue; + } + + aNodes->Append(gp_Pnt2d(aParam1, aParam2)); + } + } + + return aNodes; +} + +//======================================================================= +// Function: initParameters +// Purpose : +//======================================================================= +Standard_Boolean BRepMesh_NURBSRangeSplitter::initParameters() const +{ + const Handle(BRepAdaptor_HSurface)& aSurface = GetSurface(); + + const GeomAbs_Shape aContinuity = GeomAbs_CN; + const std::pair aIntervalsNb( + aSurface->NbUIntervals(aContinuity), + aSurface->NbVIntervals(aContinuity) + ); + + TColStd_Array1OfReal aIntervals[2] = { + TColStd_Array1OfReal(1, aIntervalsNb.first + 1), + TColStd_Array1OfReal(1, aIntervalsNb.second + 1) + }; + + aSurface->UIntervals(aIntervals[0], aContinuity); + aSurface->VIntervals(aIntervals[1], aContinuity); + + const Standard_Boolean isSplitIntervals = toSplitIntervals ( + aSurface->ChangeSurface().Surface().Surface(), aIntervals); + + if (!initParamsFromIntervals(aIntervals[0], GetRangeU(), isSplitIntervals, + const_cast(GetParametersU()))) + { + //if (!grabParamsOfEdges (Edge_Frontier, Param_U)) + { + return Standard_False; + } + } + + if (!initParamsFromIntervals(aIntervals[1], GetRangeV(), isSplitIntervals, + const_cast(GetParametersV()))) + { + //if (!grabParamsOfEdges (Edge_Frontier, Param_V)) + { + return Standard_False; + } + } + + return grabParamsOfEdges(Edge_Internal, Param_U | Param_V); +} + +//======================================================================= +//function : grabParamsOfInternalEdges +//purpose : +//======================================================================= +Standard_Boolean BRepMesh_NURBSRangeSplitter::grabParamsOfEdges ( + const EdgeType theEdgeType, + const Standard_Integer theParamDimensionFlag) const +{ + if ((theParamDimensionFlag & (Param_U | Param_V)) == 0) + { + return Standard_False; + } + + const IMeshData::IFaceHandle& aDFace = GetDFace (); + for (Standard_Integer aWireIt = 0; aWireIt < aDFace->WiresNb (); ++aWireIt) + { + const IMeshData::IWireHandle& aDWire = aDFace->GetWire (aWireIt); + for (Standard_Integer aEdgeIt = 0; aEdgeIt < aDWire->EdgesNb (); ++aEdgeIt) + { + const IMeshData::IEdgePtr& aDEdge = aDWire->GetEdge (aEdgeIt); + for (Standard_Integer aPCurveIt = 0; aPCurveIt < aDEdge->PCurvesNb (); ++aPCurveIt) + { + const IMeshData::IPCurveHandle& aDPCurve = aDEdge->GetPCurve (aPCurveIt); + if (aDPCurve->GetFace () == aDFace) + { + if (theEdgeType == Edge_Internal && !aDPCurve->IsInternal ()) + { + continue; + } + + for (Standard_Integer aPointIt = 0; aPointIt < aDPCurve->ParametersNb (); ++aPointIt) + { + const gp_Pnt2d& aPnt2d = aDPCurve->GetPoint (aPointIt); + if (theParamDimensionFlag & Param_U) + { + const_cast(GetParametersU ()).Add (aPnt2d.X ()); + } + + if (theParamDimensionFlag & Param_V) + { + const_cast(GetParametersV ()).Add (aPnt2d.Y ()); + } + } + } + } + } + } + + return Standard_True; +} + +//======================================================================= +//function : computeGrainAndFilterParameters +//purpose : +//======================================================================= +Handle(IMeshData::SequenceOfReal) BRepMesh_NURBSRangeSplitter::computeGrainAndFilterParameters( + const IMeshData::IMapOfReal& theSourceParams, + const Standard_Real theTol2d, + const Standard_Real theRangeDiff, + const Standard_Real theDelta, + const IMeshTools_Parameters& theParameters, + const Handle(NCollection_IncAllocator)& theAllocator) const +{ + // Sort and filter sequence of parameters + Standard_Real aMinDiff = Precision::PConfusion(); + if (theDelta < 1.) + { + aMinDiff /= theDelta; + } + + aMinDiff = Max(theParameters.MinSize, aMinDiff); + + const Standard_Real aDiffMaxLim = 0.1 * theRangeDiff; + const Standard_Real aDiffMinLim = Max(0.005 * theRangeDiff, + 2. * theTol2d); + const Standard_Real aDiff = Max(theParameters.MinSize, + Min(aDiffMaxLim, aDiffMinLim)); + return filterParameters(theSourceParams, aMinDiff, aDiff, theAllocator); +} + +//======================================================================= +//function : filterParameters +//purpose : +//======================================================================= +Handle(IMeshData::SequenceOfReal) BRepMesh_NURBSRangeSplitter::filterParameters( + const IMeshData::IMapOfReal& theParams, + const Standard_Real theMinDist, + const Standard_Real theFilterDist, + const Handle(NCollection_IncAllocator)& theAllocator) const +{ + Handle(IMeshData::SequenceOfReal) aResult = new IMeshData::SequenceOfReal(theAllocator); + + // Sort sequence of parameters + const Standard_Integer anInitLen = theParams.Extent(); + + if (anInitLen < 1) + { + return aResult; + } + + TColStd_Array1OfReal aParamArray(1, anInitLen); + Standard_Integer j; + for (j = 1; j <= anInitLen; j++) + aParamArray(j) = theParams(j); + + std::sort(aParamArray.begin(), aParamArray.end()); + + // mandatory pre-filtering using the first (minimal) filter value + Standard_Integer aParamLength = 1; + for (j = 2; j <= anInitLen; j++) + { + if ((aParamArray(j) - aParamArray(aParamLength)) > theMinDist) + { + if (++aParamLength < j) + aParamArray(aParamLength) = aParamArray(j); + } + } + + //perform filtering on series + Standard_Real aLastAdded, aLastCandidate; + Standard_Boolean isCandidateDefined = Standard_False; + aLastAdded = aParamArray(1); + aLastCandidate = aLastAdded; + aResult->Append(aLastAdded); + + for (j = 2; j < aParamLength; j++) + { + Standard_Real aVal = aParamArray(j); + if (aVal - aLastAdded > theFilterDist) + { + //adds the parameter + if (isCandidateDefined) + { + aLastAdded = aLastCandidate; + isCandidateDefined = Standard_False; + j--; + } + else + { + aLastAdded = aVal; + } + aResult->Append(aLastAdded); + continue; + } + + aLastCandidate = aVal; + isCandidateDefined = Standard_True; + } + aResult->Append(aParamArray(aParamLength)); + + return aResult; +} diff --git a/src/BRepMesh/BRepMesh_NURBSRangeSplitter.hxx b/src/BRepMesh/BRepMesh_NURBSRangeSplitter.hxx new file mode 100644 index 0000000000..a74f2d23a2 --- /dev/null +++ b/src/BRepMesh/BRepMesh_NURBSRangeSplitter.hxx @@ -0,0 +1,91 @@ +// Created on: 2016-07-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _BRepMesh_NURBSRangeSplitter_HeaderFile +#define _BRepMesh_NURBSRangeSplitter_HeaderFile + +#include +#include +#include + +//! Auxiliary class extending UV range splitter in order to generate +//! internal nodes for NURBS surface. +class BRepMesh_NURBSRangeSplitter : public BRepMesh_UVParamRangeSplitter +{ +public: + + //! Constructor. + BRepMesh_NURBSRangeSplitter() + { + } + + //! Destructor. + virtual ~BRepMesh_NURBSRangeSplitter() + { + } + + //! Updates discrete range of surface according to its geometric range. + Standard_EXPORT virtual void AdjustRange() Standard_OVERRIDE; + + //! Returns list of nodes generated using surface data and specified parameters. + Standard_EXPORT virtual Handle(IMeshData::ListOfPnt2d) GenerateSurfaceNodes( + const IMeshTools_Parameters& theParameters) const Standard_OVERRIDE; + +protected: + + //! Initializes U and V parameters lists using CN continuity intervals. + Standard_EXPORT virtual Standard_Boolean initParameters() const; + +private: + + //! Computes parameters of filter and applies it to the source parameters. + Handle(IMeshData::SequenceOfReal) computeGrainAndFilterParameters( + const IMeshData::IMapOfReal& theSourceParams, + const Standard_Real theTol2d, + const Standard_Real theRangeDiff, + const Standard_Real theDelta, + const IMeshTools_Parameters& theParameters, + const Handle(NCollection_IncAllocator)& theAllocator) const; + + //! Filters parameters in order to avoid too dence distribution. + Handle(IMeshData::SequenceOfReal) filterParameters( + const IMeshData::IMapOfReal& theParams, + const Standard_Real theMinDist, + const Standard_Real theFilterDist, + const Handle(NCollection_IncAllocator)& theAllocator) const; + + enum EdgeType + { + Edge_Internal, + Edge_Frontier + }; + + enum ParamDimension + { + Param_U = 0x1, + Param_V = 0x2 + }; + + //! Finds edges of discrete face and uses its points + //! as auxiliary control parameters for generation of nodes. + Standard_Boolean grabParamsOfEdges (const EdgeType theEdgeType, + const Standard_Integer theParamDimensionFlag) const; + +private: + + GeomAbs_SurfaceType mySurfaceType; +}; + +#endif diff --git a/src/BRepMesh/BRepMesh_NodeInsertionMeshAlgo.hxx b/src/BRepMesh/BRepMesh_NodeInsertionMeshAlgo.hxx new file mode 100644 index 0000000000..54f80fda62 --- /dev/null +++ b/src/BRepMesh/BRepMesh_NodeInsertionMeshAlgo.hxx @@ -0,0 +1,237 @@ +// Created on: 2016-07-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _BRepMesh_NodeInsertionMeshAlgo_HeaderFile +#define _BRepMesh_NodeInsertionMeshAlgo_HeaderFile + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//! Extends base meshing algo in order to enable possibility +//! of addition of free vertices into the mesh. +template +class BRepMesh_NodeInsertionMeshAlgo : public BaseAlgo +{ +public: + + //! Constructor. + BRepMesh_NodeInsertionMeshAlgo() + { + } + + //! Destructor. + virtual ~BRepMesh_NodeInsertionMeshAlgo() + { + } + + //! Performs processing of the given face. + virtual void Perform( + const IMeshData::IFaceHandle& theDFace, + const IMeshTools_Parameters& theParameters) Standard_OVERRIDE + { + myRangeSplitter.Reset(theDFace, theParameters); + myClassifier = new BRepMesh_Classifier; + BaseAlgo::Perform(theDFace, theParameters); + myClassifier.Nullify(); + } + +protected: + + typedef NCollection_Shared > SequenceOfPnt2d; + + //! Performs initialization of data structure using existing model data. + virtual Standard_Boolean initDataStructure() Standard_OVERRIDE + { + Handle(NCollection_IncAllocator) aTmpAlloc = new NCollection_IncAllocator; + + const IMeshData::IFaceHandle& aDFace = this->getDFace(); + NCollection_Array1 aWires(0, aDFace->WiresNb() - 1); + for (Standard_Integer aWireIt = 0; aWireIt < aDFace->WiresNb(); ++aWireIt) + { + const IMeshData::IWireHandle& aDWire = aDFace->GetWire(aWireIt); + if (aDWire->IsSet(IMeshData_SelfIntersectingWire) || + (aDWire->IsSet(IMeshData_OpenWire) && aWireIt != 0)) + { + continue; + } + + aWires(aWireIt) = collectWirePoints(aDWire, aTmpAlloc); + } + + myRangeSplitter.AdjustRange(); + if (!myRangeSplitter.IsValid()) + { + aDFace->SetStatus(IMeshData_Failure); + return Standard_False; + } + + const std::pair& aDelta = myRangeSplitter.GetDelta(); + const std::pair& aTolUV = myRangeSplitter.GetToleranceUV(); + const Standard_Real uCellSize = 14.0 * aTolUV.first; + const Standard_Real vCellSize = 14.0 * aTolUV.second; + + this->getStructure()->Data()->SetCellSize (uCellSize / aDelta.first, vCellSize / aDelta.second); + this->getStructure()->Data()->SetTolerance(aTolUV.first / aDelta.first, aTolUV.second / aDelta.second); + + for (Standard_Integer aWireIt = 0; aWireIt < aDFace->WiresNb(); ++aWireIt) + { + const Handle(SequenceOfPnt2d)& aWire = aWires(aWireIt); + if (!aWire.IsNull() && !aWire->IsEmpty()) + { + myClassifier->RegisterWire(*aWire, aTolUV, + myRangeSplitter.GetRangeU(), + myRangeSplitter.GetRangeV()); + } + } + + if (this->getParameters().InternalVerticesMode) + { + insertInternalVertices(); + } + + return BaseAlgo::initDataStructure(); + } + + //! Adds the given 2d point to mesh data structure. + //! Returns index of node in the structure. + virtual Standard_Integer addNodeToStructure( + const gp_Pnt2d& thePoint, + const Standard_Integer theLocation3d, + const BRepMesh_DegreeOfFreedom theMovability, + const Standard_Boolean isForceAdd) Standard_OVERRIDE + { + return BaseAlgo::addNodeToStructure( + myRangeSplitter.Scale(thePoint, Standard_True), + theLocation3d, theMovability, isForceAdd); + } + + //! Returns 2d point associated to the given vertex. + virtual gp_Pnt2d getNodePoint2d( + const BRepMesh_Vertex& theVertex) const Standard_OVERRIDE + { + return myRangeSplitter.Scale(theVertex.Coord(), Standard_False); + } + + //! Returns range splitter. + const RangeSplitter& getRangeSplitter() const + { + return myRangeSplitter; + } + + //! Returns classifier. + const Handle(BRepMesh_Classifier)& getClassifier() const + { + return myClassifier; + } + +private: + + //! Creates collection of points representing discrete wire. + Handle(SequenceOfPnt2d) collectWirePoints( + const IMeshData::IWireHandle& theDWire, + const Handle(NCollection_IncAllocator)& theAllocator) + { + Handle(SequenceOfPnt2d) aWirePoints = new SequenceOfPnt2d(theAllocator); + for (Standard_Integer aEdgeIt = 0; aEdgeIt < theDWire->EdgesNb(); ++aEdgeIt) + { + const IMeshData::IEdgeHandle aDEdge = theDWire->GetEdge(aEdgeIt); + const IMeshData::IPCurveHandle& aPCurve = aDEdge->GetPCurve( + this->getDFace().get(), theDWire->GetEdgeOrientation(aEdgeIt)); + + Standard_Integer aPointIt, aEndIndex, aInc; + if (aPCurve->IsForward()) + { + // For an infinite cylinder (for example) + // aPCurve->ParametersNb() == 0 + + aEndIndex = aPCurve->ParametersNb() - 1; + aPointIt = Min(0, aEndIndex); + aInc = 1; + } + else + { + // For an infinite cylinder (for example) + // aPCurve->ParametersNb() == 0 + + aPointIt = aPCurve->ParametersNb() - 1; + aEndIndex = Min(0, aPointIt); + aInc = -1; + } + + // For an infinite cylinder (for example) + // this cycle will not be executed. + for (; aPointIt != aEndIndex; aPointIt += aInc) + { + const gp_Pnt2d& aPnt2d = aPCurve->GetPoint(aPointIt); + aWirePoints->Append(&aPnt2d); + myRangeSplitter.AddPoint(aPnt2d); + } + } + + return aWirePoints; + } + + //! Iterates over internal vertices of a face and + //! creates corresponding nodes in data structure. + void insertInternalVertices() + { + TopExp_Explorer aExplorer(this->getDFace()->GetFace(), TopAbs_VERTEX, TopAbs_EDGE); + for (; aExplorer.More(); aExplorer.Next()) + { + const TopoDS_Vertex& aVertex = TopoDS::Vertex(aExplorer.Current()); + if (aVertex.Orientation() != TopAbs_INTERNAL) + { + continue; + } + + insertInternalVertex(aVertex); + } + } + + //! Inserts the given vertex into mesh. + void insertInternalVertex(const TopoDS_Vertex& theVertex) + { + try + { + OCC_CATCH_SIGNALS + + gp_Pnt2d aPnt2d = BRep_Tool::Parameters(theVertex, this->getDFace()->GetFace()); + // check UV values for internal vertices + if (myClassifier->Perform(aPnt2d) != TopAbs_IN) + return; + + this->registerNode(BRep_Tool::Pnt(theVertex), aPnt2d, + BRepMesh_Fixed, Standard_False); + } + catch (Standard_Failure const&) + { + } + } + +private: + + RangeSplitter myRangeSplitter; + Handle(BRepMesh_Classifier) myClassifier; +}; + +#endif diff --git a/src/BRepMesh/BRepMesh_OrientedEdge.hxx b/src/BRepMesh/BRepMesh_OrientedEdge.hxx index 6f9f154e0b..976c1ba4a2 100644 --- a/src/BRepMesh/BRepMesh_OrientedEdge.hxx +++ b/src/BRepMesh/BRepMesh_OrientedEdge.hxx @@ -35,8 +35,8 @@ public: //! Constructs a link between two vertices. BRepMesh_OrientedEdge( - const Standard_Integer theFirstNode, - const Standard_Integer theLastNode) + const Standard_Integer theFirstNode, + const Standard_Integer theLastNode) : myFirstNode(theFirstNode), myLastNode(theLastNode) { @@ -54,12 +54,12 @@ public: return myLastNode; } - //! Returns hash code for this edge. - //! @param theUpper upper index in the container. - //! @return hash code. - Standard_Integer HashCode(const Standard_Integer theUpper) const + //! Computes a hash code for this oriented edge, in the range [1, theUpperBound] + //! @param theUpperBound the upper bound of the range a computing hash code must be within + //! @return a computed hash code, in the range [1, theUpperBound] + inline Standard_Integer HashCode (const Standard_Integer theUpperBound) const { - return ::HashCode(myFirstNode + myLastNode, theUpper); + return ::HashCode (myFirstNode + myLastNode, theUpperBound); } //! Checks this and other edge for equality. @@ -71,7 +71,7 @@ public: } //! Alias for IsEqual. - Standard_Boolean operator ==(const BRepMesh_OrientedEdge& Other) const + inline Standard_Boolean operator ==(const BRepMesh_OrientedEdge& Other) const { return IsEqual(Other); } @@ -82,10 +82,13 @@ private: Standard_Integer myLastNode; }; -inline Standard_Integer HashCode(const BRepMesh_OrientedEdge& theEdge, - const Standard_Integer theUpper) +//! Computes a hash code for the given oriented edge, in the range [1, theUpperBound] +//! @param theOrientedEdge the oriented edge which hash code is to be computed +//! @param theUpperBound the upper bound of the range a computing hash code must be within +//! @return a computed hash code, in the range [1, theUpperBound] +inline Standard_Integer HashCode (const BRepMesh_OrientedEdge& theOrientedEdge, const Standard_Integer theUpperBound) { - return theEdge.HashCode(theUpper); + return theOrientedEdge.HashCode (theUpperBound); } #endif diff --git a/src/BRepMesh/BRepMesh_PairOfPolygon.hxx b/src/BRepMesh/BRepMesh_PairOfPolygon.hxx deleted file mode 100644 index e6951793ed..0000000000 --- a/src/BRepMesh/BRepMesh_PairOfPolygon.hxx +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (c) 2013 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 _BRepMesh_PairOfPolygon_HeaderFile -#define _BRepMesh_PairOfPolygon_HeaderFile - -#include -#include -#include - -class Poly_PolygonOnTriangulation; - -class BRepMesh_PairOfPolygon -{ -public: - - DEFINE_STANDARD_ALLOC - - //! Constructor. Creates empty pair with null fileds. - BRepMesh_PairOfPolygon() - { - } - - //! Clears pair handles. - inline void Clear() - { - myFirst.Nullify(); - myLast.Nullify(); - } - - //! Sets the first element of the pair. - //! If last element is empty, also assignes the given polygon to it. - //! @param thePolygon plygon to be set. - inline void Prepend(const Handle(Poly_PolygonOnTriangulation)& thePolygon) - { - myFirst = thePolygon; - - if (myLast.IsNull()) - myLast = thePolygon; - } - - //! Sets the last element of the pair. - //! If first element is empty, also assignes the given polygon to it. - //! @param thePolygon plygon to be set. - inline void Append(const Handle(Poly_PolygonOnTriangulation)& thePolygon) - { - if (myFirst.IsNull()) - myFirst = thePolygon; - - myLast = thePolygon; - } - - //! Returns first polygon on triangulation. - inline const Handle(Poly_PolygonOnTriangulation)& First() const - { - return myFirst; - } - - //! Returns last polygon on triangulation. - inline const Handle(Poly_PolygonOnTriangulation)& Last() const - { - return myLast; - } - -private: - - Handle(Poly_PolygonOnTriangulation) myFirst; - Handle(Poly_PolygonOnTriangulation) myLast; -}; - -#endif diff --git a/src/BRepMesh/BRepMesh_SelectorOfDataStructureOfDelaun.cxx b/src/BRepMesh/BRepMesh_SelectorOfDataStructureOfDelaun.cxx index 03217709ea..dd323f29eb 100644 --- a/src/BRepMesh/BRepMesh_SelectorOfDataStructureOfDelaun.cxx +++ b/src/BRepMesh/BRepMesh_SelectorOfDataStructureOfDelaun.cxx @@ -16,17 +16,13 @@ #include #include +#include //======================================================================= //function : Default constructor //purpose : //======================================================================= BRepMesh_SelectorOfDataStructureOfDelaun::BRepMesh_SelectorOfDataStructureOfDelaun() -: myAllocator(new NCollection_IncAllocator(BRepMesh::MEMORY_BLOCK_SIZE_HUGE)), - myNodes (10, myAllocator), - myLinks (10, myAllocator), - myElements(10, myAllocator), - myFrontier(10, myAllocator) { } @@ -36,12 +32,7 @@ BRepMesh_SelectorOfDataStructureOfDelaun::BRepMesh_SelectorOfDataStructureOfDela //======================================================================= BRepMesh_SelectorOfDataStructureOfDelaun::BRepMesh_SelectorOfDataStructureOfDelaun( const Handle(BRepMesh_DataStructureOfDelaun)& theMesh) -: myAllocator(new NCollection_IncAllocator(BRepMesh::MEMORY_BLOCK_SIZE_HUGE)), - myMesh (theMesh), - myNodes (10, myAllocator), - myLinks (10, myAllocator), - myElements(10, myAllocator), - myFrontier(10, myAllocator) + : myMesh(theMesh) { } @@ -76,7 +67,7 @@ void BRepMesh_SelectorOfDataStructureOfDelaun::NeighboursOf( void BRepMesh_SelectorOfDataStructureOfDelaun::NeighboursOfNode( const Standard_Integer theNodeIndex) { - BRepMesh::ListOfInteger::Iterator aLinkIt( + IMeshData::ListOfInteger::Iterator aLinkIt( myMesh->LinksConnectedTo(theNodeIndex)); for (; aLinkIt.More(); aLinkIt.Next()) @@ -135,10 +126,7 @@ void BRepMesh_SelectorOfDataStructureOfDelaun::NeighboursOfElement( void BRepMesh_SelectorOfDataStructureOfDelaun::NeighboursByEdgeOf( const BRepMesh_Triangle& theElement) { - Standard_Integer e[3]; - Standard_Boolean o[3]; - theElement.Edges(e, o); - + const Standard_Integer(&e)[3] = theElement.myEdges; for (Standard_Integer i = 0; i < 3; ++i) elementsOfLink(e[i]); } diff --git a/src/BRepMesh/BRepMesh_SelectorOfDataStructureOfDelaun.hxx b/src/BRepMesh/BRepMesh_SelectorOfDataStructureOfDelaun.hxx index 65847ad557..2d1cc4684c 100644 --- a/src/BRepMesh/BRepMesh_SelectorOfDataStructureOfDelaun.hxx +++ b/src/BRepMesh/BRepMesh_SelectorOfDataStructureOfDelaun.hxx @@ -14,25 +14,20 @@ #ifndef _BRepMesh_SelectorOfDataStructureOfDelaun_HeaderFile #define _BRepMesh_SelectorOfDataStructureOfDelaun_HeaderFile -#include -#include -#include +#include #include -#include -#include #include +#include class BRepMesh_Vertex; class BRepMesh_Edge; //! Describes a selector and an iterator on a //! selector of components of a mesh. -class BRepMesh_SelectorOfDataStructureOfDelaun +class BRepMesh_SelectorOfDataStructureOfDelaun : public Standard_Transient { public: - DEFINE_STANDARD_ALLOC - //! Default constructor. Standard_EXPORT BRepMesh_SelectorOfDataStructureOfDelaun(); @@ -75,41 +70,42 @@ public: } //! Returns selected nodes. - inline const BRepMesh::MapOfInteger& Nodes() const + inline const IMeshData::MapOfInteger& Nodes() const { return myNodes; } //! Returns selected links. - inline const BRepMesh::MapOfInteger& Links() const + inline const IMeshData::MapOfInteger& Links() const { return myLinks; } //! Returns selected elements. - inline const BRepMesh::MapOfInteger& Elements() const + inline const IMeshData::MapOfInteger& Elements() const { return myElements; } //! Gives the list of incices of frontier links. - inline const BRepMesh::MapOfInteger& FrontierLinks() const + inline const IMeshData::MapOfInteger& FrontierLinks() const { return myFrontier; } + DEFINE_STANDARD_RTTI_INLINE(BRepMesh_SelectorOfDataStructureOfDelaun, Standard_Transient) + private: //! Collects elements connected to link with the given index. void elementsOfLink(const Standard_Integer theIndex); private: - Handle(NCollection_IncAllocator) myAllocator; Handle(BRepMesh_DataStructureOfDelaun) myMesh; - BRepMesh::MapOfInteger myNodes; - BRepMesh::MapOfInteger myLinks; - BRepMesh::MapOfInteger myElements; - BRepMesh::MapOfInteger myFrontier; + IMeshData::MapOfInteger myNodes; + IMeshData::MapOfInteger myLinks; + IMeshData::MapOfInteger myElements; + IMeshData::MapOfInteger myFrontier; }; #endif diff --git a/src/BRepMesh/BRepMesh_ShapeTool.cxx b/src/BRepMesh/BRepMesh_ShapeTool.cxx index ebd837bd7a..83af4d6015 100644 --- a/src/BRepMesh/BRepMesh_ShapeTool.cxx +++ b/src/BRepMesh/BRepMesh_ShapeTool.cxx @@ -1,5 +1,6 @@ -// Copyright (c) 1995-1999 Matra Datavision -// Copyright (c) 1999-2014 OPEN CASCADE SAS +// Created on: 2016-04-19 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN // // This file is part of Open CASCADE Technology software library. // @@ -13,21 +14,20 @@ // commercial license or contractual agreement. #include - -#include -#include -#include -#include -#include +#include +#include +#include +#include #include -#include -#include -#include +#include #include -#include +#include #include +#include +#include -namespace { +namespace +{ //! Auxilary struct to take a tolerance of edge. struct EdgeTolerance { @@ -64,7 +64,7 @@ namespace { } //======================================================================= -//function : BoxMaxDimension +//function : MaxFaceTolerance //purpose : //======================================================================= Standard_Real BRepMesh_ShapeTool::MaxFaceTolerance(const TopoDS_Face& theFace) @@ -72,7 +72,7 @@ Standard_Real BRepMesh_ShapeTool::MaxFaceTolerance(const TopoDS_Face& theFace) Standard_Real aMaxTolerance = BRep_Tool::Tolerance(theFace); Standard_Real aTolerance = Max( - MaxTolerance(theFace), + MaxTolerance(theFace), MaxTolerance(theFace)); return Max(aMaxTolerance, aTolerance); @@ -85,7 +85,7 @@ Standard_Real BRepMesh_ShapeTool::MaxFaceTolerance(const TopoDS_Face& theFace) void BRepMesh_ShapeTool::BoxMaxDimension(const Bnd_Box& theBox, Standard_Real& theMaxDimension) { - if(theBox.IsVoid()) + if (theBox.IsVoid()) return; Standard_Real aMinX, aMinY, aMinZ, aMaxX, aMaxY, aMaxZ; @@ -95,98 +95,102 @@ void BRepMesh_ShapeTool::BoxMaxDimension(const Bnd_Box& theBox, } //======================================================================= -//function : RelativeEdgeDeflection +//function : CheckAndUpdateFlags //purpose : //======================================================================= -Standard_Real BRepMesh_ShapeTool::RelativeEdgeDeflection( - const TopoDS_Edge& theEdge, - const Standard_Real theDeflection, - const Standard_Real theMaxShapeSize, - Standard_Real& theAdjustmentCoefficient) +void BRepMesh_ShapeTool::CheckAndUpdateFlags ( + const IMeshData::IEdgeHandle& theEdge, + const IMeshData::IPCurveHandle& thePCurve) { - theAdjustmentCoefficient = 1.; - Standard_Real aDefEdge = theDeflection; - if(theEdge.IsNull()) - return aDefEdge; - - Bnd_Box aBox; - BRepBndLib::Add(theEdge, aBox, Standard_False); - BoxMaxDimension(aBox, aDefEdge); - - // Adjust resulting value in relation to the total size - theAdjustmentCoefficient = theMaxShapeSize / (2 * aDefEdge); - if (theAdjustmentCoefficient < 0.5) - theAdjustmentCoefficient = 0.5; - else if (theAdjustmentCoefficient > 2.) - theAdjustmentCoefficient = 2.; - - return (theAdjustmentCoefficient * aDefEdge * theDeflection); -} - -//======================================================================= -//function : FindUV -//purpose : -//======================================================================= -gp_XY BRepMesh_ShapeTool::FindUV( - const Standard_Integer theIndexOfPnt3d, - const gp_Pnt2d& thePnt2d, - const Standard_Real theMinDistance, - const Handle(BRepMesh_FaceAttribute)& theFaceAttribute) -{ - const gp_XY& aPnt2d = thePnt2d.Coord(); - BRepMesh::HDMapOfIntegerListOfXY& aLocation2D = - theFaceAttribute->ChangeLocation2D(); - - if (!aLocation2D->IsBound(theIndexOfPnt3d)) + if (!theEdge->GetSameParam () && + !theEdge->GetSameRange () && + theEdge->GetDegenerated ()) { - BRepMesh::ListOfXY aPoints2d; - aPoints2d.Append(aPnt2d); - aLocation2D->Bind(theIndexOfPnt3d, aPoints2d); - return aPnt2d; + // Nothing to do worse. + return; } - BRepMesh::ListOfXY& aPoints2d = aLocation2D->ChangeFind(theIndexOfPnt3d); + const TopoDS_Edge& aEdge = theEdge->GetEdge (); + const TopoDS_Face& aFace = thePCurve->GetFace ()->GetFace (); - // Find the most closest 2d point to the given one. - gp_XY aUV; - Standard_Real aMinDist = RealLast(); - BRepMesh::ListOfXY::Iterator aPoint2dIt(aPoints2d); - for (; aPoint2dIt.More(); aPoint2dIt.Next()) + Handle (Geom_Curve) aCurve; + Standard_Real aFirstParam, aLastParam; + Range (aEdge, aCurve, aFirstParam, aLastParam); + if (aCurve.IsNull()) { - const gp_XY& aCurPnt2d = aPoint2dIt.Value(); + theEdge->SetDegenerated(Standard_True); + return; + } - Standard_Real aDist = (aPnt2d - aCurPnt2d).Modulus(); - if (aDist < aMinDist) + BRepAdaptor_Curve aCurveOnSurf(aEdge, aFace); + if (theEdge->GetSameParam () || theEdge->GetSameRange ()) + { + if (theEdge->GetSameRange ()) { - aUV = aCurPnt2d; - aMinDist = aDist; + const Standard_Real aDiffFirst = aCurveOnSurf.FirstParameter () - aFirstParam; + const Standard_Real aDiffLast = aCurveOnSurf.LastParameter () - aLastParam; + theEdge->SetSameRange ( + Abs (aDiffFirst) < Precision::PConfusion () && + Abs (aDiffLast ) < Precision::PConfusion ()); + + if (!theEdge->GetSameRange()) + { + theEdge->SetSameParam(Standard_False); + } } } - const Standard_Real aTolerance = theMinDistance; - - // Get face limits - Standard_Real aDiffU = theFaceAttribute->GetUMax() - theFaceAttribute->GetUMin(); - Standard_Real aDiffV = theFaceAttribute->GetVMax() - theFaceAttribute->GetVMin(); - - const Standard_Real Utol2d = .5 * aDiffU; - const Standard_Real Vtol2d = .5 * aDiffV; - - const Handle(BRepAdaptor_HSurface)& aSurface = theFaceAttribute->Surface(); - const gp_Pnt aPnt1 = aSurface->Value(aUV.X(), aUV.Y()); - const gp_Pnt aPnt2 = aSurface->Value(aPnt2d.X(), aPnt2d.Y()); - - //! If selected point is too far from the given one in parametric space - //! or their positions in 3d are different, add the given point as unique. - if (Abs(aUV.X() - aPnt2d.X()) > Utol2d || - Abs(aUV.Y() - aPnt2d.Y()) > Vtol2d || - !aPnt1.IsEqual(aPnt2, aTolerance)) + if (!theEdge->GetDegenerated ()/* || theEdge->GetSameParam ()*/) { - aUV = aPnt2d; - aPoints2d.Append(aUV); - } + TopoDS_Vertex aStartVertex, aEndVertex; + TopExp::Vertices (aEdge, aStartVertex, aEndVertex); + if (aStartVertex.IsNull() || aEndVertex.IsNull()) + { + theEdge->SetDegenerated(Standard_True); + return; + } - return aUV; + if (aStartVertex.IsSame(aEndVertex)) + { + const Standard_Integer aPointsNb = 20; + const Standard_Real aVertexTolerance = BRep_Tool::Tolerance (aStartVertex); + const Standard_Real aDu = (aLastParam - aFirstParam) / aPointsNb; + //const Standard_Real aEdgeTolerance = BRep_Tool::Tolerance (aEdge); + //const Standard_Real aSqEdgeTolerance = aEdgeTolerance * aEdgeTolerance; + + gp_Pnt aPrevPnt; + aCurve->D0 (aFirstParam, aPrevPnt); + + Standard_Real aLength = 0.0; + for (Standard_Integer i = 1; i <= aPointsNb; ++i) + { + const Standard_Real aParameter = aFirstParam + i * aDu; + // Calculation of the length of the edge in 3D + // in order to check degenerativity + gp_Pnt aPnt; + aCurve->D0 (aParameter, aPnt); + aLength += aPrevPnt.Distance (aPnt); + + //if (theEdge->GetSameParam ()) + //{ + // // Check that points taken at the 3d and pcurve using + // // same parameter are within tolerance of an edge. + // gp_Pnt aPntOnSurf; + // aCurveOnSurf.D0 (aParameter, aPntOnSurf); + // theEdge->SetSameParam (aPnt.SquareDistance (aPntOnSurf) < aSqEdgeTolerance); + //} + + if (aLength > aVertexTolerance /*&& !theEdge->GetSameParam()*/) + { + break; + } + + aPrevPnt = aPnt; + } + + theEdge->SetDegenerated (aLength < aVertexTolerance); + } + } } //======================================================================= @@ -204,7 +208,7 @@ void BRepMesh_ShapeTool::AddInFace( aTrsf.Invert(); TColgp_Array1OfPnt& aNodes = theTriangulation->ChangeNodes(); - for (Standard_Integer i = aNodes.Lower(); i <= aNodes.Upper(); ++i) + for (Standard_Integer i = aNodes.Lower(); i <= aNodes.Upper(); ++i) aNodes(i).Transform(aTrsf); } @@ -212,117 +216,157 @@ void BRepMesh_ShapeTool::AddInFace( aBuilder.UpdateFace(theFace, theTriangulation); } + //======================================================================= //function : NullifyFace //purpose : //======================================================================= -void BRepMesh_ShapeTool::NullifyFace(const TopoDS_Face& theFace) +void BRepMesh_ShapeTool::NullifyFace (const TopoDS_Face& theFace) { BRep_Builder aBuilder; - aBuilder.UpdateFace(theFace, Handle(Poly_Triangulation)()); + aBuilder.UpdateFace (theFace, Handle (Poly_Triangulation)()); } //======================================================================= //function : NullifyEdge //purpose : //======================================================================= -void BRepMesh_ShapeTool::NullifyEdge( - const TopoDS_Edge& theEdge, - const Handle(Poly_Triangulation)& theTriangulation, - const TopLoc_Location& theLocation) +void BRepMesh_ShapeTool::NullifyEdge ( + const TopoDS_Edge& theEdge, + const Handle (Poly_Triangulation)& theTriangulation, + const TopLoc_Location& theLocation) { - UpdateEdge(theEdge, Handle(Poly_PolygonOnTriangulation)(), + UpdateEdge (theEdge, Handle (Poly_PolygonOnTriangulation)(), theTriangulation, theLocation); } +//======================================================================= +//function : NullifyEdge +//purpose : +//======================================================================= +void BRepMesh_ShapeTool::NullifyEdge ( + const TopoDS_Edge& theEdge, + const TopLoc_Location& theLocation) +{ + BRep_Builder aBuilder; + aBuilder.UpdateEdge (theEdge, Handle (Poly_Polygon3D)(), theLocation); +} + //======================================================================= //function : UpdateEdge //purpose : //======================================================================= -void BRepMesh_ShapeTool::UpdateEdge( - const TopoDS_Edge& theEdge, - const Handle(Poly_PolygonOnTriangulation)& thePolygon, - const Handle(Poly_Triangulation)& theTriangulation, - const TopLoc_Location& theLocation) +void BRepMesh_ShapeTool::UpdateEdge ( + const TopoDS_Edge& theEdge, + const Handle (Poly_PolygonOnTriangulation)& thePolygon, + const Handle (Poly_Triangulation)& theTriangulation, + const TopLoc_Location& theLocation) { BRep_Builder aBuilder; - aBuilder.UpdateEdge(theEdge, thePolygon, theTriangulation, theLocation); + aBuilder.UpdateEdge (theEdge, thePolygon, theTriangulation, theLocation); } //======================================================================= //function : UpdateEdge //purpose : //======================================================================= -void BRepMesh_ShapeTool::UpdateEdge( - const TopoDS_Edge& theEdge, - const Handle(Poly_PolygonOnTriangulation)& thePolygon1, - const Handle(Poly_PolygonOnTriangulation)& thePolygon2, - const Handle(Poly_Triangulation)& theTriangulation, - const TopLoc_Location& theLocation) +void BRepMesh_ShapeTool::UpdateEdge ( + const TopoDS_Edge& theEdge, + const Handle (Poly_PolygonOnTriangulation)& thePolygon1, + const Handle (Poly_PolygonOnTriangulation)& thePolygon2, + const Handle (Poly_Triangulation)& theTriangulation, + const TopLoc_Location& theLocation) { BRep_Builder aBuilder; - aBuilder.UpdateEdge(theEdge, thePolygon1, thePolygon2, + aBuilder.UpdateEdge (theEdge, thePolygon1, thePolygon2, theTriangulation, theLocation); } +//======================================================================= +//function : UpdateEdge +//purpose : +//======================================================================= +void BRepMesh_ShapeTool::UpdateEdge( + const TopoDS_Edge& theEdge, + const Handle(Poly_Polygon3D)& thePolygon) +{ + BRep_Builder aBuilder; + aBuilder.UpdateEdge(theEdge, thePolygon); +} + //======================================================================= //function : UseLocation //purpose : //======================================================================= -gp_Pnt BRepMesh_ShapeTool::UseLocation(const gp_Pnt& thePnt, - const TopLoc_Location& theLoc) +gp_Pnt BRepMesh_ShapeTool::UseLocation ( + const gp_Pnt& thePnt, + const TopLoc_Location& theLoc) { if (theLoc.IsIdentity()) + { return thePnt; + } - return thePnt.Transformed(theLoc.Transformation()); + return thePnt.Transformed (theLoc.Transformation ()); } //======================================================================= -//function : IsDegenerated +//function : UVPoints //purpose : //======================================================================= -Standard_Boolean BRepMesh_ShapeTool::IsDegenerated( - const TopoDS_Edge& theEdge, - const TopoDS_Face& theFace) +Standard_Boolean BRepMesh_ShapeTool::UVPoints ( + const TopoDS_Edge& theEdge, + const TopoDS_Face& theFace, + gp_Pnt2d& theFirstPoint2d, + gp_Pnt2d& theLastPoint2d, + const Standard_Boolean isConsiderOrientation) { - // Get vertices - TopoDS_Vertex pBegin, pEnd; - TopExp::Vertices(theEdge, pBegin, pEnd); - if (pBegin.IsNull() || pEnd.IsNull()) - return Standard_True; - - if (BRep_Tool::Degenerated(theEdge)) - return Standard_True; - if (!pBegin.IsSame(pEnd)) + Handle (Geom2d_Curve) aCurve2d; + Standard_Real aFirstParam, aLastParam; + if (!Range(theEdge, theFace, aCurve2d, aFirstParam, aLastParam, isConsiderOrientation)) + { return Standard_False; + } - Standard_Real wFirst, wLast; - BRep_Tool::Range(theEdge, theFace, wFirst, wLast); - - // calculation of the length of the edge in 3D - Standard_Real longueur = 0.0; - Standard_Real du = (wLast - wFirst) * 0.05; - gp_Pnt P1, P2; - BRepAdaptor_Curve BC(theEdge); - BC.D0(wFirst, P1); - Standard_Real tolV = BRep_Tool::Tolerance(pBegin); - Standard_Real tolV2 = 1.2 * tolV; - - for (Standard_Integer l = 1; l <= 20; ++l) - { - BC.D0(wFirst + l * du, P2); - longueur += P1.Distance(P2); + aCurve2d->D0 (aFirstParam, theFirstPoint2d); + aCurve2d->D0 (aLastParam, theLastPoint2d); + return Standard_True; +} - if (longueur > tolV2) - break; +//======================================================================= +//function : Range +//purpose : +//======================================================================= +Standard_Boolean BRepMesh_ShapeTool::Range ( + const TopoDS_Edge& theEdge, + const TopoDS_Face& theFace, + Handle (Geom2d_Curve)& thePCurve, + Standard_Real& theFirstParam, + Standard_Real& theLastParam, + const Standard_Boolean isConsiderOrientation) +{ - P1 = P2; - } + ShapeAnalysis_Edge aEdge; + return aEdge.PCurve (theEdge, theFace, thePCurve, + theFirstParam, theLastParam, + isConsiderOrientation); +} - if (longueur < tolV2) - return Standard_True; +//======================================================================= +//function : Range +//purpose : +//======================================================================= +Standard_Boolean BRepMesh_ShapeTool::Range ( + const TopoDS_Edge& theEdge, + Handle (Geom_Curve)& theCurve, + Standard_Real& theFirstParam, + Standard_Real& theLastParam, + const Standard_Boolean isConsiderOrientation) +{ - return Standard_False; + ShapeAnalysis_Edge aEdge; + return aEdge.Curve3d (theEdge, theCurve, + theFirstParam, theLastParam, + isConsiderOrientation); } diff --git a/src/BRepMesh/BRepMesh_ShapeTool.hxx b/src/BRepMesh/BRepMesh_ShapeTool.hxx index e1883d7746..d257d612d0 100644 --- a/src/BRepMesh/BRepMesh_ShapeTool.hxx +++ b/src/BRepMesh/BRepMesh_ShapeTool.hxx @@ -1,4 +1,6 @@ -// Copyright (c) 2013 OPEN CASCADE SAS +// Created on: 2016-04-19 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN // // This file is part of Open CASCADE Technology software library. // @@ -11,31 +13,29 @@ // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. - #ifndef _BRepMesh_ShapeTool_HeaderFile #define _BRepMesh_ShapeTool_HeaderFile -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include -class Poly_Triangulation; +class Geom_Curve; +class Geom2d_Curve; +class Poly_Polygon3D; class TopoDS_Face; class TopoDS_Edge; class Bnd_Box; -class TopoDS_Vertex; -class gp_XY; -class gp_Pnt2d; -class BRepMesh_ShapeTool +//! Auxiliary class providing functionality to compute, +//! retrieve and store data to TopoDS and model shape. +class BRepMesh_ShapeTool : public Standard_Transient { public: - DEFINE_STANDARD_ALLOC - //! Returns maximum tolerance of the given face. //! Considers tolerances of edges and vertices contained in the given face. Standard_EXPORT static Standard_Real MaxFaceTolerance( @@ -48,39 +48,15 @@ public: Standard_EXPORT static void BoxMaxDimension(const Bnd_Box& theBox, Standard_Real& theMaxDimension); - //! Returns relative deflection for edge with respect to shape size. - //! @param theEdge edge for which relative deflection should be computed. - //! @param theDeflection absolute deflection. - //! @param theMaxShapeSize maximum size of a shape. - //! @param theAdjustmentCoefficient coefficient of adjustment between maximum - //! size of shape and calculated relative deflection. - //! @return relative deflection for the edge. - Standard_EXPORT static Standard_Real RelativeEdgeDeflection( - const TopoDS_Edge& theEdge, - const Standard_Real theDeflection, - const Standard_Real theMaxShapeSize, - Standard_Real& theAdjustmentCoefficient); - - //! Checks 2d representations of 3d point with the - //! given index for equality to avoid duplications. - //! @param theIndexOfPnt3d index of 3d point with which 2d - //! representation should be associated. - //! @param thePnt2d 2d representation of the point with the - //! given index. - //! @param theMinDistance minimum distance between vertices - //! regarding which they could be treated as distinct ones. - //! @param theFaceAttribute attributes contining data calculated - //! according to face geomtry and define limits of face in parametric - //! space. If defined, will be used instead of surface parameter. - //! @param theLocation2dMap map of 2d representations of 3d points. - //! @return given 2d point in case if 3d poind does not alredy have - //! the similar representation, otherwice 2d point corresponding to - //! existing representation will be returned. - Standard_EXPORT static gp_XY FindUV( - const Standard_Integer theIndexOfPnt3d, - const gp_Pnt2d& thePnt2d, - const Standard_Real theMinDistance, - const Handle(BRepMesh_FaceAttribute)& theFaceAttribute); + //! Checks same parameter, same range and degenerativity attributes + //! using geometrical data of the given edge and updates edge model + //! by computed parameters in case of worst case - it can drop flags + //! same parameter and same range to False but never to True if it is + //! already set to False. In contrary, it can also drop degenerated + //! flag to True, but never to False if it is already set to True. + Standard_EXPORT static void CheckAndUpdateFlags ( + const IMeshData::IEdgeHandle& theEdge, + const IMeshData::IPCurveHandle& thePCurve); //! Stores the given triangulation into the given face. //! @param theFace face to be updated by triangulation. @@ -91,27 +67,41 @@ public: //! Nullifies triangulation stored in the face. //! @param theFace face to be updated by null triangulation. - Standard_EXPORT static void NullifyFace(const TopoDS_Face& theFace); + Standard_EXPORT static void NullifyFace (const TopoDS_Face& theFace); //! Nullifies polygon on triangulation stored in the edge. //! @param theEdge edge to be updated by null polygon. //! @param theTriangulation triangulation the given edge is associated to. //! @param theLocation face location. - Standard_EXPORT static void NullifyEdge( - const TopoDS_Edge& theEdge, - const Handle(Poly_Triangulation)& theTriangulation, - const TopLoc_Location& theLocation); + Standard_EXPORT static void NullifyEdge ( + const TopoDS_Edge& theEdge, + const Handle (Poly_Triangulation)& theTriangulation, + const TopLoc_Location& theLocation); + + //! Nullifies 3d polygon stored in the edge. + //! @param theEdge edge to be updated by null polygon. + //! @param theLocation face location. + Standard_EXPORT static void NullifyEdge ( + const TopoDS_Edge& theEdge, + const TopLoc_Location& theLocation); //! Updates the given edge by the given tessellated representation. //! @param theEdge edge to be updated. //! @param thePolygon tessellated representation of the edge to be stored. //! @param theTriangulation triangulation the given edge is associated to. //! @param theLocation face location. + Standard_EXPORT static void UpdateEdge ( + const TopoDS_Edge& theEdge, + const Handle (Poly_PolygonOnTriangulation)& thePolygon, + const Handle (Poly_Triangulation)& theTriangulation, + const TopLoc_Location& theLocation); + + //! Updates the given edge by the given tessellated representation. + //! @param theEdge edge to be updated. + //! @param thePolygon tessellated representation of the edge to be stored. Standard_EXPORT static void UpdateEdge( - const TopoDS_Edge& theEdge, - const Handle(Poly_PolygonOnTriangulation)& thePolygon, - const Handle(Poly_Triangulation)& theTriangulation, - const TopLoc_Location& theLocation); + const TopoDS_Edge& theEdge, + const Handle(Poly_Polygon3D)& thePolygon); //! Updates the given seam edge by the given tessellated representations. //! @param theEdge edge to be updated. @@ -121,27 +111,46 @@ public: //! reversed direction of the seam edge. //! @param theTriangulation triangulation the given edge is associated to. //! @param theLocation face location. - Standard_EXPORT static void UpdateEdge( - const TopoDS_Edge& theEdge, - const Handle(Poly_PolygonOnTriangulation)& thePolygon1, - const Handle(Poly_PolygonOnTriangulation)& thePolygon2, - const Handle(Poly_Triangulation)& theTriangulation, - const TopLoc_Location& theLocation); + Standard_EXPORT static void UpdateEdge ( + const TopoDS_Edge& theEdge, + const Handle (Poly_PolygonOnTriangulation)& thePolygon1, + const Handle (Poly_PolygonOnTriangulation)& thePolygon2, + const Handle (Poly_Triangulation)& theTriangulation, + const TopLoc_Location& theLocation); //! Applies location to the given point and return result. //! @param thePnt point to be transformed. //! @param theLoc location to be applied. - Standard_EXPORT static gp_Pnt UseLocation(const gp_Pnt& thePnt, - const TopLoc_Location& theLoc); - - //! Checks is the given edge degenerated. - //! Checks geometrical parameters in case if IsDegenerated flag is not set. - //! @param theEdge edge to be checked. - //! @param theFace face within which parametric space edge will be checked - //! for geometrical degenerativity. - Standard_EXPORT static Standard_Boolean IsDegenerated( - const TopoDS_Edge& theEdge, - const TopoDS_Face& theFace); + Standard_EXPORT static gp_Pnt UseLocation ( + const gp_Pnt& thePnt, + const TopLoc_Location& theLoc); + + //! Gets the strict UV locations of the extremities of the edge using pcurve. + Standard_EXPORT static Standard_Boolean UVPoints ( + const TopoDS_Edge& theEdge, + const TopoDS_Face& theFace, + gp_Pnt2d& theFirstPoint2d, + gp_Pnt2d& theLastPoint2d, + const Standard_Boolean isConsiderOrientation = Standard_False); + + //! Gets the parametric range of the given edge on the given face. + Standard_EXPORT static Standard_Boolean Range ( + const TopoDS_Edge& theEdge, + const TopoDS_Face& theFace, + Handle (Geom2d_Curve)& thePCurve, + Standard_Real& theFirstParam, + Standard_Real& theLastParam, + const Standard_Boolean isConsiderOrientation = Standard_False); + + //! Gets the 3d range of the given edge. + Standard_EXPORT static Standard_Boolean Range ( + const TopoDS_Edge& theEdge, + Handle (Geom_Curve)& theCurve, + Standard_Real& theFirstParam, + Standard_Real& theLastParam, + const Standard_Boolean isConsiderOrientation = Standard_False); + + DEFINE_STANDARD_RTTI_INLINE(BRepMesh_ShapeTool, Standard_Transient) }; -#endif +#endif \ No newline at end of file diff --git a/src/BRepMesh/BRepMesh_ShapeVisitor.cxx b/src/BRepMesh/BRepMesh_ShapeVisitor.cxx new file mode 100644 index 0000000000..0705c13cf0 --- /dev/null +++ b/src/BRepMesh/BRepMesh_ShapeVisitor.cxx @@ -0,0 +1,151 @@ +// Created on: 2016-04-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +//======================================================================= +// Function: Constructor +// Purpose : +//======================================================================= +BRepMesh_ShapeVisitor::BRepMesh_ShapeVisitor (const Handle (IMeshData_Model)& theModel) +: myModel (theModel), + myDEdgeMap(1, new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE)) +{ +} + +//======================================================================= +// Function: Destructor +// Purpose : +//======================================================================= +BRepMesh_ShapeVisitor::~BRepMesh_ShapeVisitor () +{ +} + +//======================================================================= +// Function: Visit (edge) +// Purpose : +//======================================================================= +void BRepMesh_ShapeVisitor::Visit(const TopoDS_Edge& theEdge) +{ + if (!myDEdgeMap.IsBound (theEdge)) + { + myModel->AddEdge (theEdge); + myDEdgeMap.Bind (theEdge, myModel->EdgesNb () - 1); + } +} + +//======================================================================= +// Function: Visit (face) +// Purpose : +//======================================================================= +void BRepMesh_ShapeVisitor::Visit (const TopoDS_Face& theFace) +{ + BRepTools::Update(theFace); + const IMeshData::IFaceHandle& aDFace = myModel->AddFace (theFace); + + // Outer wire should always be the first in the model. + TopoDS_Wire aOuterWire = ShapeAnalysis::OuterWire (theFace); + if (!addWire (aOuterWire, aDFace)) + { + aDFace->SetStatus (IMeshData_Failure); + return; + } + + TopExp_Explorer aWireIt (theFace, TopAbs_WIRE); + for (; aWireIt.More (); aWireIt.Next ()) + { + const TopoDS_Wire& aWire = TopoDS::Wire (aWireIt.Current ()); + if (aWire.IsSame(aOuterWire)) + { + continue; + } + + if (!addWire (aWire, aDFace)) + { + // If there is a failure on internal wire, just skip it. + // The most significant is an outer wire. + aDFace->SetStatus (IMeshData_UnorientedWire); + } + } +} + +//======================================================================= +// Function: addWire +// Purpose : +//======================================================================= +Standard_Boolean BRepMesh_ShapeVisitor::addWire ( + const TopoDS_Wire& theWire, + const IMeshData::IFaceHandle& theDFace) +{ + if (theWire.IsNull()) + { + return Standard_False; + } + + Handle(ShapeExtend_WireData) aWireData = new ShapeExtend_WireData(theWire, Standard_True, Standard_False); + ShapeAnalysis_Wire aWireTool (aWireData, theDFace->GetFace (), Precision::Confusion ()); + + ShapeAnalysis_WireOrder aOrderTool; + aWireTool.CheckOrder (aOrderTool, Standard_True, Standard_False); + if (aWireTool.LastCheckStatus(ShapeExtend_FAIL)) + { + return Standard_False; + } + + if (aWireTool.LastCheckStatus(ShapeExtend_DONE3)) + { + theDFace->SetStatus(IMeshData_UnorientedWire); + } + + const Standard_Integer aEdgesNb = aOrderTool.NbEdges (); + if (aEdgesNb != aWireData->NbEdges()) + { + return Standard_False; + } + + const IMeshData::IWireHandle& aDWire = theDFace->AddWire (theWire, aEdgesNb); + for (Standard_Integer i = 1; i <= aEdgesNb; ++i) + { + const Standard_Integer aEdgeIndex = aOrderTool.Ordered (i); + const TopoDS_Edge& aEdge = aWireData->Edge (aEdgeIndex); + if (aEdge.Orientation() != TopAbs_EXTERNAL) + { + const IMeshData::IEdgeHandle& aDEdge = myModel->GetEdge (myDEdgeMap.Find (aEdge)); + + aDEdge->AddPCurve (theDFace.get(), aEdge.Orientation()); + aDWire->AddEdge (aDEdge.get(), aEdge.Orientation()); + } + } + + return Standard_True; +} diff --git a/src/BRepMesh/BRepMesh_ShapeVisitor.hxx b/src/BRepMesh/BRepMesh_ShapeVisitor.hxx new file mode 100644 index 0000000000..171f49c61b --- /dev/null +++ b/src/BRepMesh/BRepMesh_ShapeVisitor.hxx @@ -0,0 +1,67 @@ +// Created on: 2016-04-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _BRepMesh_ShapeVisitor_HeaderFile +#define _BRepMesh_ShapeVisitor_HeaderFile + +#include +#include +#include +#include +#include +#include + +class TopoDS_Face; +class TopoDS_Edge; +class TopoDS_Wire; +class IMeshTools_Context; +class IMeshData_Wire; + +//! Builds discrete model of a shape by adding faces and free edges. +//! Computes deflection for corresponded shape and checks whether it +//! fits existing polygonal representation. If not, cleans shape from +//! outdated info. +class BRepMesh_ShapeVisitor : public IMeshTools_ShapeVisitor +{ +public: + + //! Constructor. + Standard_EXPORT BRepMesh_ShapeVisitor (const Handle (IMeshData_Model)& theModel); + + //! Destructor. + Standard_EXPORT virtual ~BRepMesh_ShapeVisitor (); + + //! Handles TopoDS_Face object. + Standard_EXPORT virtual void Visit (const TopoDS_Face& theFace) Standard_OVERRIDE; + + //! Handles TopoDS_Edge object. + Standard_EXPORT virtual void Visit (const TopoDS_Edge& theEdge) Standard_OVERRIDE; + + DEFINE_STANDARD_RTTI_INLINE(BRepMesh_ShapeVisitor, IMeshTools_ShapeVisitor) + +private: + + //! Adds wire to face discrete model. + Standard_Boolean addWire ( + const TopoDS_Wire& theWire, + const IMeshData::IFaceHandle& theDFace); + +private: + + Handle (IMeshData_Model) myModel; + IMeshData::DMapOfShapeInteger myDEdgeMap; +}; + +#endif \ No newline at end of file diff --git a/src/BRepMesh/BRepMesh_SphereRangeSplitter.cxx b/src/BRepMesh/BRepMesh_SphereRangeSplitter.cxx new file mode 100644 index 0000000000..4a3112ee79 --- /dev/null +++ b/src/BRepMesh/BRepMesh_SphereRangeSplitter.cxx @@ -0,0 +1,59 @@ +// Created on: 2016-07-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 +#include + +//======================================================================= +// Function: GenerateSurfaceNodes +// Purpose : +//======================================================================= +Handle(IMeshData::ListOfPnt2d) BRepMesh_SphereRangeSplitter::GenerateSurfaceNodes( + const IMeshTools_Parameters& theParameters) const +{ + // Calculate parameters for iteration in V direction + Standard_Real aStep = 0.7 * GCPnts_TangentialDeflection::ArcAngularStep( + GetDFace()->GetSurface()->Sphere().Radius(), GetDFace()->GetDeflection(), + theParameters.Angle, theParameters.MinSize); + + const std::pair* aRange[2] = { + &GetRangeV(), + &GetRangeU() + }; + + std::pair aStepAndOffset[2]; + computeStep(*aRange[0], aStep, aStepAndOffset[0]); + computeStep(*aRange[1], aStep, aStepAndOffset[1]); + + const Handle(NCollection_IncAllocator) aTmpAlloc = + new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE); + Handle(IMeshData::ListOfPnt2d) aNodes = new IMeshData::ListOfPnt2d(aTmpAlloc); + + const Standard_Real aHalfDu = aStepAndOffset[1].first * 0.5; + Standard_Boolean Shift = Standard_False; + Standard_Real aPasV = aRange[0]->first + aStepAndOffset[0].first; + for (; aPasV < aStepAndOffset[0].second; aPasV += aStepAndOffset[0].first) + { + Shift = !Shift; + const Standard_Real d = (Shift) ? aHalfDu : 0.; + Standard_Real aPasU = aRange[1]->first + d; + for (; aPasU < aStepAndOffset[1].second; aPasU += aStepAndOffset[1].first) + { + aNodes->Append(gp_Pnt2d(aPasU, aPasV)); + } + } + + return aNodes; +} diff --git a/src/BRepMesh/BRepMesh_SphereRangeSplitter.hxx b/src/BRepMesh/BRepMesh_SphereRangeSplitter.hxx new file mode 100644 index 0000000000..c237df213e --- /dev/null +++ b/src/BRepMesh/BRepMesh_SphereRangeSplitter.hxx @@ -0,0 +1,56 @@ +// Created on: 2016-07-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _BRepMesh_SphereRangeSplitter_HeaderFile +#define _BRepMesh_SphereRangeSplitter_HeaderFile + +#include +#include + +//! Auxiliary class extending default range splitter in +//! order to generate internal nodes for spherical surface. +class BRepMesh_SphereRangeSplitter : public BRepMesh_DefaultRangeSplitter +{ +public: + + //! Constructor. + BRepMesh_SphereRangeSplitter() + { + } + + //! Destructor. + virtual ~BRepMesh_SphereRangeSplitter() + { + } + + //! Returns list of nodes generated using surface data and specified parameters. + Standard_EXPORT virtual Handle(IMeshData::ListOfPnt2d) GenerateSurfaceNodes( + const IMeshTools_Parameters& theParameters) const Standard_OVERRIDE; + +private: + + //! Computes step for the given range. + inline void computeStep( + const std::pair& theRange, + const Standard_Real theDefaultStep, + std::pair& theStepAndOffset) const + { + const Standard_Real aDiff = theRange.second - theRange.first; + theStepAndOffset.first = aDiff / ((Standard_Integer) (aDiff / theDefaultStep) + 1); + theStepAndOffset.second = theRange.second - Precision::PConfusion(); + } +}; + +#endif diff --git a/src/BRepMesh/BRepMesh_TorusRangeSplitter.cxx b/src/BRepMesh/BRepMesh_TorusRangeSplitter.cxx new file mode 100644 index 0000000000..455a473aba --- /dev/null +++ b/src/BRepMesh/BRepMesh_TorusRangeSplitter.cxx @@ -0,0 +1,218 @@ +// Created on: 2016-07-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 +#include + +//======================================================================= +// Function: GenerateSurfaceNodes +// Purpose : +//======================================================================= +Handle(IMeshData::ListOfPnt2d) BRepMesh_TorusRangeSplitter::GenerateSurfaceNodes( + const IMeshTools_Parameters& theParameters) const +{ + const std::pair& aRangeU = GetRangeU(); + const std::pair& aRangeV = GetRangeV(); + + const Standard_Real aDiffU = aRangeU.second - aRangeU.first; + const Standard_Real aDiffV = aRangeV.second - aRangeV.first; + + const gp_Torus aTorus = GetDFace()->GetSurface()->Torus(); + const Standard_Real r = aTorus.MinorRadius(); + const Standard_Real R = aTorus.MajorRadius(); + + const Standard_Real oldDv = GCPnts_TangentialDeflection::ArcAngularStep( + r, GetDFace()->GetDeflection(), theParameters.Angle, theParameters.MinSize); + + Standard_Real Dv = 0.9*oldDv; //TWOTHIRD * oldDv; + Dv = oldDv; + + const Standard_Integer nbV = Max((Standard_Integer) (aDiffV / Dv), 2); + Dv = aDiffV / (nbV + 1); + + Standard_Real Du; + const Standard_Real ru = R + r; + if (ru > 1.e-16) + { + Du = GCPnts_TangentialDeflection::ArcAngularStep(ru, + GetDFace()->GetDeflection(), theParameters.Angle, theParameters.MinSize); + + const Standard_Real aa = sqrt(Du*Du + oldDv*oldDv); + if (aa < gp::Resolution()) + { + return Handle(IMeshData::ListOfPnt2d)(); + } + + Du *= Min(oldDv, Du) / aa; + } + else + { + Du = Dv; + } + + Standard_Integer nbU = Max((Standard_Integer) (aDiffU / Du), 2); + nbU = Max(nbU, (Standard_Integer) (nbV * aDiffU * R / (aDiffV * r) / 5.)); + Du = aDiffU / (nbU + 1); + + const Handle(NCollection_IncAllocator) aTmpAlloc = + new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE); + + Handle(IMeshData::SequenceOfReal) aParamU, aParamV; + if (R < r) + { + // As the points of edges are returned. + // in this case, the points are not representative. + + //-- Choose DeltaX and DeltaY so that to avoid skipping points on the grid + aParamU = new IMeshData::SequenceOfReal(aTmpAlloc); + for (Standard_Integer i = 0; i <= nbU; i++) + { + aParamU->Append(aRangeU.first + i * Du); + } + }//R r + { + aParamU = fillParams(GetParametersU(), GetRangeU(), nbU, 0.5, aTmpAlloc); + } + + aParamV = fillParams(GetParametersV(), GetRangeV(), nbV, 2. / 3., aTmpAlloc); + + const std::pair aNewRangeU(aRangeU.first + Du * 0.1, + aRangeU.second - Du * 0.1); + + const std::pair aNewRangeV(aRangeV.first + Dv * 0.1, + aRangeV.second - Dv * 0.1); + + Handle(IMeshData::ListOfPnt2d) aNodes = new IMeshData::ListOfPnt2d(aTmpAlloc); + for (Standard_Integer i = 1; i <= aParamU->Length(); ++i) + { + const Standard_Real aPasU = aParamU->Value(i); + if (aPasU >= aNewRangeU.first && aPasU < aNewRangeU.second) + { + for (Standard_Integer j = 1; j <= aParamV->Length(); ++j) + { + const Standard_Real aPasV = aParamV->Value(j); + if (aPasV >= aNewRangeV.first && aPasV < aNewRangeV.second) + { + aNodes->Append(gp_Pnt2d(aPasU, aPasV)); + } + } + } + } + + return aNodes; +} + +//======================================================================= +// Function: AddPoint +// Purpose : +//======================================================================= +void BRepMesh_TorusRangeSplitter::AddPoint(const gp_Pnt2d& thePoint) +{ + BRepMesh_DefaultRangeSplitter::AddPoint(thePoint); + GetParametersU().Add(thePoint.X()); + GetParametersV().Add(thePoint.Y()); +} + +//======================================================================= +// Function: fillParams +// Purpose : +//======================================================================= +Handle(IMeshData::SequenceOfReal) BRepMesh_TorusRangeSplitter::fillParams( + const IMeshData::IMapOfReal& theParams, + const std::pair& theRange, + const Standard_Integer theStepsNb, + const Standard_Real theScale, + const Handle(NCollection_IncAllocator)& theAllocator) const +{ + Handle(IMeshData::SequenceOfReal) aParams = + new IMeshData::SequenceOfReal(theAllocator); + + const Standard_Integer aLength = theParams.Size(); + TColStd_Array1OfReal aParamArray(1, aLength); + + for (Standard_Integer j = 1; j <= aLength; ++j) + { + aParamArray(j) = theParams(j); + } + + // Calculate DU, leave array of parameters + const Standard_Real aDiff = Abs(theRange.second - theRange.first); + Standard_Real aStep = FUN_CalcAverageDUV(aParamArray, aLength); + aStep = Max(aStep, aDiff / (Standard_Real) theStepsNb / 2.); + + Standard_Real aStdStep = aDiff / (Standard_Real) aLength; + if (aStep > aStdStep) + { + aStdStep = aStep; + } + aStdStep *= theScale; + + // Add parameters + for (Standard_Integer j = 1; j <= aLength; ++j) + { + const Standard_Real pp = aParamArray(j); + + Standard_Boolean isToInsert = Standard_True; + const Standard_Integer aParamsLength = aParams->Length(); + for (Standard_Integer i = 1; i <= aParamsLength && isToInsert; ++i) + { + isToInsert = (Abs(aParams->Value(i) - pp) > aStdStep); + } + + if (isToInsert) + { + aParams->Append(pp); + } + } + + return aParams; +} + +//======================================================================= +// Function: FUN_CalcAverageDUV +// Purpose : +//======================================================================= +Standard_Real BRepMesh_TorusRangeSplitter::FUN_CalcAverageDUV( + TColStd_Array1OfReal& P, const Standard_Integer PLen) const +{ + Standard_Integer i, j, n = 0; + Standard_Real p, result = 0.; + + for (i = 1; i <= PLen; i++) + { + // Sort + for (j = i + 1; j <= PLen; j++) + { + if (P(i) > P(j)) + { + p = P(i); + P(i) = P(j); + P(j) = p; + } + } + // Accumulate + if (i != 1) + { + p = Abs(P(i) - P(i - 1)); + if (p > 1.e-7) + { + result += p; + n++; + } + } + } + return (n ? (result / (Standard_Real) n) : -1.); +} diff --git a/src/BRepMesh/BRepMesh_TorusRangeSplitter.hxx b/src/BRepMesh/BRepMesh_TorusRangeSplitter.hxx new file mode 100644 index 0000000000..1373e7d0e0 --- /dev/null +++ b/src/BRepMesh/BRepMesh_TorusRangeSplitter.hxx @@ -0,0 +1,57 @@ +// Created on: 2016-07-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _BRepMesh_TorusRangeSplitter_HeaderFile +#define _BRepMesh_TorusRangeSplitter_HeaderFile + +#include +#include + +//! Auxiliary class extending UV range splitter in order to generate +//! internal nodes for NURBS surface. +class BRepMesh_TorusRangeSplitter : public BRepMesh_UVParamRangeSplitter +{ +public: + + //! Constructor. + BRepMesh_TorusRangeSplitter() + { + } + + //! Destructor. + virtual ~BRepMesh_TorusRangeSplitter() + { + } + + //! Returns list of nodes generated using surface data and specified parameters. + Standard_EXPORT virtual Handle(IMeshData::ListOfPnt2d) GenerateSurfaceNodes( + const IMeshTools_Parameters& theParameters) const Standard_OVERRIDE; + + //! Registers border point. + Standard_EXPORT virtual void AddPoint(const gp_Pnt2d& thePoint) Standard_OVERRIDE; + +private: + + Handle(IMeshData::SequenceOfReal) fillParams( + const IMeshData::IMapOfReal& theParams, + const std::pair& theRange, + const Standard_Integer theStepsNb, + const Standard_Real theScale, + const Handle(NCollection_IncAllocator)& theAllocator) const; + + Standard_Real FUN_CalcAverageDUV(TColStd_Array1OfReal& P, const Standard_Integer PLen) const; +}; + +#endif diff --git a/src/BRepMesh/BRepMesh_Triangle.hxx b/src/BRepMesh/BRepMesh_Triangle.hxx index f6a5bac399..6cb531a56b 100644 --- a/src/BRepMesh/BRepMesh_Triangle.hxx +++ b/src/BRepMesh/BRepMesh_Triangle.hxx @@ -34,14 +34,14 @@ public: //! Default constructor. BRepMesh_Triangle() - : myEdge1(0), - myEdge2(0), - myEdge3(0), - myOrientation1(Standard_False), - myOrientation2(Standard_False), - myOrientation3(Standard_False), - myMovability (BRepMesh_Free) + : myMovability (BRepMesh_Free) { + myEdges[0] = 0; + myEdges[1] = 0; + myEdges[2] = 0; + myOrientations[0] = Standard_False; + myOrientations[1] = Standard_False; + myOrientations[2] = Standard_False; } //! Constructor. @@ -65,12 +65,8 @@ public: const Standard_Boolean (&theOrientations)[3], const BRepMesh_DegreeOfFreedom theMovability) { - myEdge1 = theEdges[0]; - myEdge2 = theEdges[1]; - myEdge3 = theEdges[2]; - myOrientation1 = theOrientations[0]; - myOrientation2 = theOrientations[1]; - myOrientation3 = theOrientations[2]; + memcpy(myEdges, theEdges, sizeof(theEdges)); + memcpy(myOrientations, theOrientations, sizeof(theOrientations)); myMovability = theMovability; } @@ -80,12 +76,8 @@ public: inline void Edges(Standard_Integer (&theEdges)[3], Standard_Boolean (&theOrientations)[3]) const { - theEdges[0] = myEdge1; - theEdges[1] = myEdge2; - theEdges[2] = myEdge3; - theOrientations[0] = myOrientation1; - theOrientations[1] = myOrientation2; - theOrientations[2] = myOrientation3; + memcpy(theEdges, myEdges, sizeof(myEdges)); + memcpy(theOrientations, myOrientations, sizeof(myOrientations)); } //! Returns movability of the triangle. @@ -99,40 +91,40 @@ public: { myMovability = theMovability; } - - //! Returns hash code for this triangle. - //! @param theUpper upper index in the container. - //! @return hash code. - Standard_Integer HashCode(const Standard_Integer theUpper) const + + //! Computes a hash code for this triangle, in the range [1, theUpperBound] + //! @param theUpperBound the upper bound of the range a computing hash code must be within + //! @return a computed hash code, in the range [1, theUpperBound] + inline Standard_Integer HashCode (const Standard_Integer theUpperBound) const { - return ::HashCode(myEdge1 + myEdge2 + myEdge3, theUpper); + return ::HashCode (myEdges[0] + myEdges[1] + myEdges[2], theUpperBound); } - + //! Checks for equality with another triangle. //! @param theOther triangle to be checked against this one. //! @return TRUE if equal, FALSE if not. - Standard_Boolean IsEqual(const BRepMesh_Triangle& theOther) const + inline Standard_Boolean IsEqual(const BRepMesh_Triangle& theOther) const { if (myMovability == BRepMesh_Deleted || theOther.myMovability == BRepMesh_Deleted) return Standard_False; - if (myEdge1 == theOther.myEdge1 && - myEdge2 == theOther.myEdge2 && - myEdge3 == theOther.myEdge3) + if (myEdges[0] == theOther.myEdges[0] && + myEdges[1] == theOther.myEdges[1] && + myEdges[2] == theOther.myEdges[2]) { return Standard_True; } - if (myEdge1 == theOther.myEdge2 && - myEdge2 == theOther.myEdge3 && - myEdge3 == theOther.myEdge1) + if (myEdges[0] == theOther.myEdges[1] && + myEdges[1] == theOther.myEdges[2] && + myEdges[2] == theOther.myEdges[0]) { return Standard_True; } - if (myEdge1 == theOther.myEdge3 && - myEdge2 == theOther.myEdge1 && - myEdge3 == theOther.myEdge2) + if (myEdges[0] == theOther.myEdges[2] && + myEdges[1] == theOther.myEdges[0] && + myEdges[2] == theOther.myEdges[1]) { return Standard_True; } @@ -141,26 +133,23 @@ public: } //! Alias for IsEqual. - Standard_Boolean operator ==(const BRepMesh_Triangle& theOther) const + inline Standard_Boolean operator ==(const BRepMesh_Triangle& theOther) const { return IsEqual(theOther); } -private: - - Standard_Integer myEdge1; - Standard_Integer myEdge2; - Standard_Integer myEdge3; - Standard_Boolean myOrientation1; - Standard_Boolean myOrientation2; - Standard_Boolean myOrientation3; + Standard_Integer myEdges[3]; + Standard_Boolean myOrientations[3]; BRepMesh_DegreeOfFreedom myMovability; }; -inline Standard_Integer HashCode(const BRepMesh_Triangle& theTriangle, - const Standard_Integer theUpper) +//! Computes a hash code for the given triangle, in the range [1, theUpperBound] +//! @param theTriangle the triangle which hash code is to be computed +//! @param theUpperBound the upper bound of the range a computing hash code must be within +//! @return a computed hash code, in the range [1, theUpperBound] +inline Standard_Integer HashCode (const BRepMesh_Triangle& theTriangle, const Standard_Integer theUpperBound) { - return theTriangle.HashCode(theUpper); + return theTriangle.HashCode (theUpperBound); } #endif diff --git a/src/BRepMesh/BRepMesh_UVParamRangeSplitter.hxx b/src/BRepMesh/BRepMesh_UVParamRangeSplitter.hxx new file mode 100644 index 0000000000..f6d2b6223b --- /dev/null +++ b/src/BRepMesh/BRepMesh_UVParamRangeSplitter.hxx @@ -0,0 +1,81 @@ +// Created on: 2016-07-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _BRepMesh_UVParamRangeSplitter_HeaderFile +#define _BRepMesh_UVParamRangeSplitter_HeaderFile + +#include +#include + +//! Intended to generate internal mesh nodes using UV parameters of boundary discrete points. +class BRepMesh_UVParamRangeSplitter : public BRepMesh_DefaultRangeSplitter +{ +public: + + //! Constructor. + BRepMesh_UVParamRangeSplitter() + : myAllocator(new NCollection_IncAllocator(IMeshData::MEMORY_BLOCK_SIZE_HUGE)), + myUParams(1, myAllocator), + myVParams(1, myAllocator) + { + } + + //! Destructor. + virtual ~BRepMesh_UVParamRangeSplitter() + { + } + + //! Resets this splitter. + virtual void Reset(const IMeshData::IFaceHandle& theDFace, + const IMeshTools_Parameters& theParameters) Standard_OVERRIDE + { + BRepMesh_DefaultRangeSplitter::Reset(theDFace, theParameters); + myUParams.Clear(); + myVParams.Clear(); + myAllocator->Reset(Standard_False); + } + +public: + //! Returns U parameters. + inline const IMeshData::IMapOfReal& GetParametersU() const + { + return myUParams; + } + + //! Returns U parameters. + inline IMeshData::IMapOfReal& GetParametersU() + { + return myUParams; + } + + //! Returns V parameters. + inline const IMeshData::IMapOfReal& GetParametersV() const + { + return myVParams; + } + + //! Returns V parameters. + inline IMeshData::IMapOfReal& GetParametersV() + { + return myVParams; + } + +private: + Handle(NCollection_IncAllocator) myAllocator; + IMeshData::IMapOfReal myUParams; + IMeshData::IMapOfReal myVParams; +}; + +#endif diff --git a/src/BRepMesh/BRepMesh_Vertex.hxx b/src/BRepMesh/BRepMesh_Vertex.hxx index 7cb7d72346..73a31798ea 100644 --- a/src/BRepMesh/BRepMesh_Vertex.hxx +++ b/src/BRepMesh/BRepMesh_Vertex.hxx @@ -20,6 +20,7 @@ #include #include #include +#include //! Light weighted structure representing vertex //! of the mesh in parametric space. Vertex could be @@ -102,19 +103,19 @@ public: { myMovability = theMovability; } - - //! Returns hash code for this vertex. - //! @param theUpper upper index in the container. - //! @return hash code. - Standard_Integer HashCode(const Standard_Integer Upper) const + + //! Computes a hash code for this vertex, in the range [1, theUpperBound] + //! @param theUpperBound the upper bound of the range a computing hash code must be within + //! @return a computed hash code, in the range [1, theUpperBound] + inline Standard_Integer HashCode(const Standard_Integer theUpperBound) const { - return ::HashCode(Floor(1e5 * myUV.X()) * Floor(1e5 * myUV.Y()), Upper); + return ::HashCode(Floor(1e5 * myUV.X()) * Floor(1e5 * myUV.Y()), theUpperBound); } //! Checks for equality with another vertex. //! @param theOther vertex to be checked against this one. //! @return TRUE if equal, FALSE if not. - Standard_Boolean IsEqual(const BRepMesh_Vertex& theOther) const + inline Standard_Boolean IsEqual(const BRepMesh_Vertex& theOther) const { if (myMovability == BRepMesh_Deleted || theOther.myMovability == BRepMesh_Deleted) @@ -126,7 +127,7 @@ public: } //! Alias for IsEqual. - Standard_Boolean operator ==(const BRepMesh_Vertex& Other) const + inline Standard_Boolean operator ==(const BRepMesh_Vertex& Other) const { return IsEqual(Other); } @@ -138,9 +139,13 @@ private: BRepMesh_DegreeOfFreedom myMovability; }; -inline Standard_Integer HashCode(const BRepMesh_Vertex& me, const Standard_Integer Upper) +//! Computes a hash code for the given vertex, in the range [1, theUpperBound] +//! @param theVertex the vertex which hash code is to be computed +//! @param theUpperBound the upper bound of the range a computing hash code must be within +//! @return a computed hash code, in the range [1, theUpperBound] +inline Standard_Integer HashCode (const BRepMesh_Vertex& theVertex, const Standard_Integer theUpperBound) { - return me.HashCode(Upper); + return theVertex.HashCode (theUpperBound); } #endif diff --git a/src/BRepMesh/BRepMesh_VertexInspector.hxx b/src/BRepMesh/BRepMesh_VertexInspector.hxx index 3b22160ec6..dfd51ae926 100644 --- a/src/BRepMesh/BRepMesh_VertexInspector.hxx +++ b/src/BRepMesh/BRepMesh_VertexInspector.hxx @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include @@ -31,13 +31,14 @@ public: //! Constructor. //! @param theAllocator memory allocator to be used by internal collections. - BRepMesh_VertexInspector ( + BRepMesh_VertexInspector( const Handle(NCollection_IncAllocator)& theAllocator) - : myResIndices(theAllocator), - myVertices (new BRepMesh::VectorOfVertex), - myDelNodes (theAllocator) + : myIndex(0), + myMinSqDist(RealLast()), + myVertices(new IMeshData::VectorOfVertex), + myDelNodes(theAllocator) { - SetTolerance( Precision::Confusion() ); + SetTolerance(Precision::Confusion()); } //! Registers the given vertex. @@ -106,35 +107,32 @@ public: //! Set reference point to be checked. inline void SetPoint(const gp_XY& thePoint) { - myResIndices.Clear(); - myPoint = thePoint; + myIndex = 0; + myMinSqDist = RealLast(); + myPoint = thePoint; } //! Returns index of point coinciding with regerence one. inline Standard_Integer GetCoincidentPoint() const { - if ( myResIndices.Size() > 0 ) - { - return myResIndices.First(); - } - return 0; + return myIndex; } //! Returns list with indexes of vertices that have movability attribute //! equal to BRepMesh_Deleted and can be replaced with another node. - inline const BRepMesh::ListOfInteger& GetListOfDelPoints() const + inline const IMeshData::ListOfInteger& GetListOfDelPoints() const { return myDelNodes; } //! Returns set of mesh vertices. - inline const BRepMesh::HVectorOfVertex& Vertices() const + inline const Handle(IMeshData::VectorOfVertex)& Vertices() const { return myVertices; } //! Returns set of mesh vertices for modification. - inline BRepMesh::HVectorOfVertex& ChangeVertices() + inline Handle(IMeshData::VectorOfVertex)& ChangeVertices() { return myVertices; } @@ -153,11 +151,12 @@ public: private: - Standard_Real myTolerance[2]; - BRepMesh::ListOfInteger myResIndices; - BRepMesh::HVectorOfVertex myVertices; - BRepMesh::ListOfInteger myDelNodes; - gp_XY myPoint; + Standard_Integer myIndex; + Standard_Real myMinSqDist; + Standard_Real myTolerance[2]; + Handle(IMeshData::VectorOfVertex) myVertices; + IMeshData::ListOfInteger myDelNodes; + gp_XY myPoint; }; #endif diff --git a/src/BRepMesh/BRepMesh_VertexTool.cxx b/src/BRepMesh/BRepMesh_VertexTool.cxx index ecad73c435..fffa7ac4da 100644 --- a/src/BRepMesh/BRepMesh_VertexTool.cxx +++ b/src/BRepMesh/BRepMesh_VertexTool.cxx @@ -14,11 +14,7 @@ // commercial license or contractual agreement. #include -#include -#include #include -#include -#include //======================================================================= //function : Inspect @@ -45,8 +41,16 @@ NCollection_CellFilter_Action BRepMesh_VertexInspector::Inspect( inTol = ((aVec.X() * aVec.X()) < myTolerance[0]) && ((aVec.Y() * aVec.Y()) < myTolerance[1]); } + if (inTol) - myResIndices.Append(theTarget); + { + const Standard_Real aSqDist = aVec.SquareModulus(); + if (aSqDist < myMinSqDist) + { + myMinSqDist = aSqDist; + myIndex = theTarget; + } + } return CellFilter_Keep; } @@ -90,7 +94,7 @@ Standard_Integer BRepMesh_VertexTool::Add( //function : Delete //purpose : //======================================================================= -void BRepMesh_VertexTool::Delete(const Standard_Integer theIndex) +void BRepMesh_VertexTool::DeleteVertex(const Standard_Integer theIndex) { BRepMesh_Vertex& aV = mySelector.GetVertex(theIndex); diff --git a/src/BRepMesh/BRepMesh_VertexTool.hxx b/src/BRepMesh/BRepMesh_VertexTool.hxx index b18b3e6179..35aa778a8a 100644 --- a/src/BRepMesh/BRepMesh_VertexTool.hxx +++ b/src/BRepMesh/BRepMesh_VertexTool.hxx @@ -15,26 +15,21 @@ #define _BRepMesh_VertexTool_HeaderFile #include -#include -#include -#include +#include #include -#include #include -#include #include +#include class BRepMesh_Vertex; //! Describes data structure intended to keep mesh nodes //! defined in UV space and implements functionality -//! providing their uniqueness regarding thir position. -class BRepMesh_VertexTool +//! providing their uniqueness regarding their position. +class BRepMesh_VertexTool : public Standard_Transient { public: - DEFINE_STANDARD_ALLOC - //! Constructor. //! @param theAllocator memory allocator to be used by internal collections. Standard_EXPORT BRepMesh_VertexTool( @@ -101,16 +96,16 @@ public: const Standard_Boolean isForceAdd); //! Deletes vertex with the given index from the tool. - Standard_EXPORT void Delete(const Standard_Integer theIndex); + Standard_EXPORT void DeleteVertex(const Standard_Integer theIndex); //! Returns set of mesh vertices. - inline const BRepMesh::HVectorOfVertex& Vertices() const + inline const Handle(IMeshData::VectorOfVertex)& Vertices() const { return mySelector.Vertices(); } //! Returns set of mesh vertices. - inline BRepMesh::HVectorOfVertex& ChangeVertices() + inline Handle(IMeshData::VectorOfVertex)& ChangeVertices() { return mySelector.ChangeVertices(); } @@ -150,12 +145,12 @@ public: //! Remove last node from the structure. inline void RemoveLast() { - Delete(Extent()); + DeleteVertex(Extent()); } //! Returns the list with indexes of vertices that have movability attribute //! equal to BRepMesh_Deleted and can be replaced with another node. - inline const BRepMesh::ListOfInteger& GetListOfDelNodes() const + inline const IMeshData::ListOfInteger& GetListOfDelNodes() const { return mySelector.GetListOfDelPoints(); } @@ -163,6 +158,8 @@ public: //! Prints statistics. Standard_EXPORT void Statistics(Standard_OStream& theStream) const; + DEFINE_STANDARD_RTTI_INLINE(BRepMesh_VertexTool, Standard_Transient) + private: //! Expands the given point according to specified tolerance. @@ -181,10 +178,10 @@ private: private: - Handle(NCollection_IncAllocator) myAllocator; - BRepMesh::VertexCellFilter myCellFilter; - BRepMesh_VertexInspector mySelector; - Standard_Real myTolerance[2]; + Handle(NCollection_IncAllocator) myAllocator; + IMeshData::VertexCellFilter myCellFilter; + BRepMesh_VertexInspector mySelector; + Standard_Real myTolerance[2]; }; #endif diff --git a/src/BRepMesh/BRepMesh_WireChecker.cxx b/src/BRepMesh/BRepMesh_WireChecker.cxx deleted file mode 100644 index 5def2f1be7..0000000000 --- a/src/BRepMesh/BRepMesh_WireChecker.cxx +++ /dev/null @@ -1,410 +0,0 @@ -// Created on: 2014-06-03 -// Created by: Oleg AGASHIN -// Copyright (c) 1997-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 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -//======================================================================= -//function : Selector::Constructor -//purpose : -//======================================================================= -BRepMesh_WireChecker::BndBox2dTreeSelector::BndBox2dTreeSelector( - const Standard_Integer theReservedSize) - : mySkippedIndex(-1), - myIndices(0, theReservedSize - 1), - myIndicesNb(0) -{ -} - -//======================================================================= -//function : Reject -//purpose : -//======================================================================= -Standard_Boolean BRepMesh_WireChecker::BndBox2dTreeSelector::Reject( - const Bnd_Box2d& theBox2D) const -{ - return myBox2D.IsOut(theBox2D); -} - -//======================================================================= -//function : Accept -//purpose : -//======================================================================= -Standard_Boolean BRepMesh_WireChecker::BndBox2dTreeSelector::Accept( - const Standard_Integer& theIndex) -{ - if (theIndex <= mySkippedIndex) - return Standard_False; - - myIndices(myIndicesNb++) = theIndex; - return Standard_True; -} - -//======================================================================= -//function : Clear -//purpose : -//======================================================================= -void BRepMesh_WireChecker::BndBox2dTreeSelector::Clear() -{ - mySkippedIndex = -1; - myIndicesNb = 0; -} - -//======================================================================= -//function : SetBox -//purpose : -//======================================================================= -void BRepMesh_WireChecker::BndBox2dTreeSelector::SetBox( - const Bnd_Box2d& theBox2D) -{ - myBox2D = theBox2D; -} - -//======================================================================= -//function : Clear -//purpose : -//======================================================================= -void BRepMesh_WireChecker::BndBox2dTreeSelector::SetSkippedIndex( - const Standard_Integer theIndex) -{ - mySkippedIndex = theIndex; -} - -//======================================================================= -//function : Indices -//purpose : -//======================================================================= -const BRepMesh::Array1OfInteger& - BRepMesh_WireChecker::BndBox2dTreeSelector::Indices() const -{ - return myIndices; -} - -//======================================================================= -//function : IndicesNb -//purpose : -//======================================================================= -Standard_Integer BRepMesh_WireChecker::BndBox2dTreeSelector::IndicesNb() const -{ - return myIndicesNb; -} - -//======================================================================= -//function : Constructor -//purpose : -//======================================================================= -BRepMesh_WireChecker::BRepMesh_WireChecker( - const TopoDS_Face& theFace, - const Standard_Real theTolUV, - const BRepMesh::HDMapOfShapePairOfPolygon& theEdges, - const BRepMesh::HIMapOfInteger& theVertexMap, - const Handle(BRepMesh_DataStructureOfDelaun)& theStructure, - const Standard_Real theUmin, - const Standard_Real theUmax, - const Standard_Real theVmin, - const Standard_Real theVmax, - const Standard_Boolean isInParallel) - : myTolUV(theTolUV), - myEdges(theEdges), - myVertexMap(theVertexMap), - myStructure(theStructure), - myUmin(theUmin), - myUmax(theUmax), - myVmin(theVmin), - myVmax(theVmax), - myStatus(BRepMesh_NoError), - myIsInParallel(isInParallel) -{ - TopoDS_Face aFace = theFace; - aFace.Orientation(TopAbs_FORWARD); - - for (TopoDS_Iterator aFaceIt(aFace); aFaceIt.More(); aFaceIt.Next()) - { - if (aFaceIt.Value().IsNull() || aFaceIt.Value().ShapeType() != TopAbs_WIRE) // may be inner vertex - continue; - const TopoDS_Wire& aWire = TopoDS::Wire(aFaceIt.Value()); - - myWiresEdges.Append(ListOfEdges()); - ListOfEdges& aEdges = myWiresEdges.ChangeLast(); - - // Start traversing the wires - BRepTools_WireExplorer aWireExplorer(aWire, aFace); - for (; aWireExplorer.More(); aWireExplorer.Next()) - { - const TopoDS_Edge& aEdge = aWireExplorer.Current(); - TopAbs_Orientation aOrient = aEdge.Orientation(); - if (aOrient != TopAbs_FORWARD && aOrient != TopAbs_REVERSED) - continue; - - aEdges.Append(aEdge); - } - - if (aEdges.IsEmpty()) - myWiresEdges.Remove(myWiresEdges.Size()); - } -} - -//======================================================================= -//function : ReCompute -//purpose : -//======================================================================= -void BRepMesh_WireChecker::ReCompute(BRepMesh::HClassifier& theClassifier) -{ - if (theClassifier.IsNull()) - return; - - theClassifier->Destroy(); - myStatus = BRepMesh_NoError; - - SeqOfDWires aDWires; - if (!collectDiscretizedWires(aDWires)) - return; - - const Standard_Integer aNbWires = aDWires.Size(); - BRepMesh::Array1OfSegmentsTree aWiresBiPoints(1, aNbWires); - fillSegmentsTree(aDWires, aWiresBiPoints); - - if (myIsInParallel && aNbWires > 1) - { - // Check wires in parallel threads. - Standard_Mutex aWireMutex; - BRepMesh_WireInterferenceChecker aIntChecker(aWiresBiPoints, &myStatus, &aWireMutex); - OSD_Parallel::For(1, aNbWires + 1, aIntChecker); - } - else - { - BRepMesh_WireInterferenceChecker aIntChecker(aWiresBiPoints, &myStatus); - OSD_Parallel::For(1, aNbWires + 1, aIntChecker, Standard_True); - } - - if (myStatus == BRepMesh_SelfIntersectingWire) - return; - - // Find holes - SeqOfDWires::Iterator aDWiresIt(aDWires); - for (; aDWiresIt.More(); aDWiresIt.Next()) - { - const SeqOfPnt2d& aDWire = aDWiresIt.Value(); - theClassifier->RegisterWire(aDWire, myTolUV, myUmin, myUmax, myVmin, myVmax); - } -} - -//======================================================================= -//function : collectDiscretizedWires -//purpose : -//======================================================================= -Standard_Boolean BRepMesh_WireChecker::collectDiscretizedWires( - SeqOfDWires& theDWires) -{ - SeqOfWireEdges::Iterator aWireIt(myWiresEdges); - for(; aWireIt.More(); aWireIt.Next()) - { - const ListOfEdges& aEdges = aWireIt.Value(); - // For each wire we create a data map, linking vertices (only - // the ends of edges) with their positions in the sequence of - // all 2d points from this wire. - // When we meet some vertex for the second time - the piece - // of sequence is treated for a HOLE and quits the sequence. - // Actually, we must unbind the vertices belonging to the - // loop from the map, but since they can't appear twice on the - // valid wire, leave them for a little speed up. - - SeqOfPnt2d aSeqPnt2d; - BRepMesh::MapOfIntegerInteger aNodeInSeq; - Standard_Integer aFirstIndex = 0, aLastIndex = 0; - - // Start traversing the wire - ListOfEdges::Iterator aEdgeIt(aEdges); - for (; aEdgeIt.More(); aEdgeIt.Next()) - { - const TopoDS_Edge& aEdge = aEdgeIt.Value(); - TopAbs_Orientation aOrient = aEdge.Orientation(); - if (!myEdges->IsBound(aEdge)) - continue; - - // Retrieve polygon - // Define the direction for adding points to aSeqPnt2d - Standard_Integer aStartId, aEndId, aIncrement; - const BRepMesh_PairOfPolygon& aPair = myEdges->Find(aEdge); - Handle(Poly_PolygonOnTriangulation) aNOD; - if (aOrient == TopAbs_FORWARD) - { - aNOD = aPair.First(); - aStartId = 1; - aEndId = aNOD->NbNodes(); - aIncrement = 1; - } - else - { - aNOD = aPair.Last(); - aStartId = aNOD->NbNodes(); - aEndId = 1; - aIncrement = -1; - } - - const TColStd_Array1OfInteger& aIndices = aNOD->Nodes(); - const Standard_Integer aFirstVertexId = myVertexMap->FindKey(aIndices(aStartId)); - const Standard_Integer aLastVertexId = myVertexMap->FindKey(aIndices(aEndId) ); - - if (aFirstVertexId == aLastVertexId && (aEndId - aStartId) == aIncrement) - { - // case of continuous set of degenerated edges - aLastIndex = aLastVertexId; - continue; - } - - if (aFirstIndex != 0) - { - if (aFirstVertexId != aLastIndex) - { - // there's a gap between edges - myStatus = BRepMesh_OpenWire; - return Standard_False; - } - } - else - aFirstIndex = aFirstVertexId; - - aLastIndex = aLastVertexId; - - // Record first vertex (to detect loops) - aNodeInSeq.Bind(aFirstVertexId, (aSeqPnt2d.Length() + 1)); - - // Add vertices in sequence - for (Standard_Integer i = aStartId; i != aEndId; i += aIncrement) - { - Standard_Integer aIndex = ((i == aStartId) ? - aFirstVertexId : - myVertexMap->FindKey(aIndices(i))); - - aSeqPnt2d.Append(gp_Pnt2d(myStructure->GetNode(aIndex).Coord())); - } - - // Now, is there a loop? - if (aNodeInSeq.IsBound(aLastVertexId)) - { - // Yes, treat it separately as a hole - // Divide points into main wire and a loop - const Standard_Integer aIdxWireStart = aNodeInSeq(aLastVertexId); - if(aIdxWireStart < aSeqPnt2d.Length()) - { - theDWires.Append(SeqOfPnt2d()); - SeqOfPnt2d& aWire = theDWires.ChangeLast(); - aSeqPnt2d.Split(aIdxWireStart, aWire); - } - } - } - - if (aFirstIndex == 0) - continue; - - // Isn't wire open? - if (aFirstIndex != aLastIndex || aSeqPnt2d.Length() > 1) - { - myStatus = BRepMesh_OpenWire; - return Standard_False; - } - } - - return Standard_True; -} - -//======================================================================= -//function : fillSegmentsTree -//purpose : -//======================================================================= -void BRepMesh_WireChecker::fillSegmentsTree( - const SeqOfDWires& theDWires, - BRepMesh::Array1OfSegmentsTree& theWiresSegmentsTree) -{ - const Standard_Integer aNbWires = theDWires.Size(); - for (Standard_Integer aWireIt = 1; aWireIt <= aNbWires; ++aWireIt) - { - const SeqOfPnt2d& aWire = theDWires(aWireIt); - const Standard_Integer aWireLen = aWire.Size(); - - BRepMesh::HArray1OfSegments aWireSegments = - new BRepMesh::Array1OfSegments(1, aWireLen); - - BRepMesh::HBndBox2dTree aBndBoxTree = - new BRepMesh::BndBox2dTree; - - BRepMesh::BndBox2dTreeFiller aBndBoxTreeFiller(*aBndBoxTree); - - Standard_Real x1 = 0., y1 = 0., aXstart = 0., aYstart = 0.; - for (Standard_Integer aPntIt = 0; aPntIt <= aWireLen; ++aPntIt) - { - Standard_Real x2, y2; - // Obtain last point of the segment - if (aPntIt == aWireLen) - { - x2 = aXstart; - y2 = aYstart; - } - else - { - const gp_Pnt2d& aPnt = aWire(aPntIt + 1); - x2 = aPnt.X(); - y2 = aPnt.Y(); - } - - // Build segment (bi-point) - if (aPntIt == 0) - { - aXstart = x2; - aYstart = y2; - } - else - { - gp_Pnt2d aStartPnt(x1, y1); - gp_Pnt2d aEndPnt(x2, y2); - - BRepMesh::Segment& aSegment = aWireSegments->ChangeValue(aPntIt); - aSegment.StartPnt = aStartPnt.XY(); - aSegment.EndPnt = aEndPnt.XY(); - - Bnd_Box2d aBox; - aBox.Add(aStartPnt); - aBox.Add( aEndPnt); - aBndBoxTreeFiller.Add(aPntIt, aBox); - } - x1 = x2; - y1 = y2; - } - aBndBoxTreeFiller.Fill(); - - BRepMesh::SegmentsTree& aSegmentsTree = theWiresSegmentsTree(aWireIt); - aSegmentsTree.first = aWireSegments; - aSegmentsTree.second = aBndBoxTree; - } -} diff --git a/src/BRepMesh/BRepMesh_WireChecker.hxx b/src/BRepMesh/BRepMesh_WireChecker.hxx deleted file mode 100644 index 9b12a8553f..0000000000 --- a/src/BRepMesh/BRepMesh_WireChecker.hxx +++ /dev/null @@ -1,142 +0,0 @@ -// Created on: 2014-06-03 -// Created by: Oleg AGASHIN -// Copyright (c) 1997-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. - -#ifndef _BRepMesh_WireChecker_HeaderFile -#define _BRepMesh_WireChecker_HeaderFile - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - - -//! Auxilary class intended to check correctness of discretized face. -//! In particular, checks boundaries of discretized face for self -//! intersections and gaps. -class BRepMesh_WireChecker -{ -public: - - //! Selector. - //! Used to identify segments with overlapped bounding boxes. - //! Note that instance of selector can be used only once due to - //! unextentable array of indices. - class BndBox2dTreeSelector : public BRepMesh::BndBox2dTree::Selector - { - public: - Standard_EXPORT BndBox2dTreeSelector(const Standard_Integer theReservedSize); - Standard_EXPORT virtual Standard_Boolean Reject(const Bnd_Box2d& theBox2D) const; - Standard_EXPORT virtual Standard_Boolean Accept(const Standard_Integer& theIndex); - - Standard_EXPORT void Clear(); - Standard_EXPORT void SetBox(const Bnd_Box2d& theBox2D); - Standard_EXPORT void SetSkippedIndex(const Standard_Integer theIndex); - Standard_EXPORT const BRepMesh::Array1OfInteger& Indices() const; - Standard_EXPORT Standard_Integer IndicesNb() const; - - protected: - Bnd_Box2d myBox2D; - Standard_Integer mySkippedIndex; - BRepMesh::Array1OfInteger myIndices; - Standard_Integer myIndicesNb; - }; - -private: - - typedef NCollection_List ListOfEdges; - typedef NCollection_Sequence SeqOfWireEdges; - - typedef NCollection_Sequence SeqOfPnt2d; - typedef NCollection_Sequence SeqOfDWires; - -public: - - //! Constructor. - //! @param theFace Face to be checked. - //! @param theTolUV Tolerance to be used for calculations in parametric space. - //! @param theEdges Map of edges with associated polygon on triangulation. - //! @param theVertexMap Map of face vertices. - //! @param theStructure Discretized representation of face in parametric space. - //! @param theUmin Lower U boundary of the face in parametric space. - //! @param theUmax Upper U boundary of the face in parametric space. - //! @param theVmin Lower V boundary of the face in parametric space. - //! @param theVmax Upper V boundary of the face in parametric space. - Standard_EXPORT BRepMesh_WireChecker( - const TopoDS_Face& theFace, - const Standard_Real theTolUV, - const BRepMesh::HDMapOfShapePairOfPolygon& theEdges, - const BRepMesh::HIMapOfInteger& theVertexMap, - const Handle(BRepMesh_DataStructureOfDelaun)& theStructure, - const Standard_Real theUmin, - const Standard_Real theUmax, - const Standard_Real theVmin, - const Standard_Real theVmax, - const Standard_Boolean isInParallel); - - //! Recompute data using parameters passed in constructor. - //! @param[out] theClassifier Classifier to be updated using calculated data. - Standard_EXPORT void ReCompute(BRepMesh::HClassifier& theClassifier); - - //! Returns status of the check. - inline BRepMesh_Status Status() const - { - return myStatus; - } - -private: - - //! Collects discrete wires. - //! @param[out] theDWires sequence of discretized wires to be filled. - //! @return TRUE on success, FALSE in case of open wire. - Standard_Boolean collectDiscretizedWires(SeqOfDWires& theDWires); - - //! Fills array of BiPoints for corresponding wire. - //! @param theDWires Sequence of wires to be processed. - //! @param theWiresSegmentsTree Array of segments with corresponding - //! bounding boxes trees to be filled. - void fillSegmentsTree( - const SeqOfDWires& theDWires, - BRepMesh::Array1OfSegmentsTree& theWiresSegmentsTree); - - //! Assignment operator. - void operator =(BRepMesh_WireChecker& /*theOther*/) - { - } - -private: - - const Standard_Real myTolUV; - const BRepMesh::HDMapOfShapePairOfPolygon& myEdges; - const BRepMesh::HIMapOfInteger& myVertexMap; - const Handle(BRepMesh_DataStructureOfDelaun)& myStructure; - const Standard_Real myUmin; - const Standard_Real myUmax; - const Standard_Real myVmin; - const Standard_Real myVmax; - BRepMesh_Status myStatus; - SeqOfWireEdges myWiresEdges; - Standard_Boolean myIsInParallel; -}; - -#endif diff --git a/src/BRepMesh/BRepMesh_WireInterferenceChecker.cxx b/src/BRepMesh/BRepMesh_WireInterferenceChecker.cxx deleted file mode 100644 index 326dc8c3ac..0000000000 --- a/src/BRepMesh/BRepMesh_WireInterferenceChecker.cxx +++ /dev/null @@ -1,134 +0,0 @@ -// Created on: 2014-06-18 -// Created by: Oleg AGASHIN -// Copyright (c) 2011-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 -#include -#include - -// TODO: remove this variable after implementation of LoopChecker2d. -static const Standard_Real MIN_LOOP_S = 2 * M_PI * 2.E-5; - -//======================================================================= -//function : Constructor -//purpose : -//======================================================================= -BRepMesh_WireInterferenceChecker::BRepMesh_WireInterferenceChecker( - const BRepMesh::Array1OfSegmentsTree& theWires, - BRepMesh_Status* theStatus, - Standard_Mutex* theMutex) -: myWires (theWires), - myStatus(theStatus), - myMutex (theMutex) -{ -} - -//======================================================================= -//function : Checker's body -//purpose : -//======================================================================= -void BRepMesh_WireInterferenceChecker::operator ()( - const Standard_Integer& theWireId) const -{ - if (*myStatus == BRepMesh_SelfIntersectingWire) - return; - - const BRepMesh::SegmentsTree& aWireSegTree1 = myWires(theWireId); - const BRepMesh::HArray1OfSegments& aWireSegments1 = aWireSegTree1.first; - const BRepMesh::HBndBox2dTree& aWireBoxTree1 = aWireSegTree1.second; - - for (Standard_Integer aWireIt = theWireId; aWireIt <= myWires.Upper(); ++aWireIt) - { - // Break execution in case if flag was raised by another thread. - if (*myStatus == BRepMesh_SelfIntersectingWire) - return; - - const Standard_Boolean isSelfIntCheck = (aWireIt == theWireId); - const BRepMesh::SegmentsTree& aWireSegTree2 = - isSelfIntCheck ? aWireSegTree1 : myWires(aWireIt); - - const BRepMesh::HArray1OfSegments& aWireSegments2 = aWireSegTree2.first; - const BRepMesh::HBndBox2dTree& aWireBoxTree2 = aWireSegTree2.second; - - BRepMesh_WireChecker::BndBox2dTreeSelector aSelector (aWireSegments2->Size()); - - Standard_Integer aSegmentId1 = aWireSegments1->Lower(); - for (; aSegmentId1 <= aWireSegments1->Upper(); ++aSegmentId1) - { - // Break execution in case if flag was raised by another thread - if (*myStatus == BRepMesh_SelfIntersectingWire) - return; - - aSelector.Clear(); - aSelector.SetBox(aWireBoxTree1->FindNode(aSegmentId1).Bnd()); - if (isSelfIntCheck) - aSelector.SetSkippedIndex(aSegmentId1); - - if (aWireBoxTree2->Select(aSelector) == 0) - continue; - - const BRepMesh::Segment& aSegment1 = aWireSegments1->Value(aSegmentId1); - const BRepMesh::Array1OfInteger& aSelected = aSelector.Indices(); - const Standard_Integer aSelectedNb = aSelector.IndicesNb(); - for (Standard_Integer aBndIt = 0; aBndIt < aSelectedNb; ++aBndIt) - { - // Break execution in case if flag was raised by another thread - if (*myStatus == BRepMesh_SelfIntersectingWire) - return; - - const Standard_Integer aSegmentId2 = aSelected(aBndIt); - const BRepMesh::Segment& aSegment2 = aWireSegments2->Value(aSegmentId2); - - gp_Pnt2d aIntPnt; - BRepMesh_GeomTool::IntFlag aIntStatus = BRepMesh_GeomTool::IntSegSeg( - aSegment1.StartPnt, aSegment1.EndPnt, - aSegment2.StartPnt, aSegment2.EndPnt, - Standard_False, Standard_False, - aIntPnt); - - if (aIntStatus == BRepMesh_GeomTool::Cross) - { - // TODO: remove this block after implementation of LoopChecker2d. - if (isSelfIntCheck) - { - gp_XY aPrevVec; - Standard_Real aSumS = 0.; - const gp_XY& aRefPnt = aIntPnt.Coord(); - for (Standard_Integer i = aSegmentId1; i < aSegmentId2; ++i) - { - const BRepMesh::Segment& aSeg = aWireSegments1->Value(i); - gp_XY aCurVec = aSeg.EndPnt - aRefPnt; - - if (aCurVec.SquareModulus() < gp::Resolution()) - continue; - - if (aPrevVec.SquareModulus() > gp::Resolution()) - aSumS += aPrevVec ^ aCurVec; - - aPrevVec = aCurVec; - } - - if (Abs(aSumS / 2.) < MIN_LOOP_S) - continue; - } - - Standard_Mutex::Sentry aSentry(myMutex); - *myStatus = BRepMesh_SelfIntersectingWire; - - return; - } - } - } - } -} diff --git a/src/BRepMesh/BRepMesh_WireInterferenceChecker.hxx b/src/BRepMesh/BRepMesh_WireInterferenceChecker.hxx deleted file mode 100644 index 03e7055ed4..0000000000 --- a/src/BRepMesh/BRepMesh_WireInterferenceChecker.hxx +++ /dev/null @@ -1,67 +0,0 @@ -// Created on: 2014-06-18 -// Created by: Oleg AGASHIN -// Copyright (c) 2011-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. - -#ifndef _BRepMesh_WireInterferenceChecker_HeaderFile -#define _BRepMesh_WireInterferenceChecker_HeaderFile - -#include -#include -#include -#include - -//! Auxilary class implementing functionality for -//! checking interference between two discretized wires. -class BRepMesh_WireInterferenceChecker -{ -public: - - //! Enumerates states of segments intersection check. - enum IntFlag - { - NoIntersection, - Cross, - EndPointTouch, - PointOnSegment, - Glued, - Same - }; - - //! Constructor - //! @param theWires wires that should be checked. - //! @param theStatus shared flag to set status of the check. - //! @param theMutex shared mutex for parallel processing. - BRepMesh_WireInterferenceChecker( - const BRepMesh::Array1OfSegmentsTree& theWires, - BRepMesh_Status* theStatus, - Standard_Mutex* theMutex = NULL); - - //! Checker's body. - //! @param theWireId Id of discretized wire to be checked. - void operator ()(const Standard_Integer& theWireId) const; - -private: - - //! Assignment operator. - void operator =(const BRepMesh_WireInterferenceChecker& /*theOther*/) - { - } - -private: - const BRepMesh::Array1OfSegmentsTree& myWires; - BRepMesh_Status* myStatus; - Standard_Mutex* myMutex; -}; - -#endif diff --git a/src/BRepMesh/FILES b/src/BRepMesh/FILES index ec39094842..a37a4504e4 100755 --- a/src/BRepMesh/FILES +++ b/src/BRepMesh/FILES @@ -1,55 +1,88 @@ -BRepMesh.hxx +BRepMesh_BaseMeshAlgo.cxx +BRepMesh_BaseMeshAlgo.hxx +BRepMesh_ConstrainedBaseMeshAlgo.hxx +BRepMesh_BoundaryParamsRangeSplitter.hxx BRepMesh_Circle.hxx BRepMesh_CircleInspector.hxx BRepMesh_CircleTool.cxx BRepMesh_CircleTool.hxx BRepMesh_Classifier.cxx BRepMesh_Classifier.hxx +BRepMesh_ConeRangeSplitter.cxx +BRepMesh_ConeRangeSplitter.hxx +BRepMesh_Context.cxx +BRepMesh_Context.hxx +BRepMesh_CurveTessellator.cxx +BRepMesh_CurveTessellator.hxx +BRepMesh_CylinderRangeSplitter.cxx +BRepMesh_CylinderRangeSplitter.hxx BRepMesh_DataStructureOfDelaun.cxx BRepMesh_DataStructureOfDelaun.hxx +BRepMesh_DefaultRangeSplitter.cxx +BRepMesh_DefaultRangeSplitter.hxx +BRepMesh_Deflection.cxx +BRepMesh_Deflection.hxx BRepMesh_DegreeOfFreedom.hxx BRepMesh_Delaun.cxx BRepMesh_Delaun.hxx +BRepMesh_DelaunayBaseMeshAlgo.cxx +BRepMesh_DelaunayBaseMeshAlgo.hxx +BRepMesh_DelaunayDeflectionControlMeshAlgo.hxx +BRepMesh_DelaunayNodeInsertionMeshAlgo.hxx BRepMesh_DiscretFactory.cxx BRepMesh_DiscretFactory.hxx BRepMesh_DiscretRoot.cxx BRepMesh_DiscretRoot.hxx BRepMesh_Edge.hxx -BRepMesh_EdgeParameterProvider.cxx +BRepMesh_EdgeDiscret.cxx +BRepMesh_EdgeDiscret.hxx BRepMesh_EdgeParameterProvider.hxx BRepMesh_EdgeTessellationExtractor.cxx BRepMesh_EdgeTessellationExtractor.hxx -BRepMesh_EdgeTessellator.cxx -BRepMesh_EdgeTessellator.hxx -BRepMesh_FaceAttribute.cxx -BRepMesh_FaceAttribute.hxx +BRepMesh_FaceChecker.cxx +BRepMesh_FaceChecker.hxx +BRepMesh_FaceDiscret.cxx +BRepMesh_FaceDiscret.hxx BRepMesh_FactoryError.hxx -BRepMesh_FastDiscret.cxx BRepMesh_FastDiscret.hxx -BRepMesh_FastDiscretFace.cxx -BRepMesh_FastDiscretFace.hxx BRepMesh_GeomTool.cxx BRepMesh_GeomTool.hxx -BRepMesh_IEdgeTool.cxx -BRepMesh_IEdgeTool.hxx BRepMesh_IncrementalMesh.cxx BRepMesh_IncrementalMesh.hxx +BRepMesh_MeshAlgoFactory.cxx +BRepMesh_MeshAlgoFactory.hxx +BRepMesh_MeshTool.cxx +BRepMesh_MeshTool.hxx +BRepMesh_ModelBuilder.cxx +BRepMesh_ModelBuilder.hxx +BRepMesh_ModelHealer.cxx +BRepMesh_ModelHealer.hxx +BRepMesh_ModelPostProcessor.cxx +BRepMesh_ModelPostProcessor.hxx +BRepMesh_ModelPreProcessor.cxx +BRepMesh_ModelPreProcessor.hxx +BRepMesh_NURBSRangeSplitter.cxx +BRepMesh_NURBSRangeSplitter.hxx +BRepMesh_NodeInsertionMeshAlgo.hxx BRepMesh_OrientedEdge.hxx BRepMesh_PairOfIndex.hxx -BRepMesh_PairOfPolygon.hxx BRepMesh_PluginEntryType.hxx BRepMesh_PluginMacro.hxx BRepMesh_SelectorOfDataStructureOfDelaun.cxx BRepMesh_SelectorOfDataStructureOfDelaun.hxx BRepMesh_ShapeTool.cxx BRepMesh_ShapeTool.hxx -BRepMesh_Status.hxx +BRepMesh_ShapeVisitor.cxx +BRepMesh_ShapeVisitor.hxx +BRepMesh_SphereRangeSplitter.cxx +BRepMesh_SphereRangeSplitter.hxx +BRepMesh_TorusRangeSplitter.cxx +BRepMesh_TorusRangeSplitter.hxx BRepMesh_Triangle.hxx +BRepMesh_UVParamRangeSplitter.hxx BRepMesh_Vertex.hxx BRepMesh_VertexInspector.hxx BRepMesh_VertexTool.cxx BRepMesh_VertexTool.hxx -BRepMesh_WireChecker.cxx -BRepMesh_WireChecker.hxx -BRepMesh_WireInterferenceChecker.cxx -BRepMesh_WireInterferenceChecker.hxx +BRepMesh_CustomBaseMeshAlgo.hxx +BRepMesh_CustomDelaunayBaseMeshAlgo.hxx diff --git a/src/BRepMeshData/BRepMeshData_Curve.cxx b/src/BRepMeshData/BRepMeshData_Curve.cxx new file mode 100644 index 0000000000..ac427f9946 --- /dev/null +++ b/src/BRepMeshData/BRepMeshData_Curve.cxx @@ -0,0 +1,126 @@ +// Created on: 2016-04-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 +#include +#include +#include + +//======================================================================= +// Function: Constructor +// Purpose : +//======================================================================= +BRepMeshData_Curve::BRepMeshData_Curve (const Handle (NCollection_IncAllocator)& theAllocator) +: myPoints (NCollection_StdAllocator(theAllocator)), + myParameters (NCollection_StdAllocator(theAllocator)) +{ +} + +//======================================================================= +// Function: Destructor +// Purpose : +//======================================================================= +BRepMeshData_Curve::~BRepMeshData_Curve () +{ +} + +//======================================================================= +// Function: InsertPoint +// Purpose : +//======================================================================= +void BRepMeshData_Curve::InsertPoint( + const Standard_Integer thePosition, + const gp_Pnt& thePoint, + const Standard_Real theParamOnPCurve) +{ + myPoints .insert(myPoints .begin() + thePosition, thePoint); + myParameters.insert(myParameters.begin() + thePosition, theParamOnPCurve); +} + +//======================================================================= +// Function: AddPoint +// Purpose : +//======================================================================= +void BRepMeshData_Curve::AddPoint ( + const gp_Pnt& thePoint, + const Standard_Real theParamOnPCurve) +{ + myPoints .push_back(thePoint); + myParameters.push_back(theParamOnPCurve); +} + +//======================================================================= +// Function: GetPoint +// Purpose : +//======================================================================= +gp_Pnt& BRepMeshData_Curve::GetPoint (const Standard_Integer theIndex) +{ + return myPoints[theIndex]; +} + +//======================================================================= +// Function: GetParameter +// Purpose : +//======================================================================= +Standard_Real& BRepMeshData_Curve::GetParameter (const Standard_Integer theIndex) +{ + return myParameters[theIndex]; +} + +//======================================================================= +// Function: ParameterNb +// Purpose : +//======================================================================= +Standard_Integer BRepMeshData_Curve::ParametersNb() const +{ + return static_cast(myParameters.size()); +} + +//======================================================================= +// Function: RemovePoint +// Purpose : +//======================================================================= +void BRepMeshData_Curve::RemovePoint (const Standard_Integer theIndex) +{ + myPoints.erase(myPoints.begin() + theIndex); + removeParameter (theIndex); +} + +//======================================================================= +// Function: removeParameter +// Purpose : +//======================================================================= +void BRepMeshData_Curve::removeParameter (const Standard_Integer theIndex) +{ + myParameters.erase(myParameters.begin() + theIndex); +} + +//======================================================================= +// Function: Clear +// Purpose : +//======================================================================= +void BRepMeshData_Curve::Clear(const Standard_Boolean isKeepEndPoints) +{ + if (!isKeepEndPoints) + { + myPoints .clear(); + myParameters.clear(); + } + else if (ParametersNb() > 2) + { + myPoints .erase(myPoints .begin() + 1, myPoints .begin() + (myPoints .size() - 1)); + myParameters.erase(myParameters.begin() + 1, myParameters.begin() + (myParameters.size() - 1)); + } +} diff --git a/src/BRepMeshData/BRepMeshData_Curve.hxx b/src/BRepMeshData/BRepMeshData_Curve.hxx new file mode 100644 index 0000000000..1566a4d916 --- /dev/null +++ b/src/BRepMeshData/BRepMeshData_Curve.hxx @@ -0,0 +1,76 @@ +// Created on: 2016-04-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _BRepMeshData_Curve_HeaderFile +#define _BRepMeshData_Curve_HeaderFile + +#include +#include +#include +#include + +//! Default implementation of curve data model entity. +class BRepMeshData_Curve : public IMeshData_Curve +{ +public: + + DEFINE_INC_ALLOC + + //! Constructor. + Standard_EXPORT BRepMeshData_Curve (const Handle (NCollection_IncAllocator)& theAllocator); + + //! Destructor. + Standard_EXPORT virtual ~BRepMeshData_Curve (); + + //! Inserts new discretization point at the given position. + Standard_EXPORT virtual void InsertPoint( + const Standard_Integer thePosition, + const gp_Pnt& thePoint, + const Standard_Real theParamOnPCurve) Standard_OVERRIDE; + + //! Adds new discretization point to pcurve. + Standard_EXPORT virtual void AddPoint ( + const gp_Pnt& thePoint, + const Standard_Real theParamOnCurve) Standard_OVERRIDE; + + //! Returns discretization point with the given index. + Standard_EXPORT virtual gp_Pnt& GetPoint (const Standard_Integer theIndex) Standard_OVERRIDE; + + //! Removes point with the given index. + Standard_EXPORT virtual void RemovePoint (const Standard_Integer theIndex) Standard_OVERRIDE; + + //! Returns parameter with the given index. + Standard_EXPORT virtual Standard_Real& GetParameter (const Standard_Integer theIndex) Standard_OVERRIDE; + + //! Returns number of parameters stored in curve. + Standard_EXPORT virtual Standard_Integer ParametersNb() const Standard_OVERRIDE; + + //! Clears parameters list. + Standard_EXPORT virtual void Clear(const Standard_Boolean isKeepEndPoints) Standard_OVERRIDE; + + DEFINE_STANDARD_RTTI_INLINE(BRepMeshData_Curve, IMeshData_Curve) + +protected: + + //! Removes parameter with the given index. + Standard_EXPORT virtual void removeParameter (const Standard_Integer theIndex) Standard_OVERRIDE; + +private: + + IMeshData::Model::SequenceOfPnt myPoints; + IMeshData::Model::SequenceOfReal myParameters; +}; + +#endif \ No newline at end of file diff --git a/src/BRepMeshData/BRepMeshData_Edge.cxx b/src/BRepMeshData/BRepMeshData_Edge.cxx new file mode 100644 index 0000000000..67ce8228ff --- /dev/null +++ b/src/BRepMeshData/BRepMeshData_Edge.cxx @@ -0,0 +1,102 @@ +// Created on: 2016-04-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 +#include +#include +#include +#include + +//======================================================================= +// Function: Constructor +// Purpose : +//======================================================================= +BRepMeshData_Edge::BRepMeshData_Edge ( + const TopoDS_Edge& theEdge, + const Handle (NCollection_IncAllocator)& theAllocator) + : IMeshData_Edge (theEdge), + myAllocator (theAllocator), + myPCurves (256, myAllocator), + myPCurvesMap(1, myAllocator) +{ + SetCurve (IMeshData::ICurveHandle (new (myAllocator) BRepMeshData_Curve (myAllocator))); +} + +//======================================================================= +// Function: Destructor +// Purpose : +//======================================================================= +BRepMeshData_Edge::~BRepMeshData_Edge () +{ +} + +//======================================================================= +// Function: AddPCurve +// Purpose : +//======================================================================= +Standard_Integer BRepMeshData_Edge::PCurvesNb () const +{ + return myPCurves.Size (); +} + +//======================================================================= +// Function: AddPCurve +// Purpose : +//======================================================================= +const IMeshData::IPCurveHandle& BRepMeshData_Edge::AddPCurve ( + const IMeshData::IFacePtr& theDFace, + const TopAbs_Orientation theOrientation) +{ + const Standard_Integer aPCurveIndex = PCurvesNb (); + // Add pcurve to list of pcurves + IMeshData::IPCurveHandle aPCurve (new (myAllocator) BRepMeshData_PCurve (theDFace, theOrientation, myAllocator)); + myPCurves.Append (aPCurve); + + // Map pcurve to faces. + if (!myPCurvesMap.IsBound(theDFace)) + { + myPCurvesMap.Bind(theDFace, IMeshData::ListOfInteger(myAllocator)); + } + + IMeshData::ListOfInteger& aListOfPCurves = myPCurvesMap.ChangeFind(theDFace); + aListOfPCurves.Append (aPCurveIndex); + + return GetPCurve (aPCurveIndex); +} + +//======================================================================= +// Function: GetPCurve +// Purpose : +//======================================================================= +const IMeshData::IPCurveHandle& BRepMeshData_Edge::GetPCurve ( + const IMeshData::IFacePtr& theDFace, + const TopAbs_Orientation theOrientation) const +{ + const IMeshData::ListOfInteger& aListOfPCurves = myPCurvesMap.Find (theDFace); + const IMeshData::IPCurveHandle& aPCurve1 = myPCurves (aListOfPCurves.First ()); + return (aPCurve1->GetOrientation () == theOrientation) ? + aPCurve1 : + myPCurves (aListOfPCurves.Last ()); +} + +//======================================================================= +// Function: GetPCurve +// Purpose : +//======================================================================= +const IMeshData::IPCurveHandle& BRepMeshData_Edge::GetPCurve ( + const Standard_Integer theIndex) const +{ + return myPCurves (theIndex); +} diff --git a/src/BRepMeshData/BRepMeshData_Edge.hxx b/src/BRepMeshData/BRepMeshData_Edge.hxx new file mode 100644 index 0000000000..d30e550da7 --- /dev/null +++ b/src/BRepMeshData/BRepMeshData_Edge.hxx @@ -0,0 +1,65 @@ +// Created on: 2016-04-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _BRepMeshData_Edge_HeaderFile +#define _BRepMeshData_Edge_HeaderFile + +#include +#include +#include +#include + +//! Default implementation of edge data model entity. +class BRepMeshData_Edge : public IMeshData_Edge +{ +public: + + DEFINE_INC_ALLOC + + //! Constructor. + Standard_EXPORT BRepMeshData_Edge ( + const TopoDS_Edge& theEdge, + const Handle (NCollection_IncAllocator)& theAllocator); + + //! Destructor. + Standard_EXPORT virtual ~BRepMeshData_Edge (); + + //! Returns number of pcurves assigned to current edge. + Standard_EXPORT virtual Standard_Integer PCurvesNb () const Standard_OVERRIDE; + + //! Adds disrete pcurve for the specifed discrete face. + Standard_EXPORT virtual const IMeshData::IPCurveHandle& AddPCurve ( + const IMeshData::IFacePtr& theDFace, + const TopAbs_Orientation theOrientation) Standard_OVERRIDE; + + //! Returns pcurve for the specified discrete face. + Standard_EXPORT virtual const IMeshData::IPCurveHandle& GetPCurve ( + const IMeshData::IFacePtr& theDFace, + const TopAbs_Orientation theOrientation) const Standard_OVERRIDE; + + //! Returns pcurve with the given index. + Standard_EXPORT virtual const IMeshData::IPCurveHandle& GetPCurve ( + const Standard_Integer theIndex) const Standard_OVERRIDE; + + DEFINE_STANDARD_RTTI_INLINE(BRepMeshData_Edge, IMeshData_Edge) + +private: + + Handle (NCollection_IncAllocator) myAllocator; + IMeshData::VectorOfIPCurveHandles myPCurves; + IMeshData::DMapOfIFacePtrsListOfInteger myPCurvesMap; +}; + +#endif \ No newline at end of file diff --git a/src/BRepMeshData/BRepMeshData_Face.cxx b/src/BRepMeshData/BRepMeshData_Face.cxx new file mode 100644 index 0000000000..2dca22c8a4 --- /dev/null +++ b/src/BRepMeshData/BRepMeshData_Face.cxx @@ -0,0 +1,72 @@ +// Created on: 2016-04-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 +#include +#include +#include + +//======================================================================= +// Function: Constructor +// Purpose : +//======================================================================= +BRepMeshData_Face::BRepMeshData_Face ( + const TopoDS_Face& theFace, + const Handle (NCollection_IncAllocator)& theAllocator) + : IMeshData_Face (theFace), + myAllocator (theAllocator), + myDWires (256, myAllocator) +{ +} + +//======================================================================= +// Function: Destructor +// Purpose : +//======================================================================= +BRepMeshData_Face::~BRepMeshData_Face () +{ +} + +//======================================================================= +// Function: WiresNb +// Purpose : +//======================================================================= +Standard_Integer BRepMeshData_Face::WiresNb () const +{ + return myDWires.Size (); +} + +//======================================================================= +// Function: AddWire +// Purpose : +//======================================================================= +const IMeshData::IWireHandle& BRepMeshData_Face::AddWire ( + const TopoDS_Wire& theWire, + const Standard_Integer theEdgeNb) +{ + IMeshData::IWireHandle aWire (new (myAllocator) BRepMeshData_Wire (theWire, theEdgeNb, myAllocator)); + myDWires.Append (aWire); + return GetWire (WiresNb () - 1); +} + +//======================================================================= +// Function: GetWire +// Purpose : +//======================================================================= +const IMeshData::IWireHandle& BRepMeshData_Face::GetWire ( + const Standard_Integer theIndex) const +{ + return myDWires (theIndex); +} diff --git a/src/BRepMeshData/BRepMeshData_Face.hxx b/src/BRepMeshData/BRepMeshData_Face.hxx new file mode 100644 index 0000000000..1f187f7cea --- /dev/null +++ b/src/BRepMeshData/BRepMeshData_Face.hxx @@ -0,0 +1,58 @@ +// Created on: 2016-04-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _BRepMeshData_Face_HeaderFile +#define _BRepMeshData_Face_HeaderFile + +#include +#include +#include + +//! Default implementation of face data model entity. +class BRepMeshData_Face : public IMeshData_Face +{ +public: + + DEFINE_INC_ALLOC + + //! Constructor. + Standard_EXPORT BRepMeshData_Face ( + const TopoDS_Face& theFace, + const Handle (NCollection_IncAllocator)& theAllocator); + + //! Destructor. + Standard_EXPORT virtual ~BRepMeshData_Face (); + + //! Gets number of children. + Standard_EXPORT virtual Standard_Integer WiresNb () const Standard_OVERRIDE; + + //! Gets wire with the given index. + Standard_EXPORT virtual const IMeshData::IWireHandle& GetWire ( + const Standard_Integer theIndex) const Standard_OVERRIDE; + + //! Adds wire to discrete model of face. + Standard_EXPORT virtual const IMeshData::IWireHandle& AddWire ( + const TopoDS_Wire& theWire, + const Standard_Integer theEdgeNb = 0) Standard_OVERRIDE; + + DEFINE_STANDARD_RTTI_INLINE(BRepMeshData_Face, IMeshData_Face) + +private: + + Handle (NCollection_IncAllocator) myAllocator; + IMeshData::VectorOfIWireHandles myDWires; +}; + +#endif \ No newline at end of file diff --git a/src/BRepMeshData/BRepMeshData_Model.cxx b/src/BRepMeshData/BRepMeshData_Model.cxx new file mode 100644 index 0000000000..08c07f8c96 --- /dev/null +++ b/src/BRepMeshData/BRepMeshData_Model.cxx @@ -0,0 +1,102 @@ +// Created on: 2016-04-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 + +#include +#include +#include +#include +#include + +//======================================================================= +// Function: Constructor +// Purpose : +//======================================================================= +BRepMeshData_Model::BRepMeshData_Model (const TopoDS_Shape& theShape) + : IMeshData_Model (theShape), + myMaxSize (0.), + myAllocator (new NCollection_IncAllocator (IMeshData::MEMORY_BLOCK_SIZE_HUGE)), + myDFaces (256, myAllocator), + myDEdges (256, myAllocator) +{ + myAllocator->SetThreadSafe(); +} + +//======================================================================= +// Function: Destructor +// Purpose : +//======================================================================= +BRepMeshData_Model::~BRepMeshData_Model () +{ +} + +//======================================================================= +// Function: FacesNb +// Purpose : +//======================================================================= +Standard_Integer BRepMeshData_Model::FacesNb () const +{ + return myDFaces.Size (); +} + +//======================================================================= +// Function: AddFace +// Purpose : +//======================================================================= +const IMeshData::IFaceHandle& BRepMeshData_Model::AddFace (const TopoDS_Face& theFace) +{ + IMeshData::IFaceHandle aFace (new (myAllocator) BRepMeshData_Face (theFace, myAllocator)); + myDFaces.Append (aFace); + return myDFaces (FacesNb () - 1); +} + +//======================================================================= +// Function: GetFace +// Purpose : +//======================================================================= +const IMeshData::IFaceHandle& BRepMeshData_Model::GetFace (const Standard_Integer theIndex) const +{ + return myDFaces (theIndex); +} + +//======================================================================= +// Function: EdgesNb +// Purpose : +//======================================================================= +Standard_Integer BRepMeshData_Model::EdgesNb () const +{ + return myDEdges.Size (); +} + +//======================================================================= +// Function: AddEdge +// Purpose : +//======================================================================= +const IMeshData::IEdgeHandle& BRepMeshData_Model::AddEdge (const TopoDS_Edge& theEdge) +{ + IMeshData::IEdgeHandle aEdge (new (myAllocator) BRepMeshData_Edge (theEdge, myAllocator)); + myDEdges.Append (aEdge); + return myDEdges (EdgesNb () - 1); +} + +//======================================================================= +// Function: GetEdge +// Purpose : +//======================================================================= +const IMeshData::IEdgeHandle& BRepMeshData_Model::GetEdge (const Standard_Integer theIndex) const +{ + return myDEdges (theIndex); +} diff --git a/src/BRepMeshData/BRepMeshData_Model.hxx b/src/BRepMeshData/BRepMeshData_Model.hxx new file mode 100644 index 0000000000..2b19684a73 --- /dev/null +++ b/src/BRepMeshData/BRepMeshData_Model.hxx @@ -0,0 +1,81 @@ +// Created on: 2016-04-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _BRepMeshData_Model_HeaderFile +#define _BRepMeshData_Model_HeaderFile + +#include +#include +#include +#include +#include + +//! Default implementation of model entity. +class BRepMeshData_Model : public IMeshData_Model +{ +public: + + //! Constructor. + //! Initializes empty model. + Standard_EXPORT BRepMeshData_Model (const TopoDS_Shape& theShape); + + //! Destructor. + Standard_EXPORT virtual ~BRepMeshData_Model (); + + //! Returns maximum size of shape's bounding box. + Standard_EXPORT virtual Standard_Real GetMaxSize () const Standard_OVERRIDE + { + return myMaxSize; + } + + //! Sets maximum size of shape's bounding box. + inline void SetMaxSize (const Standard_Real theValue) + { + myMaxSize = theValue; + } + + DEFINE_STANDARD_RTTI_INLINE(BRepMeshData_Model, IMeshData_Model) + +public: //! @name discrete faces + + //! Returns number of faces in discrete model. + Standard_EXPORT virtual Standard_Integer FacesNb () const Standard_OVERRIDE; + + //! Adds new face to shape model. + Standard_EXPORT virtual const IMeshData::IFaceHandle& AddFace (const TopoDS_Face& theFace) Standard_OVERRIDE; + + //! Gets model's face with the given index. + Standard_EXPORT virtual const IMeshData::IFaceHandle& GetFace (const Standard_Integer theIndex) const Standard_OVERRIDE; + +public: //! @name discrete edges + + //! Returns number of edges in discrete model. + Standard_EXPORT virtual Standard_Integer EdgesNb () const Standard_OVERRIDE; + + //! Adds new edge to shape model. + Standard_EXPORT virtual const IMeshData::IEdgeHandle& AddEdge (const TopoDS_Edge& theEdge) Standard_OVERRIDE; + + //! Gets model's edge with the given index. + Standard_EXPORT virtual const IMeshData::IEdgeHandle& GetEdge (const Standard_Integer theIndex) const Standard_OVERRIDE; + +private: + + Standard_Real myMaxSize; + Handle (NCollection_IncAllocator) myAllocator; + IMeshData::VectorOfIFaceHandles myDFaces; + IMeshData::VectorOfIEdgeHandles myDEdges; +}; + +#endif \ No newline at end of file diff --git a/src/BRepMeshData/BRepMeshData_PCurve.cxx b/src/BRepMeshData/BRepMeshData_PCurve.cxx new file mode 100644 index 0000000000..4c03911829 --- /dev/null +++ b/src/BRepMeshData/BRepMeshData_PCurve.cxx @@ -0,0 +1,155 @@ +// Created on: 2016-04-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 +#include +#include +#include +#include + +//======================================================================= +// Function: Constructor +// Purpose : +//======================================================================= +BRepMeshData_PCurve::BRepMeshData_PCurve ( + const IMeshData::IFacePtr& theDFace, + const TopAbs_Orientation theOrientation, + const Handle (NCollection_IncAllocator)& theAllocator) + : IMeshData_PCurve (theDFace, theOrientation), + myPoints2d (NCollection_StdAllocator(theAllocator)), + myParameters (NCollection_StdAllocator(theAllocator)), + myIndices (NCollection_StdAllocator(theAllocator)) +{ +} + +//======================================================================= +// Function: Destructor +// Purpose : +//======================================================================= +BRepMeshData_PCurve::~BRepMeshData_PCurve () +{ +} + +//======================================================================= +// Function: InsertPoint +// Purpose : +//======================================================================= +void BRepMeshData_PCurve::InsertPoint( + const Standard_Integer thePosition, + const gp_Pnt2d& thePoint, + const Standard_Real theParamOnPCurve) +{ + myPoints2d .insert(myPoints2d .begin() + thePosition, thePoint); + myParameters.insert(myParameters.begin() + thePosition, theParamOnPCurve); + myIndices .insert(myIndices .begin() + thePosition, 0); +} + +//======================================================================= +// Function: AddPoint +// Purpose : +//======================================================================= +void BRepMeshData_PCurve::AddPoint ( + const gp_Pnt2d& thePoint, + const Standard_Real theParamOnPCurve) +{ + myPoints2d .push_back(thePoint); + myParameters.push_back(theParamOnPCurve); + myIndices .push_back(0); +} + +//======================================================================= +// Function: GetPoint +// Purpose : +//======================================================================= +gp_Pnt2d& BRepMeshData_PCurve::GetPoint (const Standard_Integer theIndex) +{ + Standard_OutOfRange_Raise_if ( + theIndex < 0 || theIndex >= static_cast(myPoints2d.size()), + "BRepMeshData_PCurve::GetPoint"); + return myPoints2d[theIndex]; +} + +//======================================================================= +// Function: GetIndex +// Purpose : +//======================================================================= +Standard_Integer& BRepMeshData_PCurve::GetIndex(const Standard_Integer theIndex) +{ + Standard_OutOfRange_Raise_if ( + theIndex < 0 || theIndex >= static_cast(myIndices.size()), + "BRepMeshData_PCurve::GetIndex"); + return myIndices[theIndex]; +} + +//======================================================================= +// Function: GetParameter +// Purpose : +//======================================================================= +Standard_Real& BRepMeshData_PCurve::GetParameter (const Standard_Integer theIndex) +{ + Standard_OutOfRange_Raise_if ( + theIndex < 0 || theIndex >= ParametersNb(), + "BRepMeshData_PCurve::GetParameter"); + return myParameters[theIndex]; +} + +//======================================================================= +// Function: ParameterNb +// Purpose : +//======================================================================= +Standard_Integer BRepMeshData_PCurve::ParametersNb() const +{ + return static_cast(myParameters.size()); +} + +//======================================================================= +// Function: RemovePoint +// Purpose : +//======================================================================= +void BRepMeshData_PCurve::RemovePoint (const Standard_Integer theIndex) +{ + myPoints2d.erase(myPoints2d.begin() + theIndex); + myIndices .erase(myIndices .begin() + theIndex); + removeParameter (theIndex); +} + +//======================================================================= +// Function: removeParameter +// Purpose : +//======================================================================= +void BRepMeshData_PCurve::removeParameter (const Standard_Integer theIndex) +{ + myParameters.erase(myParameters.begin() + theIndex); +} + +//======================================================================= +// Function: Clear +// Purpose : +//======================================================================= +void BRepMeshData_PCurve::Clear(const Standard_Boolean isKeepEndPoints) +{ + if (!isKeepEndPoints) + { + myPoints2d .clear(); + myParameters.clear(); + myIndices .clear(); + } + else if (ParametersNb() > 2) + { + myPoints2d .erase(myPoints2d .begin() + 1, myPoints2d .begin() + (myPoints2d .size() - 1)); + myParameters.erase(myParameters.begin() + 1, myParameters.begin() + (myParameters.size() - 1)); + myIndices .erase(myIndices .begin() + 1, myIndices .begin() + (myIndices .size() - 1)); + } +} diff --git a/src/BRepMeshData/BRepMeshData_PCurve.hxx b/src/BRepMeshData/BRepMeshData_PCurve.hxx new file mode 100644 index 0000000000..1189f92636 --- /dev/null +++ b/src/BRepMeshData/BRepMeshData_PCurve.hxx @@ -0,0 +1,82 @@ +// Created on: 2016-04-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _BRepMeshData_PCurve_HeaderFile +#define _BRepMeshData_PCurve_HeaderFile + +#include +#include +#include + +//! Default implementation of pcurve data model entity. +class BRepMeshData_PCurve : public IMeshData_PCurve +{ +public: + + DEFINE_INC_ALLOC + + //! Constructor. + Standard_EXPORT BRepMeshData_PCurve ( + const IMeshData::IFacePtr& theDFace, + const TopAbs_Orientation theOrientation, + const Handle (NCollection_IncAllocator)& theAllocator); + + //! Destructor. + Standard_EXPORT virtual ~BRepMeshData_PCurve (); + + //! Inserts new discretization point at the given position. + Standard_EXPORT virtual void InsertPoint( + const Standard_Integer thePosition, + const gp_Pnt2d& thePoint, + const Standard_Real theParamOnPCurve) Standard_OVERRIDE; + + //! Adds new discretization point to pcurve. + Standard_EXPORT virtual void AddPoint ( + const gp_Pnt2d& thePoint, + const Standard_Real theParamOnPCurve) Standard_OVERRIDE; + + //! Returns discretization point with the given index. + Standard_EXPORT virtual gp_Pnt2d& GetPoint (const Standard_Integer theIndex) Standard_OVERRIDE; + + //! Returns index in mesh corresponded to discretization point with the given index. + Standard_EXPORT virtual Standard_Integer& GetIndex(const Standard_Integer theIndex) Standard_OVERRIDE; + + //! Removes point with the given index. + Standard_EXPORT virtual void RemovePoint (const Standard_Integer theIndex) Standard_OVERRIDE; + + //! Returns parameter with the given index. + Standard_EXPORT virtual Standard_Real& GetParameter (const Standard_Integer theIndex) Standard_OVERRIDE; + + //! Returns number of parameters stored in pcurve. + Standard_EXPORT virtual Standard_Integer ParametersNb() const Standard_OVERRIDE; + + //! Clears parameters list. + Standard_EXPORT virtual void Clear(const Standard_Boolean isKeepEndPoints) Standard_OVERRIDE; + + DEFINE_STANDARD_RTTI_INLINE(BRepMeshData_PCurve, IMeshData_PCurve) + +protected: + + //! Removes parameter with the given index. + Standard_EXPORT virtual void removeParameter (const Standard_Integer theIndex) Standard_OVERRIDE; + +private: + + IMeshData::Model::SequenceOfPnt2d myPoints2d; + IMeshData::Model::SequenceOfReal myParameters; + IMeshData::Model::SequenceOfInteger myIndices; +}; + +#endif \ No newline at end of file diff --git a/src/BRepMeshData/BRepMeshData_Wire.cxx b/src/BRepMeshData/BRepMeshData_Wire.cxx new file mode 100644 index 0000000000..8139f6a84a --- /dev/null +++ b/src/BRepMeshData/BRepMeshData_Wire.cxx @@ -0,0 +1,86 @@ +// Created on: 2016-04-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 +#include +#include +#include + +//======================================================================= +// Function: Constructor +// Purpose : +//======================================================================= +BRepMeshData_Wire::BRepMeshData_Wire ( + const TopoDS_Wire& theWire, + const Standard_Integer theEdgeNb, + const Handle (NCollection_IncAllocator)& theAllocator) + : IMeshData_Wire (theWire), + myDEdges (theEdgeNb > 0 ? theEdgeNb : 256, theAllocator), + myDEdgesOri (theEdgeNb > 0 ? theEdgeNb : 256, theAllocator) +{ +} + +//======================================================================= +// Function: Destructor +// Purpose : +//======================================================================= +BRepMeshData_Wire::~BRepMeshData_Wire () +{ +} + +//======================================================================= +// Function: EdgesNb +// Purpose : +//======================================================================= +Standard_Integer BRepMeshData_Wire::EdgesNb () const +{ + return myDEdges.Size (); +} + +//======================================================================= +// Function: Destructor +// Purpose : +//======================================================================= +Standard_Integer BRepMeshData_Wire::AddEdge ( + const IMeshData::IEdgePtr& theDEdge, + const TopAbs_Orientation theOrientation) +{ + const Standard_Integer aIndex = EdgesNb (); + + myDEdges .Append (theDEdge); + myDEdgesOri.Append (theOrientation); + + return aIndex; +} + +//======================================================================= +// Function: GetEdge +// Purpose : +//======================================================================= +const IMeshData::IEdgePtr& BRepMeshData_Wire::GetEdge ( + const Standard_Integer theIndex) const +{ + return myDEdges (theIndex); +} + +//======================================================================= +// Function: GetEdgeOrientation +// Purpose : +//======================================================================= +TopAbs_Orientation BRepMeshData_Wire::GetEdgeOrientation ( + const Standard_Integer theIndex) const +{ + return myDEdgesOri (theIndex); +} diff --git a/src/BRepMeshData/BRepMeshData_Wire.hxx b/src/BRepMeshData/BRepMeshData_Wire.hxx new file mode 100644 index 0000000000..bf55509684 --- /dev/null +++ b/src/BRepMeshData/BRepMeshData_Wire.hxx @@ -0,0 +1,63 @@ +// Created on: 2016-04-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _BRepMeshData_Wire_HeaderFile +#define _BRepMeshData_Wire_HeaderFile + +#include +#include + +//! Default implementation of wire data model entity. +class BRepMeshData_Wire : public IMeshData_Wire +{ +public: + + DEFINE_INC_ALLOC + + //! Constructor. + Standard_EXPORT BRepMeshData_Wire ( + const TopoDS_Wire& theWire, + const Standard_Integer theEdgeNb, + const Handle (NCollection_IncAllocator)& theAllocator); + + //! Destructor. + Standard_EXPORT virtual ~BRepMeshData_Wire (); + + //! Gets number of children. + Standard_EXPORT virtual Standard_Integer EdgesNb () const Standard_OVERRIDE; + + //! Adds new discrete edge with specified orientation to wire chain. + //! @return index of added edge in wire chain. + Standard_EXPORT virtual Standard_Integer AddEdge ( + const IMeshData::IEdgePtr& theDEdge, + const TopAbs_Orientation theOrientation) Standard_OVERRIDE; + + //! Gets edge with the given index. + Standard_EXPORT virtual const IMeshData::IEdgePtr& GetEdge ( + const Standard_Integer theIndex) const Standard_OVERRIDE; + + //! Returns True if orientation of discrete edge with the given index is forward. + Standard_EXPORT virtual TopAbs_Orientation GetEdgeOrientation ( + const Standard_Integer theIndex) const Standard_OVERRIDE; + + DEFINE_STANDARD_RTTI_INLINE(BRepMeshData_Wire, IMeshData_Wire) + +private: + + IMeshData::VectorOfIEdgePtrs myDEdges; + IMeshData::VectorOfOrientation myDEdgesOri; +}; + +#endif \ No newline at end of file diff --git a/src/BRepMeshData/FILES b/src/BRepMeshData/FILES new file mode 100644 index 0000000000..eb27095179 --- /dev/null +++ b/src/BRepMeshData/FILES @@ -0,0 +1,12 @@ +BRepMeshData_Curve.cxx +BRepMeshData_Curve.hxx +BRepMeshData_Edge.cxx +BRepMeshData_Edge.hxx +BRepMeshData_Face.cxx +BRepMeshData_Face.hxx +BRepMeshData_Model.cxx +BRepMeshData_Model.hxx +BRepMeshData_PCurve.cxx +BRepMeshData_PCurve.hxx +BRepMeshData_Wire.cxx +BRepMeshData_Wire.hxx diff --git a/src/DBRep/DBRep_DrawableShape.cxx b/src/DBRep/DBRep_DrawableShape.cxx index 22df8ddb50..f300abe294 100644 --- a/src/DBRep/DBRep_DrawableShape.cxx +++ b/src/DBRep/DBRep_DrawableShape.cxx @@ -840,7 +840,7 @@ void DBRep_DrawableShape::DisplayHiddenLines(Draw_Display& dis) if (!strcmp(dout.GetType(id),"PERS")) focal = dout.Focal(id); Standard_Real Ang,Def; HLRBRep::PolyHLRAngleAndDeflection(myAng,Ang,Def); - BRepMesh_FastDiscret::Parameters aMeshParams; + IMeshTools_Parameters aMeshParams; aMeshParams.Relative = Standard_True; aMeshParams.Deflection = Def; aMeshParams.Angle = Ang; diff --git a/src/IMeshData/FILES b/src/IMeshData/FILES new file mode 100644 index 0000000000..1af663a2f1 --- /dev/null +++ b/src/IMeshData/FILES @@ -0,0 +1,13 @@ +IMeshData_Curve.hxx +IMeshData_Edge.hxx +IMeshData_Face.hxx +IMeshData_Model.hxx +IMeshData_ParametersList.hxx +IMeshData_ParametersListArrayAdaptor.hxx +IMeshData_PCurve.hxx +IMeshData_Shape.hxx +IMeshData_Status.hxx +IMeshData_StatusOwner.hxx +IMeshData_TessellatedShape.hxx +IMeshData_Types.hxx +IMeshData_Wire.hxx diff --git a/src/IMeshData/IMeshData_Curve.hxx b/src/IMeshData/IMeshData_Curve.hxx new file mode 100644 index 0000000000..505efad262 --- /dev/null +++ b/src/IMeshData/IMeshData_Curve.hxx @@ -0,0 +1,62 @@ +// Created on: 2016-04-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _IMeshData_Curve_HeaderFile +#define _IMeshData_Curve_HeaderFile + +#include +#include + +class gp_Pnt; + +//! Interface class representing discrete 3d curve of edge. +//! Indexation of points starts from zero. +class IMeshData_Curve : public IMeshData_ParametersList +{ +public: + + //! Destructor. + Standard_EXPORT virtual ~IMeshData_Curve() + { + } + + //! Inserts new discretization point at the given position. + Standard_EXPORT virtual void InsertPoint( + const Standard_Integer thePosition, + const gp_Pnt& thePoint, + const Standard_Real theParamOnPCurve) = 0; + + //! Adds new discretization point to curve. + Standard_EXPORT virtual void AddPoint ( + const gp_Pnt& thePoint, + const Standard_Real theParamOnCurve) = 0; + + //! Returns discretization point with the given index. + Standard_EXPORT virtual gp_Pnt& GetPoint (const Standard_Integer theIndex) = 0; + + //! Removes point with the given index. + Standard_EXPORT virtual void RemovePoint (const Standard_Integer theIndex) = 0; + + DEFINE_STANDARD_RTTI_INLINE(IMeshData_Curve, IMeshData_ParametersList) + +protected: + + //! Constructor. + Standard_EXPORT IMeshData_Curve() + { + } +}; + +#endif \ No newline at end of file diff --git a/src/IMeshData/IMeshData_Edge.hxx b/src/IMeshData/IMeshData_Edge.hxx new file mode 100644 index 0000000000..162d2a20fa --- /dev/null +++ b/src/IMeshData/IMeshData_Edge.hxx @@ -0,0 +1,167 @@ +// Created on: 2016-04-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _IMeshData_Edge_HeaderFile +#define _IMeshData_Edge_HeaderFile + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class IMeshData_Face; + +//! Interface class representing discrete model of an edge. +class IMeshData_Edge : public IMeshData_TessellatedShape, public IMeshData_StatusOwner +{ +public: + + //! Destructor. + Standard_EXPORT virtual ~IMeshData_Edge() + { + } + + //! Returns TopoDS_Edge attached to model. + inline const TopoDS_Edge& GetEdge () const + { + return TopoDS::Edge (GetShape ()); + } + + //! Returns number of pcurves assigned to current edge. + Standard_EXPORT virtual Standard_Integer PCurvesNb () const = 0; + + //! Adds discrete pcurve for the specifed discrete face. + Standard_EXPORT virtual const IMeshData::IPCurveHandle& AddPCurve ( + const IMeshData::IFacePtr& theDFace, + const TopAbs_Orientation theOrientation) = 0; + + //! Returns pcurve for the specified discrete face. + Standard_EXPORT virtual const IMeshData::IPCurveHandle& GetPCurve ( + const IMeshData::IFacePtr& theDFace, + const TopAbs_Orientation theOrientation) const = 0; + + //! Returns pcurve with the given index. + Standard_EXPORT virtual const IMeshData::IPCurveHandle& GetPCurve ( + const Standard_Integer theIndex) const = 0; + + //! Clears curve and all pcurves assigned to the edge from discretization. + inline void Clear(const Standard_Boolean isKeepEndPoints) + { + myCurve->Clear(isKeepEndPoints); + for (Standard_Integer aPCurveIt = 0; aPCurveIt < PCurvesNb(); ++aPCurveIt) + { + GetPCurve(aPCurveIt)->Clear(isKeepEndPoints); + } + } + + //! Returns true in case if the edge is free one, i.e. it does not have pcurves. + inline Standard_Boolean IsFree () const + { + return (PCurvesNb () == 0); + } + + //! Sets 3d curve associated with current edge. + inline void SetCurve (const IMeshData::ICurveHandle& theCurve) + { + myCurve = theCurve; + } + + //! Returns 3d curve associated with current edge. + inline const IMeshData::ICurveHandle& GetCurve () const + { + return myCurve; + } + + //! Gets value of angular deflection for the discrete model. + inline Standard_Real GetAngularDeflection () const + { + return myAngDeflection; + } + + //! Sets value of angular deflection for the discrete model. + inline void SetAngularDeflection (const Standard_Real theValue) + { + myAngDeflection = theValue; + } + + //! Returns same param flag. + //! By default equals to flag stored in topological shape. + inline Standard_Boolean GetSameParam () const + { + return mySameParam; + } + + //! Updates same param flag. + inline void SetSameParam (const Standard_Boolean theValue) + { + mySameParam = theValue; + } + + //! Returns same range flag. + //! By default equals to flag stored in topological shape. + inline Standard_Boolean GetSameRange () const + { + return mySameRange; + } + + //! Updates same range flag. + inline void SetSameRange (const Standard_Boolean theValue) + { + mySameRange = theValue; + } + + //! Returns degenerative flag. + //! By default equals to flag stored in topological shape. + inline Standard_Boolean GetDegenerated () const + { + return myDegenerated; + } + + //! Updates degenerative flag. + inline void SetDegenerated (const Standard_Boolean theValue) + { + myDegenerated = theValue; + } + + DEFINE_STANDARD_RTTI_INLINE(IMeshData_Edge, IMeshData_TessellatedShape) + +protected: + + //! Constructor. + //! Initializes empty model. + Standard_EXPORT IMeshData_Edge (const TopoDS_Edge& theEdge) + : IMeshData_TessellatedShape(theEdge), + mySameParam (BRep_Tool::SameParameter(theEdge)), + mySameRange (BRep_Tool::SameRange (theEdge)), + myDegenerated(BRep_Tool::Degenerated (theEdge)), + myAngDeflection(RealLast()) + { + } + +private: + + Standard_Boolean mySameParam; + Standard_Boolean mySameRange; + Standard_Boolean myDegenerated; + Standard_Real myAngDeflection; + IMeshData::ICurveHandle myCurve; +}; + +#endif \ No newline at end of file diff --git a/src/IMeshData/IMeshData_Face.hxx b/src/IMeshData/IMeshData_Face.hxx new file mode 100644 index 0000000000..4db215de1a --- /dev/null +++ b/src/IMeshData/IMeshData_Face.hxx @@ -0,0 +1,93 @@ +// Created on: 2016-04-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _IMeshData_Face_HeaderFile +#define _IMeshData_Face_HeaderFile + +#include +#include +#include +#include +#include +#include +#include +#include + +class IMeshData_Wire; +class TopoDS_Wire; + +//! Interface class representing discrete model of a face. +//! Face model contains one or several wires. +//! First wire is always outer one. +class IMeshData_Face : public IMeshData_TessellatedShape, public IMeshData_StatusOwner +{ +public: + + //! Destructor. + Standard_EXPORT virtual ~IMeshData_Face() + { + } + + //! Returns number of wires. + Standard_EXPORT virtual Standard_Integer WiresNb () const = 0; + + //! Adds wire to discrete model of face. + Standard_EXPORT virtual const IMeshData::IWireHandle& AddWire ( + const TopoDS_Wire& theWire, + const Standard_Integer theEdgeNb = 0) = 0; + + //! Returns discrete edge with the given index. + Standard_EXPORT virtual const IMeshData::IWireHandle& GetWire ( + const Standard_Integer theIndex) const = 0; + + //! Returns face's surface. + inline const Handle(BRepAdaptor_HSurface)& GetSurface() const + { + return mySurface; + } + + //! Returns TopoDS_Face attached to model. + inline const TopoDS_Face& GetFace () const + { + return TopoDS::Face (GetShape ()); + } + + //! Returns whether the face discrete model is valid. + inline Standard_Boolean IsValid () const + { + return (IsEqual(IMeshData_NoError) || + IsEqual(IMeshData_ReMesh) || + IsEqual(IMeshData_UnorientedWire)); + } + + DEFINE_STANDARD_RTTI_INLINE(IMeshData_Face, IMeshData_TessellatedShape) + +protected: + + //! Constructor. + //! Initializes empty model. + Standard_EXPORT IMeshData_Face (const TopoDS_Face& theFace) + : IMeshData_TessellatedShape(theFace) + { + BRepAdaptor_Surface aSurfAdaptor(GetFace(), Standard_False); + mySurface = new BRepAdaptor_HSurface(aSurfAdaptor); + } + +private: + + mutable Handle(BRepAdaptor_HSurface) mySurface; +}; + +#endif \ No newline at end of file diff --git a/src/IMeshData/IMeshData_Model.hxx b/src/IMeshData/IMeshData_Model.hxx new file mode 100644 index 0000000000..773ab6e973 --- /dev/null +++ b/src/IMeshData/IMeshData_Model.hxx @@ -0,0 +1,76 @@ +// Created on: 2016-04-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _IMeshData_Model_HeaderFile +#define _IMeshData_Model_HeaderFile + +#include +#include +#include +#include + +class TopoDS_Face; +class TopoDS_Edge; +class IMeshData_Face; +class IMeshData_Edge; + +//! Interface class representing discrete model of a shape. +class IMeshData_Model : public IMeshData_Shape +{ +public: + + //! Destructor. + Standard_EXPORT virtual ~IMeshData_Model() + { + } + + //! Returns maximum size of shape model. + Standard_EXPORT virtual Standard_Real GetMaxSize () const = 0; + + DEFINE_STANDARD_RTTI_INLINE(IMeshData_Model, IMeshData_Shape) + +public: //! @name discrete faces + + //! Returns number of faces in discrete model. + Standard_EXPORT virtual Standard_Integer FacesNb () const = 0; + + //! Adds new face to shape model. + Standard_EXPORT virtual const IMeshData::IFaceHandle& AddFace (const TopoDS_Face& theFace) = 0; + + //! Gets model's face with the given index. + Standard_EXPORT virtual const IMeshData::IFaceHandle& GetFace (const Standard_Integer theIndex) const = 0; + +public: //! @name discrete edges + + //! Returns number of edges in discrete model. + Standard_EXPORT virtual Standard_Integer EdgesNb () const = 0; + + //! Adds new edge to shape model. + Standard_EXPORT virtual const IMeshData::IEdgeHandle& AddEdge (const TopoDS_Edge& theEdge) = 0; + + //! Gets model's edge with the given index. + Standard_EXPORT virtual const IMeshData::IEdgeHandle& GetEdge (const Standard_Integer theIndex) const = 0; + +protected: + + //! Constructor. + //! Initializes empty model. + Standard_EXPORT IMeshData_Model (const TopoDS_Shape& theShape) + : IMeshData_Shape(theShape) + { + } +}; + +#endif \ No newline at end of file diff --git a/src/IMeshData/IMeshData_PCurve.hxx b/src/IMeshData/IMeshData_PCurve.hxx new file mode 100644 index 0000000000..4c6530cf0e --- /dev/null +++ b/src/IMeshData/IMeshData_PCurve.hxx @@ -0,0 +1,99 @@ +// Created on: 2016-04-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _IMeshData_PCurve_HeaderFile +#define _IMeshData_PCurve_HeaderFile + +#include +#include +#include + +class gp_Pnt2d; + +//! Interface class representing pcurve of edge associated with discrete face. +//! Indexation of points starts from zero. +class IMeshData_PCurve : public IMeshData_ParametersList +{ +public: + + //! Destructor. + Standard_EXPORT virtual ~IMeshData_PCurve() + { + } + + //! Inserts new discretization point at the given position. + Standard_EXPORT virtual void InsertPoint( + const Standard_Integer thePosition, + const gp_Pnt2d& thePoint, + const Standard_Real theParamOnPCurve) = 0; + + //! Adds new discretization point to pcurve. + Standard_EXPORT virtual void AddPoint ( + const gp_Pnt2d& thePoint, + const Standard_Real theParamOnPCurve) = 0; + + //! Returns discretization point with the given index. + Standard_EXPORT virtual gp_Pnt2d& GetPoint (const Standard_Integer theIndex) = 0; + + //! Returns index in mesh corresponded to discretization point with the given index. + Standard_EXPORT virtual Standard_Integer& GetIndex(const Standard_Integer theIndex) = 0; + + //! Removes point with the given index. + Standard_EXPORT virtual void RemovePoint (const Standard_Integer theIndex) = 0; + + //! Returns forward flag of this pcurve. + inline Standard_Boolean IsForward () const + { + return (myOrientation != TopAbs_REVERSED); + } + + //! Returns internal flag of this pcurve. + inline Standard_Boolean IsInternal() const + { + return (myOrientation == TopAbs_INTERNAL); + } + + //! Returns orientation of the edge associated with current pcurve. + inline TopAbs_Orientation GetOrientation() const + { + return myOrientation; + } + + //! Returns discrete face pcurve is associated to. + inline const IMeshData::IFacePtr& GetFace () const + { + return myDFace; + } + + DEFINE_STANDARD_RTTI_INLINE(IMeshData_PCurve, IMeshData_ParametersList) + +protected: + + //! Constructor. + Standard_EXPORT IMeshData_PCurve ( + const IMeshData::IFacePtr& theDFace, + const TopAbs_Orientation theOrientation) + : myDFace(theDFace), + myOrientation(theOrientation) + { + } + +private: + + IMeshData::IFacePtr myDFace; + TopAbs_Orientation myOrientation; +}; + +#endif \ No newline at end of file diff --git a/src/IMeshData/IMeshData_ParametersList.hxx b/src/IMeshData/IMeshData_ParametersList.hxx new file mode 100644 index 0000000000..8190fd2f32 --- /dev/null +++ b/src/IMeshData/IMeshData_ParametersList.hxx @@ -0,0 +1,54 @@ +// Created on: 2016-04-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _IMeshData_ParametersList_HeaderFile +#define _IMeshData_ParametersList_HeaderFile + +#include +#include + +//! Interface class representing list of parameters on curve. +class IMeshData_ParametersList : public Standard_Transient +{ +public: + + //! Destructor. + Standard_EXPORT virtual ~IMeshData_ParametersList() + { + } + + //! Returns parameter with the given index. + Standard_EXPORT virtual Standard_Real& GetParameter (const Standard_Integer theIndex) = 0; + + //! Returns number of parameters. + Standard_EXPORT virtual Standard_Integer ParametersNb() const = 0; + + //! Clears parameters list. + Standard_EXPORT virtual void Clear(const Standard_Boolean isKeepEndPoints) = 0; + + DEFINE_STANDARD_RTTI_INLINE(IMeshData_ParametersList, Standard_Transient) + +protected: + + //! Constructor. + Standard_EXPORT IMeshData_ParametersList() + { + } + + //! Removes parameter with the given index. + Standard_EXPORT virtual void removeParameter (const Standard_Integer theIndex) = 0; +}; + +#endif \ No newline at end of file diff --git a/src/IMeshData/IMeshData_ParametersListArrayAdaptor.hxx b/src/IMeshData/IMeshData_ParametersListArrayAdaptor.hxx new file mode 100644 index 0000000000..4356961163 --- /dev/null +++ b/src/IMeshData/IMeshData_ParametersListArrayAdaptor.hxx @@ -0,0 +1,70 @@ +// Created on: 2016-04-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _IMeshData_ParametersListArrayAdaptor_HeaderFile +#define _IMeshData_ParametersListArrayAdaptor_HeaderFile + +#include +#include +#include + +//! Auxiliary tool representing adaptor interface for child classes of +//! IMeshData_ParametersList to be used in tools working on NCollection_Array structure. +template +class IMeshData_ParametersListArrayAdaptor : public Standard_Transient +{ +public: + + //! Constructor. Initializes tool by the given parameters. + Standard_EXPORT IMeshData_ParametersListArrayAdaptor( + const ParametersListPtrType& theParameters) + : myParameters (theParameters) + { + } + + //! Destructor. + Standard_EXPORT virtual ~IMeshData_ParametersListArrayAdaptor() + { + } + + //! Returns lower index in parameters array. + Standard_EXPORT Standard_Integer Lower() const + { + return 0; + } + + //! Returns upper index in parameters array. + Standard_EXPORT Standard_Integer Upper() const + { + return myParameters->ParametersNb() - 1; + } + + //! Returns value of the given index. + Standard_EXPORT Standard_Real Value(const Standard_Integer theIndex) const + { + return myParameters->GetParameter(theIndex); + } + +private: + + IMeshData_ParametersListArrayAdaptor ( + const IMeshData_ParametersListArrayAdaptor& theOther); + + void operator=(const IMeshData_ParametersListArrayAdaptor& theOther); + + const ParametersListPtrType myParameters; +}; + +#endif \ No newline at end of file diff --git a/src/IMeshData/IMeshData_Shape.hxx b/src/IMeshData/IMeshData_Shape.hxx new file mode 100644 index 0000000000..eb5100a42a --- /dev/null +++ b/src/IMeshData/IMeshData_Shape.hxx @@ -0,0 +1,66 @@ +// Created on: 2016-04-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _IMeshData_Shape_HeaderFile +#define _IMeshData_Shape_HeaderFile + +#include +#include + +//! Interface class representing model with associated TopoDS_Shape. +//! Intended for inheritance by structures and algorithms keeping +//! reference TopoDS_Shape. +class IMeshData_Shape : public Standard_Transient +{ +public: + + //! Destructor. + Standard_EXPORT virtual ~IMeshData_Shape() + { + } + + //! Assigns shape to discrete shape. + inline void SetShape (const TopoDS_Shape& theShape) + { + myShape = theShape; + } + + //! Returns shape assigned to discrete shape. + const TopoDS_Shape& GetShape () const + { + return myShape; + } + + DEFINE_STANDARD_RTTI_INLINE(IMeshData_Shape, Standard_Transient) + +protected: + + //! Constructor. + Standard_EXPORT IMeshData_Shape() + { + } + + //! Constructor. + Standard_EXPORT IMeshData_Shape (const TopoDS_Shape& theShape) + : myShape(theShape) + { + } + +private: + + TopoDS_Shape myShape; +}; + +#endif \ No newline at end of file diff --git a/src/IMeshData/IMeshData_Status.hxx b/src/IMeshData/IMeshData_Status.hxx new file mode 100644 index 0000000000..4ba98d7daa --- /dev/null +++ b/src/IMeshData/IMeshData_Status.hxx @@ -0,0 +1,33 @@ +// Created on: 2011-05-17 +// Created by: Oleg AGASHIN +// Copyright (c) 2011-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. + +#ifndef _IMeshData_Status_HeaderFile +#define _IMeshData_Status_HeaderFile + +//! Enumerates statuses used to notify state of discrete model. +enum IMeshData_Status +{ + IMeshData_NoError = 0x0, //!< Mesh generation is successful. + IMeshData_OpenWire = 0x1, //!< Notifies open wire problem, which can potentially lead to incorrect results. + IMeshData_SelfIntersectingWire = 0x2, //!< Notifies self-intersections on discretized wire, which can potentially lead to incorrect results. + IMeshData_Failure = 0x4, //!< Failed to generate mesh for some faces. + IMeshData_ReMesh = 0x8, //!< Deflection of some edges has been decreased due to interference of discrete model. + IMeshData_UnorientedWire = 0x10, //!< Notifies bad orientation of a wire, which can potentially lead to incorrect results. + IMeshData_TooFewPoints = 0x20, //!< Discrete model contains too few boundary points to generate mesh. + IMeshData_Outdated = 0x40, //!< Existing triangulation of some faces corresponds to greater deflection than specified by parameter. + IMeshData_Reused = 0x80 //!< Existing triangulation of some faces is reused as far as it fits specified deflection. +}; + +#endif diff --git a/src/IMeshData/IMeshData_StatusOwner.hxx b/src/IMeshData/IMeshData_StatusOwner.hxx new file mode 100644 index 0000000000..d1b54b032c --- /dev/null +++ b/src/IMeshData/IMeshData_StatusOwner.hxx @@ -0,0 +1,76 @@ +// Created on: 2016-06-23 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _IMeshData_StatusOwner_HeaderFile +#define _IMeshData_StatusOwner_HeaderFile + +#include +#include +#include + +//! Extension interface class providing status functionality. +class IMeshData_StatusOwner +{ +public: + + //! Destructor. + Standard_EXPORT virtual ~IMeshData_StatusOwner() + { + } + + //! Returns true in case if status is strictly equal to the given value. + inline Standard_Boolean IsEqual(const IMeshData_Status theValue) const + { + return (myStatus == theValue); + } + + //! Returns true in case if status is set. + inline Standard_Boolean IsSet(const IMeshData_Status theValue) const + { + return (myStatus & theValue) != 0; + } + + //! Adds status to status flags of a face. + inline void SetStatus(const IMeshData_Status theValue) + { + myStatus |= theValue; + } + + //! Adds status to status flags of a face. + inline void UnsetStatus(const IMeshData_Status theValue) + { + myStatus &= ~theValue; + } + + //! Returns complete status mask. + inline Standard_Integer GetStatusMask() const + { + return myStatus; + } + +protected: + + //! Constructor. Initializes default status. + Standard_EXPORT IMeshData_StatusOwner() + : myStatus(IMeshData_NoError) + { + } + +private: + + Standard_Integer myStatus; +}; + +#endif diff --git a/src/IMeshData/IMeshData_TessellatedShape.hxx b/src/IMeshData/IMeshData_TessellatedShape.hxx new file mode 100644 index 0000000000..94001b032d --- /dev/null +++ b/src/IMeshData/IMeshData_TessellatedShape.hxx @@ -0,0 +1,67 @@ +// Created on: 2016-04-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _IMeshData_TessellatedShape_HeaderFile +#define _IMeshData_TessellatedShape_HeaderFile + +#include +#include +#include + +//! Interface class representing shaped model with deflection. +class IMeshData_TessellatedShape : public IMeshData_Shape +{ +public: + + //! Destructor. + Standard_EXPORT virtual ~IMeshData_TessellatedShape() + { + } + + //! Gets deflection value for the discrete model. + inline Standard_Real GetDeflection () const + { + return myDeflection; + } + + //! Sets deflection value for the discrete model. + inline void SetDeflection (const Standard_Real theValue) + { + myDeflection = theValue; + } + + DEFINE_STANDARD_RTTI_INLINE(IMeshData_TessellatedShape, IMeshData_Shape) + +protected: + + //! Constructor. + Standard_EXPORT IMeshData_TessellatedShape () + : myDeflection(RealLast()) + { + } + + //! Constructor. + Standard_EXPORT IMeshData_TessellatedShape (const TopoDS_Shape& theShape) + : IMeshData_Shape(theShape), + myDeflection(RealLast()) + { + } + +private: + + Standard_Real myDeflection; +}; + +#endif \ No newline at end of file diff --git a/src/IMeshData/IMeshData_Types.hxx b/src/IMeshData/IMeshData_Types.hxx new file mode 100644 index 0000000000..0b52effc0a --- /dev/null +++ b/src/IMeshData/IMeshData_Types.hxx @@ -0,0 +1,170 @@ +// Created on: 2016-04-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _IMeshData_Types_HeaderFile +#define _IMeshData_Types_HeaderFile + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +class IMeshData_Shape; +class IMeshData_Face; +class IMeshData_Wire; +class IMeshData_Edge; +class IMeshData_Curve; +class IMeshData_PCurve; +class IMeshData_Model; +class BRepMesh_VertexInspector; +class BRepMesh_CircleInspector; + +#define DEFINE_INC_ALLOC \ + DEFINE_NCOLLECTION_ALLOC \ + void operator delete (void* /*theAddress*/) \ + { \ + /*it's inc allocator, nothing to do*/ \ + } + +namespace IMeshData +{ + //! Default size for memory block allocated by IncAllocator. + /** + * The idea here is that blocks of the given size are returned to the system + * rather than retained in the malloc heap, at least on WIN32 and WIN64 platforms. + */ +#ifdef _WIN64 + const size_t MEMORY_BLOCK_SIZE_HUGE = 1024 * 1024; +#else + const size_t MEMORY_BLOCK_SIZE_HUGE = 512 * 1024; +#endif + + typedef IMeshData_Edge* IEdgePtr; + typedef IMeshData_Face* IFacePtr; + + typedef Handle(IMeshData_Edge) IEdgeHandle; + typedef Handle(IMeshData_Wire) IWireHandle; + typedef Handle(IMeshData_Face) IFaceHandle; + typedef Handle(IMeshData_Curve) ICurveHandle; + typedef Handle(IMeshData_PCurve) IPCurveHandle; + + typedef IMeshData_ParametersListArrayAdaptor ICurveArrayAdaptor; + typedef Handle(ICurveArrayAdaptor) ICurveArrayAdaptorHandle; + + typedef NCollection_Shared > BndBox2dTree; + typedef NCollection_UBTreeFiller BndBox2dTreeFiller; + + // Vectors + typedef NCollection_Shared > VectorOfIFaceHandles; + typedef NCollection_Shared > VectorOfIWireHandles; + typedef NCollection_Shared > VectorOfIEdgeHandles; + typedef NCollection_Shared > VectorOfIPCurveHandles; + typedef NCollection_Shared > VectorOfIEdgePtrs; + typedef NCollection_Shared > VectorOfBoolean; + typedef NCollection_Shared > VectorOfInteger; + typedef NCollection_Shared > VectorOfOrientation; + typedef NCollection_Shared > VectorOfElements; + typedef NCollection_Shared > VectorOfCircle; + + typedef NCollection_Shared > Array1OfVertexOfDelaun; + typedef NCollection_Shared > VectorOfVertex; + + // Sequences + typedef NCollection_Shared > SequenceOfBndB2d; + typedef NCollection_Shared > SequenceOfInteger; + typedef NCollection_Shared > SequenceOfReal; + + namespace Model + { + typedef std::deque > SequenceOfPnt; + typedef std::deque > SequenceOfPnt2d; + typedef std::deque > SequenceOfReal; + typedef std::deque > SequenceOfInteger; + } + + // Lists + typedef NCollection_Shared > ListOfInteger; + typedef NCollection_Shared > ListOfPnt2d; + typedef NCollection_Shared > ListOfIPCurves; + + typedef NCollection_Shared MapOfInteger; + typedef TColStd_MapIteratorOfPackedMapOfInteger IteratorOfMapOfInteger; + + typedef NCollection_CellFilter CircleCellFilter; + typedef NCollection_CellFilter VertexCellFilter; + + // Data Maps + template + struct WeakEqual + { + static Standard_Boolean IsEqual(const Type* theFirst, + const Type* theSecond) + { + return (theFirst == theSecond); + } + + //! Computes a hash code for the given pointer, in the range [1, theUpperBound] + //! @param thePointer the pointer which hash code is to be computed + //! @param theUpperBound the upper bound of the range a computing hash code must be within + //! @return a computed hash code, in the range [1, theUpperBound] + static Standard_Integer HashCode (const Type* const thePointer, Standard_Integer theUpperBound) + { + return ::HashCode (thePointer, theUpperBound); + } + }; + + typedef NCollection_Shared > DMapOfShapeInteger; + typedef NCollection_Shared > > DMapOfIFacePtrsListOfInteger; + typedef NCollection_Shared > > MapOfIEdgePtr; + typedef NCollection_Shared > > MapOfIFacePtr; + typedef NCollection_Shared > MapOfOrientedEdges; + typedef NCollection_Shared > MapOfReal; + typedef NCollection_Shared > > IDMapOfIFacePtrsListOfIPCurves; + typedef NCollection_Shared > > DMapOfIFacePtrsMapOfIEdgePtrs; + typedef NCollection_Shared > IDMapOfLink; + typedef NCollection_Shared > DMapOfIntegerListOfInteger; + typedef NCollection_Shared > MapOfIntegerInteger; + typedef NCollection_Shared > IMapOfReal; + + typedef NCollection_Shared > Array1OfInteger; +} + +#endif diff --git a/src/IMeshData/IMeshData_Wire.hxx b/src/IMeshData/IMeshData_Wire.hxx new file mode 100644 index 0000000000..e2c2634f71 --- /dev/null +++ b/src/IMeshData/IMeshData_Wire.hxx @@ -0,0 +1,74 @@ +// Created on: 2016-04-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _IMeshData_Wire_HeaderFile +#define _IMeshData_Wire_HeaderFile + +#include +#include +#include +#include +#include +#include + +class IMeshData_Edge; + +//! Interface class representing discrete model of a wire. +//! Wire should represent an ordered set of edges. +class IMeshData_Wire : public IMeshData_TessellatedShape, public IMeshData_StatusOwner +{ +public: + + //! Destructor. + Standard_EXPORT virtual ~IMeshData_Wire() + { + } + + //! Returns TopoDS_Face attached to model. + inline const TopoDS_Wire& GetWire () const + { + return TopoDS::Wire (GetShape ()); + } + + //! Returns number of edges. + Standard_EXPORT virtual Standard_Integer EdgesNb () const = 0; + + //! Adds new discrete edge with specified orientation to wire chain. + //! @return index of added edge in wire chain. + Standard_EXPORT virtual Standard_Integer AddEdge ( + const IMeshData::IEdgePtr& theDEdge, + const TopAbs_Orientation theOrientation) = 0; + + //! Returns discrete edge with the given index. + Standard_EXPORT virtual const IMeshData::IEdgePtr& GetEdge ( + const Standard_Integer theIndex) const = 0; + + //! Returns True if orientation of discrete edge with the given index is forward. + Standard_EXPORT virtual TopAbs_Orientation GetEdgeOrientation ( + const Standard_Integer theIndex) const = 0; + + DEFINE_STANDARD_RTTI_INLINE(IMeshData_Wire, IMeshData_TessellatedShape) + +protected: + + //! Constructor. + //! Initializes empty model. + Standard_EXPORT IMeshData_Wire(const TopoDS_Wire& theWire) + : IMeshData_TessellatedShape(theWire) + { + } +}; + +#endif \ No newline at end of file diff --git a/src/IMeshTools/FILES b/src/IMeshTools/FILES new file mode 100644 index 0000000000..e582bc1d1b --- /dev/null +++ b/src/IMeshTools/FILES @@ -0,0 +1,12 @@ +IMeshTools_Context.hxx +IMeshTools_CurveTessellator.hxx +IMeshTools_MeshAlgo.hxx +IMeshTools_MeshAlgoFactory.hxx +IMeshTools_MeshBuilder.hxx +IMeshTools_MeshBuilder.cxx +IMeshTools_ModelAlgo.hxx +IMeshTools_ModelBuilder.hxx +IMeshTools_Parameters.hxx +IMeshTools_ShapeExplorer.hxx +IMeshTools_ShapeExplorer.cxx +IMeshTools_ShapeVisitor.hxx diff --git a/src/IMeshTools/IMeshTools_Context.hxx b/src/IMeshTools/IMeshTools_Context.hxx new file mode 100644 index 0000000000..fe77996c2e --- /dev/null +++ b/src/IMeshTools/IMeshTools_Context.hxx @@ -0,0 +1,240 @@ +// Created on: 2016-04-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _IMeshTools_Context_HeaderFile +#define _IMeshTools_Context_HeaderFile + +#include +#include +#include +#include +#include +#include + +//! Interface class representing context of BRepMesh algorithm. +//! Intended to cache discrete model and instances of tools for +//! its processing. +class IMeshTools_Context : public IMeshData_Shape +{ +public: + + //! Constructor. + Standard_EXPORT IMeshTools_Context() + { + } + + //! Destructor. + Standard_EXPORT virtual ~IMeshTools_Context() + { + } + + //! Builds model using assined model builder. + //! @return True on success, False elsewhere. + Standard_EXPORT virtual Standard_Boolean BuildModel () + { + if (myModelBuilder.IsNull()) + { + return Standard_False; + } + + myModel = myModelBuilder->Perform(GetShape(), myParameters); + + return !myModel.IsNull(); + } + + //! Performs discretization of model edges using assigned edge discret algorithm. + //! @return True on success, False elsewhere. + Standard_EXPORT virtual Standard_Boolean DiscretizeEdges() + { + if (myModel.IsNull() || myEdgeDiscret.IsNull()) + { + return Standard_False; + } + + // Discretize edges of a model. + return myEdgeDiscret->Perform(myModel, myParameters); + } + + //! Performs healing of discrete model built by DiscretizeEdges() method + //! using assigned healing algorithm. + //! @return True on success, False elsewhere. + Standard_EXPORT virtual Standard_Boolean HealModel() + { + if (myModel.IsNull()) + { + return Standard_False; + } + + return myModelHealer.IsNull() ? + Standard_True : + myModelHealer->Perform(myModel, myParameters); + } + + //! Performs pre-processing of discrete model using assigned algorithm. + //! Performs auxiliary actions such as cleaning shape from old triangulation. + //! @return True on success, False elsewhere. + Standard_EXPORT virtual Standard_Boolean PreProcessModel() + { + if (myModel.IsNull()) + { + return Standard_False; + } + + return myPreProcessor.IsNull() ? + Standard_True : + myPreProcessor->Perform(myModel, myParameters); + } + + //! Performs meshing of faces of discrete model using assigned meshing algorithm. + //! @return True on success, False elsewhere. + Standard_EXPORT virtual Standard_Boolean DiscretizeFaces() + { + if (myModel.IsNull() || myFaceDiscret.IsNull()) + { + return Standard_False; + } + + // Discretize faces of a model. + return myFaceDiscret->Perform(myModel, myParameters); + } + + //! Performs post-processing of discrete model using assigned algorithm. + //! @return True on success, False elsewhere. + Standard_EXPORT virtual Standard_Boolean PostProcessModel() + { + if (myModel.IsNull()) + { + return Standard_False; + } + + return myPostProcessor.IsNull() ? + Standard_True : + myPostProcessor->Perform(myModel, myParameters); + } + + //! Cleans temporary context data. + Standard_EXPORT virtual void Clean() + { + if (myParameters.CleanModel) + { + myModel.Nullify(); + } + } + + //! Gets instance of a tool to be used to build discrete model. + inline const Handle (IMeshTools_ModelBuilder)& GetModelBuilder () const + { + return myModelBuilder; + } + + //! Sets instance of a tool to be used to build discrete model. + inline void SetModelBuilder (const Handle (IMeshTools_ModelBuilder)& theBuilder) + { + myModelBuilder = theBuilder; + } + + //! Gets instance of a tool to be used to discretize edges of a model. + inline const Handle (IMeshTools_ModelAlgo)& GetEdgeDiscret () const + { + return myEdgeDiscret; + } + + //! Sets instance of a tool to be used to discretize edges of a model. + inline void SetEdgeDiscret (const Handle (IMeshTools_ModelAlgo)& theEdgeDiscret) + { + myEdgeDiscret = theEdgeDiscret; + } + + //! Gets instance of a tool to be used to heal discrete model. + inline const Handle(IMeshTools_ModelAlgo)& GetModelHealer() const + { + return myModelHealer; + } + + //! Sets instance of a tool to be used to heal discrete model. + inline void SetModelHealer(const Handle(IMeshTools_ModelAlgo)& theModelHealer) + { + myModelHealer = theModelHealer; + } + + //! Gets instance of pre-processing algorithm. + inline const Handle(IMeshTools_ModelAlgo)& GetPreProcessor() const + { + return myPreProcessor; + } + + //! Sets instance of pre-processing algorithm. + inline void SetPreProcessor(const Handle(IMeshTools_ModelAlgo)& thePreProcessor) + { + myPreProcessor = thePreProcessor; + } + + //! Gets instance of meshing algorithm. + inline const Handle(IMeshTools_ModelAlgo)& GetFaceDiscret() const + { + return myFaceDiscret; + } + + //! Sets instance of meshing algorithm. + inline void SetFaceDiscret(const Handle(IMeshTools_ModelAlgo)& theFaceDiscret) + { + myFaceDiscret = theFaceDiscret; + } + + //! Gets instance of post-processing algorithm. + inline const Handle(IMeshTools_ModelAlgo)& GetPostProcessor() const + { + return myPostProcessor; + } + + //! Sets instance of post-processing algorithm. + inline void SetPostProcessor(const Handle(IMeshTools_ModelAlgo)& thePostProcessor) + { + myPostProcessor = thePostProcessor; + } + + //! Gets parameters to be used for meshing. + inline const IMeshTools_Parameters& GetParameters () const + { + return myParameters; + } + + //! Gets reference to parameters to be used for meshing. + inline IMeshTools_Parameters& ChangeParameters () + { + return myParameters; + } + + //! Returns discrete model of a shape. + inline const Handle (IMeshData_Model)& GetModel () const + { + return myModel; + } + + DEFINE_STANDARD_RTTI_INLINE(IMeshTools_Context, IMeshData_Shape) + +private: + + Handle (IMeshTools_ModelBuilder) myModelBuilder; + Handle (IMeshData_Model) myModel; + Handle (IMeshTools_ModelAlgo) myEdgeDiscret; + Handle (IMeshTools_ModelAlgo) myModelHealer; + Handle (IMeshTools_ModelAlgo) myPreProcessor; + Handle (IMeshTools_ModelAlgo) myFaceDiscret; + Handle (IMeshTools_ModelAlgo) myPostProcessor; + IMeshTools_Parameters myParameters; +}; + +#endif \ No newline at end of file diff --git a/src/BRepMesh/BRepMesh_IEdgeTool.hxx b/src/IMeshTools/IMeshTools_CurveTessellator.hxx similarity index 62% rename from src/BRepMesh/BRepMesh_IEdgeTool.hxx rename to src/IMeshTools/IMeshTools_CurveTessellator.hxx index 6bbd84a74b..2cbd66bfd6 100644 --- a/src/BRepMesh/BRepMesh_IEdgeTool.hxx +++ b/src/IMeshTools/IMeshTools_CurveTessellator.hxx @@ -1,6 +1,6 @@ -// Created on: 2014-08-13 +// Created on: 2016-04-19 +// Copyright (c) 2016 OPEN CASCADE SAS // Created by: Oleg AGASHIN -// Copyright (c) 2011-2014 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. // @@ -13,36 +13,45 @@ // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. -#ifndef _BRepMesh_IEdgeTool_HeaderFile -#define _BRepMesh_IEdgeTool_HeaderFile +#ifndef _IMeshTools_EdgeTessellator_HeaderFile +#define _IMeshTools_EdgeTessellator_HeaderFile -#include -#include -#include #include +#include + +class gp_Pnt; //! Interface class providing API for edge tessellation tools. -class BRepMesh_IEdgeTool : public Standard_Transient +class IMeshTools_CurveTessellator : public Standard_Transient { public: + + //! Destructor. + Standard_EXPORT virtual ~IMeshTools_CurveTessellator() + { + } + //! Returns number of tessellation points. - virtual Standard_Integer NbPoints() const = 0; + Standard_EXPORT virtual Standard_Integer PointsNb () const = 0; //! Returns parameters of solution with the given index. //! @param theIndex index of tessellation point. - //! @param theParameter parameters on PCurve corresponded to the solution. //! @param thePoint tessellation point. - //! @param theUV coordinates of tessellation point in parametric space of face. + //! @param theParameter parameters on PCurve corresponded to the solution. //! @return True in case of valid result, false elewhere. - virtual Standard_Boolean Value( + Standard_EXPORT virtual Standard_Boolean Value ( const Standard_Integer theIndex, - Standard_Real& theParameter, gp_Pnt& thePoint, - gp_Pnt2d& theUV) = 0; + Standard_Real& theParameter) const = 0; - DEFINE_STANDARD_RTTIEXT(BRepMesh_IEdgeTool,Standard_Transient) -}; + DEFINE_STANDARD_RTTI_INLINE(IMeshTools_CurveTessellator, Standard_Transient) -DEFINE_STANDARD_HANDLE(BRepMesh_IEdgeTool, Standard_Transient) +protected: + + //! Constructor. + Standard_EXPORT IMeshTools_CurveTessellator() + { + } +}; -#endif +#endif \ No newline at end of file diff --git a/src/IMeshTools/IMeshTools_MeshAlgo.hxx b/src/IMeshTools/IMeshTools_MeshAlgo.hxx new file mode 100644 index 0000000000..fb8e0b6d49 --- /dev/null +++ b/src/IMeshTools/IMeshTools_MeshAlgo.hxx @@ -0,0 +1,50 @@ +// Created on: 2016-07-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _IMeshTools_MeshAlgo_HeaderFile +#define _IMeshTools_MeshAlgo_HeaderFile + +#include +#include +#include + +struct IMeshTools_Parameters; + +//! Interface class providing API for algorithms intended to create mesh for discrete face. +class IMeshTools_MeshAlgo : public Standard_Transient +{ +public: + + //! Destructor. + Standard_EXPORT virtual ~IMeshTools_MeshAlgo() + { + } + + //! Performs processing of the given face. + Standard_EXPORT virtual void Perform( + const IMeshData::IFaceHandle& theDFace, + const IMeshTools_Parameters& theParameters) = 0; + + DEFINE_STANDARD_RTTI_INLINE(IMeshTools_MeshAlgo, Standard_Transient) + +protected: + + //! Constructor. + Standard_EXPORT IMeshTools_MeshAlgo() + { + } +}; + +#endif \ No newline at end of file diff --git a/src/IMeshTools/IMeshTools_MeshAlgoFactory.hxx b/src/IMeshTools/IMeshTools_MeshAlgoFactory.hxx new file mode 100644 index 0000000000..47008755bc --- /dev/null +++ b/src/IMeshTools/IMeshTools_MeshAlgoFactory.hxx @@ -0,0 +1,52 @@ +// Created on: 2016-07-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _IMeshTools_MeshAlgoFactory_HeaderFile +#define _IMeshTools_MeshAlgoFactory_HeaderFile + +#include +#include +#include +#include + +struct IMeshTools_Parameters; + +//! Base interface for factories producing instances of triangulation +//! algorithms taking into account type of surface of target face. +class IMeshTools_MeshAlgoFactory : public Standard_Transient +{ +public: + + //! Destructor. + Standard_EXPORT virtual ~IMeshTools_MeshAlgoFactory() + { + } + + //! Creates instance of meshing algorithm for the given type of surface. + Standard_EXPORT virtual Handle(IMeshTools_MeshAlgo) GetAlgo( + const GeomAbs_SurfaceType theSurfaceType, + const IMeshTools_Parameters& theParameters) const = 0; + + DEFINE_STANDARD_RTTI_INLINE(IMeshTools_MeshAlgoFactory, Standard_Transient) + +protected: + + //! Constructor. + Standard_EXPORT IMeshTools_MeshAlgoFactory() + { + } +}; + +#endif \ No newline at end of file diff --git a/src/IMeshTools/IMeshTools_MeshBuilder.cxx b/src/IMeshTools/IMeshTools_MeshBuilder.cxx new file mode 100644 index 0000000000..3b67a6c798 --- /dev/null +++ b/src/IMeshTools/IMeshTools_MeshBuilder.cxx @@ -0,0 +1,118 @@ +// Created on: 2016-04-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 +#include +#include + +//======================================================================= +// Function: Constructor +// Purpose : +//======================================================================= +IMeshTools_MeshBuilder::IMeshTools_MeshBuilder () +{ +} + +//======================================================================= +// Function: Constructor +// Purpose : +//======================================================================= +IMeshTools_MeshBuilder::IMeshTools_MeshBuilder ( + const Handle (IMeshTools_Context)& theContext) + : myContext(theContext) +{ +} + +//======================================================================= +// Function: Destructor +// Purpose : +//======================================================================= +IMeshTools_MeshBuilder::~IMeshTools_MeshBuilder () +{ +} + +//======================================================================= +// Function: Perform +// Purpose : +//======================================================================= +void IMeshTools_MeshBuilder::Perform () +{ + ClearStatus (); + + const Handle (IMeshTools_Context)& aContext = GetContext (); + if (aContext.IsNull ()) + { + SetStatus (Message_Fail1); + return; + } + + if (aContext->BuildModel ()) + { + if (aContext->DiscretizeEdges ()) + { + if (aContext->HealModel ()) + { + if (aContext->PreProcessModel()) + { + if (aContext->DiscretizeFaces()) + { + if (aContext->PostProcessModel()) + { + SetStatus(Message_Done1); + } + else + { + SetStatus(Message_Fail7); + } + } + else + { + SetStatus(Message_Fail6); + } + } + else + { + SetStatus(Message_Fail5); + } + } + else + { + SetStatus(Message_Fail4); + } + } + else + { + SetStatus (Message_Fail3); + } + } + else + { + const Handle (IMeshTools_ModelBuilder)& aModelBuilder = + aContext->GetModelBuilder (); + + if (aModelBuilder.IsNull ()) + { + SetStatus (Message_Fail1); + } + else + { + // Is null shape or another problem? + SetStatus (aModelBuilder->GetStatus ().IsSet (Message_Fail1) ? + Message_Warn1 : Message_Fail2); + } + } + + aContext->Clean (); +} diff --git a/src/IMeshTools/IMeshTools_MeshBuilder.hxx b/src/IMeshTools/IMeshTools_MeshBuilder.hxx new file mode 100644 index 0000000000..8c0d314224 --- /dev/null +++ b/src/IMeshTools/IMeshTools_MeshBuilder.hxx @@ -0,0 +1,74 @@ +// Created on: 2016-04-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _IMeshTools_MeshBuilder_HeaderFile +#define _IMeshTools_MeshBuilder_HeaderFile + +#include +#include +#include + +//! Builds mesh for each face of shape without triangulation. +//! In case if some faces of shape have already been triangulated +//! checks deflection of existing polygonal model and re-uses it +//! if deflection satisfies the specified parameter. Otherwise +//! nullifies existing triangulation and build triangulation anew. +//! +//! The following statuses are used: +//! Message_Done1 - algorithm has finished without errors. +//! Message_Fail1 - invalid context. +//! Message_Fail2 - algorithm has faced unexpected error. +//! Message_Fail3 - fail to discretize edges. +//! Message_Fail4 - can't heal discrete model. +//! Message_Fail5 - fail to pre-process model. +//! Message_Fail6 - fail to discretize faces. +//! Message_Fail7 - fail to post-process model. +//! Message_Warn1 - shape contains no objects to mesh. +class IMeshTools_MeshBuilder : public Message_Algorithm +{ +public: + + //! Constructor. + Standard_EXPORT IMeshTools_MeshBuilder(); + + //! Constructor. + Standard_EXPORT IMeshTools_MeshBuilder (const Handle (IMeshTools_Context)& theContext); + + //! Destructor. + Standard_EXPORT virtual ~IMeshTools_MeshBuilder(); + + //! Sets context for algorithm. + inline void SetContext (const Handle (IMeshTools_Context)& theContext) + { + myContext = theContext; + } + + //! Gets context of algorithm. + inline const Handle (IMeshTools_Context)& GetContext () const + { + return myContext; + } + + //! Performs meshing ot the shape using current context. + Standard_EXPORT virtual void Perform (); + + DEFINE_STANDARD_RTTI_INLINE(IMeshTools_MeshBuilder, Message_Algorithm) + +private: + + Handle (IMeshTools_Context) myContext; +}; + +#endif \ No newline at end of file diff --git a/src/IMeshTools/IMeshTools_ModelAlgo.hxx b/src/IMeshTools/IMeshTools_ModelAlgo.hxx new file mode 100644 index 0000000000..963c880c75 --- /dev/null +++ b/src/IMeshTools/IMeshTools_ModelAlgo.hxx @@ -0,0 +1,69 @@ +// Created on: 2016-04-19 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _IMeshTools_ModelAlgo_HeaderFile +#define _IMeshTools_ModelAlgo_HeaderFile + +#include +#include +#include +#include + +class IMeshData_Model; +struct IMeshTools_Parameters; + +//! Interface class providing API for algorithms intended to update or modify discrete model. +class IMeshTools_ModelAlgo : public Standard_Transient +{ +public: + + //! Destructor. + Standard_EXPORT virtual ~IMeshTools_ModelAlgo() + { + } + + //! Exceptions protected processing of the given model. + Standard_Boolean Perform ( + const Handle (IMeshData_Model)& theModel, + const IMeshTools_Parameters& theParameters) + { + try + { + OCC_CATCH_SIGNALS + + return performInternal (theModel, theParameters); + } + catch (Standard_Failure const&) + { + return Standard_False; + } + } + + DEFINE_STANDARD_RTTI_INLINE(IMeshTools_ModelAlgo, Standard_Transient) + +protected: + + //! Constructor. + Standard_EXPORT IMeshTools_ModelAlgo() + { + } + + //! Performs processing of the given model. + Standard_EXPORT virtual Standard_Boolean performInternal ( + const Handle (IMeshData_Model)& theModel, + const IMeshTools_Parameters& theParameters) = 0; +}; + +#endif \ No newline at end of file diff --git a/src/IMeshTools/IMeshTools_ModelBuilder.hxx b/src/IMeshTools/IMeshTools_ModelBuilder.hxx new file mode 100644 index 0000000000..5d6d416932 --- /dev/null +++ b/src/IMeshTools/IMeshTools_ModelBuilder.hxx @@ -0,0 +1,80 @@ +// Created on: 2016-04-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _IMeshTools_ModelBuilder_HeaderFile +#define _IMeshTools_ModelBuilder_HeaderFile + +#include +#include +#include +#include +#include + +class IMeshData_Model; +struct IMeshTools_Parameters; + +//! Interface class represents API for tool building discrete model. +//! +//! The following statuses should be used by default: +//! Message_Done1 - model has been sucessfully built. +//! Message_Fail1 - empty shape. +//! Message_Fail2 - model has not been build due to unexpected reason. +class IMeshTools_ModelBuilder : public Message_Algorithm +{ +public: + + //! Destructor. + Standard_EXPORT virtual ~IMeshTools_ModelBuilder() + { + } + + //! Exceptions protected method to create discrete model for the given shape. + //! Returns nullptr in case of failure. + Handle (IMeshData_Model) Perform ( + const TopoDS_Shape& theShape, + const IMeshTools_Parameters& theParameters) + { + ClearStatus (); + + try + { + OCC_CATCH_SIGNALS + + return performInternal (theShape, theParameters); + } + catch (Standard_Failure const&) + { + SetStatus (Message_Fail2); + return NULL; + } + } + + DEFINE_STANDARD_RTTI_INLINE(IMeshTools_ModelBuilder, Message_Algorithm) + +protected: + + //! Constructor. + Standard_EXPORT IMeshTools_ModelBuilder() + { + } + + //! Creates discrete model for the given shape. + //! Returns nullptr in case of failure. + Standard_EXPORT virtual Handle (IMeshData_Model) performInternal ( + const TopoDS_Shape& theShape, + const IMeshTools_Parameters& theParameters) = 0; +}; + +#endif \ No newline at end of file diff --git a/src/IMeshTools/IMeshTools_Parameters.hxx b/src/IMeshTools/IMeshTools_Parameters.hxx new file mode 100644 index 0000000000..6279708a78 --- /dev/null +++ b/src/IMeshTools/IMeshTools_Parameters.hxx @@ -0,0 +1,88 @@ +// Created on: 2016-04-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _IMeshTools_Parameters_HeaderFile +#define _IMeshTools_Parameters_HeaderFile + +#include + +//! Structure storing meshing parameters +struct IMeshTools_Parameters { + + //! Default constructor + IMeshTools_Parameters () + : + Angle(0.5), + Deflection(0.001), + AngleInterior(-1.0), + DeflectionInterior(-1.0), + MinSize (-1.0), + InParallel (Standard_False), + Relative (Standard_False), + InternalVerticesMode (Standard_True), + ControlSurfaceDeflection (Standard_True), + CleanModel (Standard_True), + AdjustMinSize (Standard_False) + { + } + + //! Returns factor used to compute default value of MinSize + //! (minimum mesh edge length) from deflection + static Standard_Real RelMinSize() + { + return 0.1; + } + + //! Angular deflection used to tessellate the boundary edges + Standard_Real Angle; + + //!Linear deflection used to tessellate the boundary edges + Standard_Real Deflection; + + //! Angular deflection used to tessellate the face interior + Standard_Real AngleInterior; + + //! Linear deflection used to tessellate the face interior + Standard_Real DeflectionInterior; + + //! Minimal allowed size of mesh element + Standard_Real MinSize; + + //! Switches on/off multi-thread computation + Standard_Boolean InParallel; + + //! Switches on/off relative computation of edge tolerance
+ //! If true, deflection used for the polygonalisation of each edge will be + //! * Size of Edge. The deflection used for the faces will be the + //! maximum deflection of their edges. + Standard_Boolean Relative; + + //! Mode to take or not to take internal face vertices into account + //! in triangulation process + Standard_Boolean InternalVerticesMode; + + //! Parameter to check the deviation of triangulation and interior of + //! the face + Standard_Boolean ControlSurfaceDeflection; + + //! Cleans temporary data model when algorithm is finished. + Standard_Boolean CleanModel; + + //! Enables/disables local adjustment of min size depending on edge size. + //! Disabled by default. + Standard_Boolean AdjustMinSize; +}; + +#endif diff --git a/src/IMeshTools/IMeshTools_ShapeExplorer.cxx b/src/IMeshTools/IMeshTools_ShapeExplorer.cxx new file mode 100644 index 0000000000..2dc244a73c --- /dev/null +++ b/src/IMeshTools/IMeshTools_ShapeExplorer.cxx @@ -0,0 +1,113 @@ +// Created on: 2016-04-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace +{ + //======================================================================= + // Function: visitEdges + // Purpose : Explodes the given shape on edges according to the specified + // criteria and visits each one in order to add it to data model. + //======================================================================= + void visitEdges (const Handle (IMeshTools_ShapeVisitor)& theVisitor, + const TopoDS_Shape& theShape, + const TopAbs_ShapeEnum theToFind, + const TopAbs_ShapeEnum theToAvoid = TopAbs_SHAPE) + { + TopExp_Explorer aEdgesIt (theShape, theToFind, theToAvoid); + for (; aEdgesIt.More (); aEdgesIt.Next ()) + { + const TopoDS_Edge& aEdge = TopoDS::Edge (aEdgesIt.Current ()); + if (!BRep_Tool::IsGeometric (aEdge)) + { + continue; + } + + theVisitor->Visit (aEdge); + } + } +} + +//======================================================================= +// Function: Constructor +// Purpose : +//======================================================================= +IMeshTools_ShapeExplorer::IMeshTools_ShapeExplorer ( + const TopoDS_Shape& theShape) + : IMeshData_Shape (theShape) +{ +} + +//======================================================================= +// Function: Destructor +// Purpose : +//======================================================================= +IMeshTools_ShapeExplorer::~IMeshTools_ShapeExplorer () +{ +} + +//======================================================================= +// Function: Accept +// Purpose : +//======================================================================= +void IMeshTools_ShapeExplorer::Accept ( + const Handle (IMeshTools_ShapeVisitor)& theVisitor) +{ + // Explore all free edges in shape. + visitEdges (theVisitor, GetShape (), TopAbs_EDGE, TopAbs_FACE); + + // Explore all related to some face edges in shape. + // make array of faces suitable for processing (excluding faces without surface) + TopTools_ListOfShape aFaceList; + BRepLib::ReverseSortFaces (GetShape (), aFaceList); + TopTools_MapOfShape aFaceMap; + + TopLoc_Location aDummyLoc; + const TopLoc_Location aEmptyLoc; + TopTools_ListIteratorOfListOfShape aFaceIter (aFaceList); + for (; aFaceIter.More (); aFaceIter.Next ()) + { + TopoDS_Shape aFaceNoLoc = aFaceIter.Value (); + aFaceNoLoc.Location (aEmptyLoc); + if (!aFaceMap.Add(aFaceNoLoc)) + { + continue; // already processed + } + + const TopoDS_Face& aFace = TopoDS::Face (aFaceIter.Value ()); + const Handle (Geom_Surface)& aSurf = BRep_Tool::Surface (aFace, aDummyLoc); + if (aSurf.IsNull()) + { + continue; + } + + // Explore all edges in face. + visitEdges (theVisitor, aFace, TopAbs_EDGE); + + // Store only forward faces in order to prevent inverse issue. + theVisitor->Visit (TopoDS::Face (aFace.Oriented (TopAbs_FORWARD))); + } +} diff --git a/src/IMeshTools/IMeshTools_ShapeExplorer.hxx b/src/IMeshTools/IMeshTools_ShapeExplorer.hxx new file mode 100644 index 0000000000..0e96ddc60e --- /dev/null +++ b/src/IMeshTools/IMeshTools_ShapeExplorer.hxx @@ -0,0 +1,41 @@ +// Created on: 2016-04-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _IMeshTools_ShapeExplorer_HeaderFile +#define _IMeshTools_ShapeExplorer_HeaderFile + +#include +#include +#include +#include + +//! Explores TopoDS_Shape for parts to be meshed - faces and free edges. +class IMeshTools_ShapeExplorer : public IMeshData_Shape +{ +public: + + //! Constructor. + Standard_EXPORT IMeshTools_ShapeExplorer (const TopoDS_Shape& theShape); + + //! Destructor. + Standard_EXPORT virtual ~IMeshTools_ShapeExplorer(); + + //! Starts exploring of a shape. + Standard_EXPORT virtual void Accept (const Handle (IMeshTools_ShapeVisitor)& theVisitor); + + DEFINE_STANDARD_RTTI_INLINE(IMeshTools_ShapeExplorer, IMeshData_Shape) +}; + +#endif \ No newline at end of file diff --git a/src/IMeshTools/IMeshTools_ShapeVisitor.hxx b/src/IMeshTools/IMeshTools_ShapeVisitor.hxx new file mode 100644 index 0000000000..50ee23dc49 --- /dev/null +++ b/src/IMeshTools/IMeshTools_ShapeVisitor.hxx @@ -0,0 +1,51 @@ +// Created on: 2016-04-07 +// Copyright (c) 2016 OPEN CASCADE SAS +// Created by: Oleg AGASHIN +// +// 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 _IMeshTools_ShapeVisitor_HeaderFile +#define _IMeshTools_ShapeVisitor_HeaderFile + +#include +#include + +class TopoDS_Face; +class TopoDS_Edge; + +//! Interface class for shape visitor. +class IMeshTools_ShapeVisitor : public Standard_Transient +{ +public: + + //! Destructor. + Standard_EXPORT virtual ~IMeshTools_ShapeVisitor() + { + } + + //! Handles TopoDS_Face object. + Standard_EXPORT virtual void Visit (const TopoDS_Face& theFace) = 0; + + //! Handles TopoDS_Edge object. + Standard_EXPORT virtual void Visit (const TopoDS_Edge& theEdge) = 0; + + DEFINE_STANDARD_RTTI_INLINE(IMeshTools_ShapeVisitor, Standard_Transient) + +protected: + + //! Constructor. + Standard_EXPORT IMeshTools_ShapeVisitor() + { + } +}; + +#endif \ No newline at end of file diff --git a/src/MeshTest/MeshTest.cxx b/src/MeshTest/MeshTest.cxx index 7db1a42f02..c7ff84c7f2 100644 --- a/src/MeshTest/MeshTest.cxx +++ b/src/MeshTest/MeshTest.cxx @@ -130,7 +130,7 @@ options:\n\ -surf_def_off disables control of deflection of mesh from real\n\ surface (enabled by default)\n\ -parallel enables parallel execution (switched off by default)\n\ - -adaptive enables adaptive computation of minimal value in parametric space\n"; + -adjust_min enables local adjustment of min size depending on edge size\n"; return 0; } @@ -148,7 +148,7 @@ options:\n\ Standard_Boolean isInParallel = Standard_False; Standard_Boolean isIntVertices = Standard_True; Standard_Boolean isControlSurDef = Standard_True; - Standard_Boolean isAdaptiveMin = Standard_False; + Standard_Boolean isAdjustMinSize = Standard_False; if (nbarg > 3) { @@ -168,8 +168,8 @@ options:\n\ isIntVertices = Standard_False; else if (aOpt == "-surf_def_off") isControlSurDef = Standard_False; - else if (aOpt == "-adaptive") - isAdaptiveMin = Standard_True; + else if (aOpt == "-adjust_min") + isAdjustMinSize = Standard_True; else if (i < nbarg) { Standard_Real aVal = Draw::Atof(argv[i++]); @@ -186,7 +186,7 @@ options:\n\ di << "Incremental Mesh, multi-threading " << (isInParallel ? "ON" : "OFF") << "\n"; - BRepMesh_FastDiscret::Parameters aMeshParams; + IMeshTools_Parameters aMeshParams; aMeshParams.Deflection = aLinDeflection; aMeshParams.Angle = aAngDeflection; aMeshParams.Relative = isRelative; @@ -194,13 +194,10 @@ options:\n\ aMeshParams.MinSize = aMinSize; aMeshParams.InternalVerticesMode = isIntVertices; aMeshParams.ControlSurfaceDeflection = isControlSurDef; - aMeshParams.AdaptiveMin = isAdaptiveMin; + aMeshParams.AdjustMinSize = isAdjustMinSize; Handle(Draw_ProgressIndicator) aProgress = new Draw_ProgressIndicator(di, 1); - BRepMesh_IncrementalMesh aMesher; - aMesher.SetShape (aShape); - aMesher.ChangeParameters() = aMeshParams; - aMesher.Perform (aProgress); + BRepMesh_IncrementalMesh aMesher (aShape, aMeshParams); di << "Meshing statuses: "; Standard_Integer statusFlags = aMesher.GetStatusFlags(); @@ -409,114 +406,6 @@ static Standard_Integer MemLeakTest(Draw_Interpretor&, Standard_Integer /*nbarg* return 0; } -//======================================================================= -//function : fastdiscret -//purpose : -//======================================================================= - -static Standard_Integer fastdiscret(Draw_Interpretor& di, Standard_Integer nbarg, const char** argv) -{ - if (nbarg < 3) return 1; - - TopoDS_Shape S = DBRep::Get(argv[1]); - if (S.IsNull()) return 1; - - const Standard_Real d = Draw::Atof(argv[2]); - - Bnd_Box B; - BRepBndLib::Add(S,B); - BRepMesh_FastDiscret::Parameters aParams; - aParams.Deflection = d; - aParams.Angle = 0.5; - BRepMesh_FastDiscret MESH(B,aParams); - - //Standard_Integer NbIterations = MESH.NbIterations(); - //if (nbarg > 4) NbIterations = Draw::Atoi(argv[4]); - //MESH.NbIterations() = NbIterations; - - di<<"Starting FastDiscret with :\n"; - di<<" Deflection="<NbTriangles(); - nbnodes += T->NbNodes(); - if (T->Deflection() > maxdef) maxdef = T->Deflection(); - if (T->Deflection() > d) - { - nbviolating++; - if (aCompViolating.IsNull()) - aBuilder.MakeCompound(aCompViolating); - aBuilder.Add(aCompViolating,ex.Current()); - } - else - { - if (aCompGood.IsNull()) - aBuilder.MakeCompound(aCompGood); - aBuilder.Add(aCompGood,ex.Current()); - } - } - } - - if (!aCompGood.IsNull()) - { - char name[256]; - strcpy(name,argv[1]); - strcat(name,"_good"); - DBRep::Set(name,aCompGood); - } - if (!aCompFailed.IsNull()) - { - char name[256]; - strcpy(name,argv[1]); - strcat(name,"_failed"); - DBRep::Set(name,aCompFailed); - } - if (!aCompViolating.IsNull()) - { - char name[256]; - strcpy(name,argv[1]); - strcat(name,"_violating"); - DBRep::Set(name,aCompViolating); - } - - di<<"FastDiscret completed with :\n"; - di<<" MaxDeflection="< #include #include #include #include #include #include +#include // This file defines global functions not declared in any public header, // intended for use from debugger prompt (Command Window in Visual Studio) @@ -28,19 +28,18 @@ //function : MeshTest_DrawLinks //purpose : Draw links from mesh data structure of type BRepMesh_FaceAttribute //======================================================================= -Standard_EXPORT const char* MeshTest_DrawLinks(const char* theNameStr, void* theFaceAttr) +Standard_EXPORT const char* MeshTest_DrawLinks(const char* theNameStr, void* theDataStruct) { - if (theNameStr == 0 || theFaceAttr == 0) + if (theNameStr == 0 || theDataStruct == 0) { return "Error: name or face attribute is null"; } try { - const Handle(BRepMesh_FaceAttribute)& aFaceAttr = *(Handle(BRepMesh_FaceAttribute)*)theFaceAttr; - const Handle(BRepMesh_DataStructureOfDelaun)& aMeshData = aFaceAttr->ChangeStructure(); + const Handle(BRepMesh_DataStructureOfDelaun)& aMeshData = *(Handle(BRepMesh_DataStructureOfDelaun)*)theDataStruct; if (aMeshData.IsNull()) return "Null mesh data structure"; Standard_Integer nbLinks = aMeshData->NbLinks(); - cout << "nblink=" << nbLinks << endl; + std::cout << "nblink=" << nbLinks << std::endl; TCollection_AsciiString aName(theNameStr); for (Standard_Integer i = 1; i <= nbLinks; i++) { @@ -51,9 +50,9 @@ Standard_EXPORT const char* MeshTest_DrawLinks(const char* theNameStr, void* the Standard_Integer n2 = aLink.LastNode(); const BRepMesh_Vertex& aV1 = aMeshData->GetNode(n1); const BRepMesh_Vertex& aV2 = aMeshData->GetNode(n2); - const gp_Pnt& aP1 = aFaceAttr->GetPoint(aV1); - const gp_Pnt& aP2 = aFaceAttr->GetPoint(aV2); - Handle(Draw_Segment3D) aSeg = new Draw_Segment3D(aP1, aP2, Draw_bleu); + Handle(Draw_Segment3D) aSeg = new Draw_Segment3D(gp_Pnt(aV1.Coord().X(), aV1.Coord().Y(), 0), + gp_Pnt(aV2.Coord().X(), aV2.Coord().Y(), 0), + Draw_bleu); Draw::Set((aName + "_" + i).ToCString(), aSeg); } return theNameStr; @@ -68,20 +67,20 @@ Standard_EXPORT const char* MeshTest_DrawLinks(const char* theNameStr, void* the //function : MeshTest_DrawTriangles //purpose : Draw triangles from mesh data structure of type BRepMesh_FaceAttribute //======================================================================= -Standard_EXPORT const char* MeshTest_DrawTriangles(const char* theNameStr, void* theFaceAttr) +Standard_EXPORT const char* MeshTest_DrawTriangles(const char* theNameStr, void* theDataStruct) { - if (theNameStr == 0 || theFaceAttr == 0) + if (theNameStr == 0 || theDataStruct == 0) { return "Error: name or face attribute is null"; } try { - const Handle(BRepMesh_FaceAttribute)& aFaceAttr = - *(Handle(BRepMesh_FaceAttribute)*)theFaceAttr; - const Handle(BRepMesh_DataStructureOfDelaun)& aMeshData = aFaceAttr->ChangeStructure(); + const Handle(BRepMesh_DataStructureOfDelaun)& aMeshData = + *(Handle(BRepMesh_DataStructureOfDelaun)*)theDataStruct; + if (aMeshData.IsNull()) return "Null mesh data structure"; Standard_Integer nbElem = aMeshData->NbElements(); - cout << "nbelem=" << nbElem << endl; + std::cout << "nbelem=" << nbElem << std::endl; TCollection_AsciiString aName(theNameStr); for (Standard_Integer i = 1; i <= nbElem; i++) { @@ -93,8 +92,10 @@ Standard_EXPORT const char* MeshTest_DrawTriangles(const char* theNameStr, void* const BRepMesh_Vertex& aV1 = aMeshData->GetNode(n[0]); const BRepMesh_Vertex& aV2 = aMeshData->GetNode(n[1]); const BRepMesh_Vertex& aV3 = aMeshData->GetNode(n[2]); - gp_Pnt aP[4] = { aFaceAttr->GetPoint(aV1), aFaceAttr->GetPoint(aV2), - aFaceAttr->GetPoint(aV3), aFaceAttr->GetPoint(aV1) }; + gp_Pnt aP[4] = { gp_Pnt(aV1.Coord().X(), aV1.Coord().Y(), 0), + gp_Pnt(aV2.Coord().X(), aV2.Coord().Y(), 0), + gp_Pnt(aV3.Coord().X(), aV3.Coord().Y(), 0), + gp_Pnt(aV1.Coord().X(), aV1.Coord().Y(), 0) }; TColgp_Array1OfPnt aPnts(aP[0], 1, 4); Handle(Poly_Polygon3D) aPoly = new Poly_Polygon3D(aPnts); Handle(DrawTrSurf_Polygon3D) aDPoly = new DrawTrSurf_Polygon3D(aPoly); diff --git a/src/MeshTest/MeshTest_DrawableMesh.cxx b/src/MeshTest/MeshTest_DrawableMesh.cxx index 5385c51e55..7a1a57400a 100644 --- a/src/MeshTest/MeshTest_DrawableMesh.cxx +++ b/src/MeshTest/MeshTest_DrawableMesh.cxx @@ -29,6 +29,7 @@ #include #include #include +#include IMPLEMENT_STANDARD_RTTIEXT(MeshTest_DrawableMesh,Draw_Drawable3D) diff --git a/src/QABugs/QABugs_11.cxx b/src/QABugs/QABugs_11.cxx index f432ca06c0..5c7e766558 100644 --- a/src/QABugs/QABugs_11.cxx +++ b/src/QABugs/QABugs_11.cxx @@ -1309,7 +1309,7 @@ static Standard_Integer OCC369(Draw_Interpretor& di, Standard_Integer argc, cons if(aShape.IsNull()) {di << "OCC369 FAULTY. Entry shape is NULL \n"; return 0;} // 3. Build mesh - BRepMesh_FastDiscret::Parameters aMeshParams; + IMeshTools_Parameters aMeshParams; aMeshParams.Relative = Standard_True; aMeshParams.Deflection = 0.2; aMeshParams.Angle = M_PI / 6; diff --git a/src/SelectMgr/SelectMgr_TriangularFrustumSet.cxx b/src/SelectMgr/SelectMgr_TriangularFrustumSet.cxx index 87f7a473f0..1a442d4fcc 100644 --- a/src/SelectMgr/SelectMgr_TriangularFrustumSet.cxx +++ b/src/SelectMgr/SelectMgr_TriangularFrustumSet.cxx @@ -37,11 +37,11 @@ void SelectMgr_TriangularFrustumSet::Build (const TColgp_Array1OfPnt2d& thePoint Handle(BRepMesh_DataStructureOfDelaun) aMeshStructure = new BRepMesh_DataStructureOfDelaun(anAllocator); Standard_Integer aPtsLower = thePoints.Lower(); Standard_Integer aPtsUpper = thePoints.Upper(); - BRepMesh::Array1OfInteger anIndexes (0, thePoints.Length() - 1); + IMeshData::VectorOfInteger anIndexes (thePoints.Length()); for (Standard_Integer aPtIdx = aPtsLower; aPtIdx <= aPtsUpper; ++aPtIdx) { BRepMesh_Vertex aVertex (thePoints.Value (aPtIdx).XY(), aPtIdx, BRepMesh_Frontier); - anIndexes.ChangeValue (aPtIdx - aPtsLower) = aMeshStructure->AddNode (aVertex); + anIndexes.Append (aMeshStructure->AddNode (aVertex)); } Standard_Real aPtSum = 0; @@ -64,11 +64,11 @@ void SelectMgr_TriangularFrustumSet::Build (const TColgp_Array1OfPnt2d& thePoint } BRepMesh_Delaun aTriangulation (aMeshStructure, anIndexes); - const BRepMesh::MapOfInteger& aTriangles = aMeshStructure->ElementsOfDomain(); + const IMeshData::MapOfInteger& aTriangles = aMeshStructure->ElementsOfDomain(); if (aTriangles.Extent() < 1) return; - BRepMesh::MapOfInteger::Iterator aTriangleIt (aTriangles); + IMeshData::IteratorOfMapOfInteger aTriangleIt (aTriangles); for (; aTriangleIt.More(); aTriangleIt.Next()) { const Standard_Integer aTriangleId = aTriangleIt.Key(); diff --git a/src/StdPrs/StdPrs_HLRPolyShape.cxx b/src/StdPrs/StdPrs_HLRPolyShape.cxx index 4ade3a16cf..e3f6a5cd89 100644 --- a/src/StdPrs/StdPrs_HLRPolyShape.cxx +++ b/src/StdPrs/StdPrs_HLRPolyShape.cxx @@ -68,7 +68,7 @@ void StdPrs_HLRPolyShape::Add(const Handle (Prs3d_Presentation)& aPresentation, { const Standard_Boolean aRel = aDrawer->TypeOfDeflection() == Aspect_TOD_RELATIVE; Standard_Real aDef = aRel ? aDrawer->HLRDeviationCoefficient() : aDrawer->MaximalChordialDeviation(); - BRepMesh_FastDiscret::Parameters aMeshParams; + IMeshTools_Parameters aMeshParams; aMeshParams.Relative = aRel; aMeshParams.Angle = aDrawer->HLRAngle(); aMeshParams.Deflection = aDef; diff --git a/src/TKMesh/EXTERNLIB b/src/TKMesh/EXTERNLIB index 97605066fa..c428c62550 100755 --- a/src/TKMesh/EXTERNLIB +++ b/src/TKMesh/EXTERNLIB @@ -1,9 +1,8 @@ -TKBRep -TKMath TKernel -TKG2d -TKG3d -TKGeomBase +TKMath +TKBRep TKTopAlgo -TKGeomAlgo -CSF_TBB +TKShHealing +TKGeomBase +TKG3d +TKG2d diff --git a/src/TKMesh/PACKAGES b/src/TKMesh/PACKAGES index 0ce38247e0..d5379def2f 100755 --- a/src/TKMesh/PACKAGES +++ b/src/TKMesh/PACKAGES @@ -1 +1,4 @@ +IMeshData +IMeshTools +BRepMeshData BRepMesh diff --git a/tests/bugs/grids.list b/tests/bugs/grids.list index 5d666dbcad..1dbf87494d 100755 --- a/tests/bugs/grids.list +++ b/tests/bugs/grids.list @@ -19,4 +19,4 @@ 019 heal 020 stlvrml 021 splitshape -022 splitshape1 +022 splitshape_1 diff --git a/tests/lowalgos/grids.list b/tests/lowalgos/grids.list index cbd0c385f2..ee6ff4d6c2 100644 --- a/tests/lowalgos/grids.list +++ b/tests/lowalgos/grids.list @@ -1,3 +1,2 @@ -001 2dinter -002 bnd -003 extcc +001 bnd +002 extcc -- 2.39.5