From 37e0750cd2b5897f35c43aaa87711cddd217e2e7 Mon Sep 17 00:00:00 2001 From: blobfish Date: Tue, 4 Nov 2014 13:22:25 -0500 Subject: [PATCH] Part: ModelRefine: adding bspline support --- src/Mod/Part/App/modelRefine.cpp | 160 +++++++++++++++++++++++++++++++ src/Mod/Part/App/modelRefine.h | 12 +++ 2 files changed, 172 insertions(+) diff --git a/src/Mod/Part/App/modelRefine.cpp b/src/Mod/Part/App/modelRefine.cpp index b2b490b0b..4c8baf8f8 100644 --- a/src/Mod/Part/App/modelRefine.cpp +++ b/src/Mod/Part/App/modelRefine.cpp @@ -29,8 +29,11 @@ #include #include #include +#include #include #include +#include +#include #include #include #include @@ -753,6 +756,162 @@ void collectConicEdges(const TopoDS_Shell &shell, TopTools_IndexedMapOfShape &ma } #endif +FaceTypedBSpline::FaceTypedBSpline() : FaceTypedBase(GeomAbs_BSplineSurface) +{ +} + +bool FaceTypedBSpline::isEqual(const TopoDS_Face &faceOne, const TopoDS_Face &faceTwo) const +{ + Handle(Geom_BSplineSurface) surfaceOne = Handle(Geom_BSplineSurface)::DownCast(BRep_Tool::Surface(faceOne)); + Handle(Geom_BSplineSurface) surfaceTwo = Handle(Geom_BSplineSurface)::DownCast(BRep_Tool::Surface(faceTwo)); + + if (surfaceOne.IsNull() || surfaceTwo.IsNull()) + return false; + + if (surfaceOne->IsURational() != surfaceTwo->IsURational()) return false; + if (surfaceTwo->IsVRational() != surfaceTwo->IsVRational()) return false; + if (surfaceOne->IsUPeriodic() != surfaceTwo->IsUPeriodic()) return false; + if (surfaceOne->IsVPeriodic() != surfaceTwo->IsVPeriodic()) return false; + if (surfaceOne->IsUClosed() != surfaceTwo->IsUClosed()) return false; + if (surfaceOne->IsVClosed() != surfaceTwo->IsVClosed()) return false; + if (surfaceOne->UDegree() != surfaceTwo->UDegree()) return false; + if (surfaceOne->VDegree() != surfaceTwo->VDegree()) return false; + + //pole test + int uPoleCountOne(surfaceOne->NbUPoles()); + int vPoleCountOne(surfaceOne->NbVPoles()); + int uPoleCountTwo(surfaceTwo->NbUPoles()); + int vPoleCountTwo(surfaceTwo->NbVPoles()); + + if (uPoleCountOne != uPoleCountTwo || vPoleCountOne != vPoleCountTwo) + return false; + + TColgp_Array2OfPnt polesOne(1, uPoleCountOne, 1, vPoleCountOne); + TColgp_Array2OfPnt polesTwo(1, uPoleCountTwo, 1, vPoleCountTwo); + surfaceOne->Poles(polesOne); + surfaceTwo->Poles(polesTwo); + + for (int indexU = 1; indexU <= uPoleCountOne; ++indexU) + { + for (int indexV = 1; indexV <= vPoleCountOne; ++indexV) + { + if (!(polesOne.Value(indexU, indexV).IsEqual(polesTwo.Value(indexU, indexV), Precision::Confusion()))) + return false; + } + } + + //knot test + int uKnotCountOne(surfaceOne->NbUKnots()); + int vKnotCountOne(surfaceOne->NbVKnots()); + int uKnotCountTwo(surfaceTwo->NbUKnots()); + int vKnotCountTwo(surfaceTwo->NbVKnots()); + if (uKnotCountOne != uKnotCountTwo || vKnotCountOne != vKnotCountTwo) + return false; + TColStd_Array1OfReal uKnotsOne(1, uKnotCountOne); + TColStd_Array1OfReal vKnotsOne(1, vKnotCountOne); + TColStd_Array1OfReal uKnotsTwo(1, uKnotCountTwo); + TColStd_Array1OfReal vKnotsTwo(1, vKnotCountTwo); + surfaceOne->UKnots(uKnotsOne); + surfaceOne->VKnots(vKnotsOne); + surfaceTwo->UKnots(uKnotsTwo); + surfaceTwo->VKnots(vKnotsTwo); + for (int indexU = 1; indexU <= uKnotCountOne; ++indexU) + if (uKnotsOne.Value(indexU) != uKnotsTwo.Value(indexU)) + return false; + for (int indexV = 1; indexV <= vKnotCountOne; ++indexV) + if (vKnotsOne.Value(indexV) != vKnotsTwo.Value(indexV)) + return false; + + //knot sequence. + int uKnotSequenceOneCount(uPoleCountOne + surfaceOne->UDegree() + 1); + int vKnotSequenceOneCount(vPoleCountOne + surfaceOne->VDegree() + 1); + int uKnotSequenceTwoCount(uPoleCountTwo + surfaceTwo->UDegree() + 1); + int vKnotSequenceTwoCount(vPoleCountTwo + surfaceTwo->VDegree() + 1); + if (uKnotSequenceOneCount != uKnotSequenceTwoCount || vKnotSequenceOneCount != vKnotSequenceTwoCount) + return false; + TColStd_Array1OfReal uKnotSequenceOne(1, uKnotSequenceOneCount); + TColStd_Array1OfReal vKnotSequenceOne(1, vKnotSequenceOneCount); + TColStd_Array1OfReal uKnotSequenceTwo(1, uKnotSequenceTwoCount); + TColStd_Array1OfReal vKnotSequenceTwo(1, vKnotSequenceTwoCount); + surfaceOne->UKnotSequence(uKnotSequenceOne); + surfaceOne->VKnotSequence(vKnotSequenceOne); + surfaceTwo->UKnotSequence(uKnotSequenceTwo); + surfaceTwo->VKnotSequence(vKnotSequenceTwo); + for (int indexU = 1; indexU <= uKnotSequenceOneCount; ++indexU) + if (uKnotSequenceOne.Value(indexU) != uKnotSequenceTwo.Value(indexU)) + return false; + for (int indexV = 1; indexV <= vKnotSequenceOneCount; ++indexV) + if (vKnotSequenceOne.Value(indexV) != vKnotSequenceTwo.Value(indexV)) + return false; + return true; +} + +GeomAbs_SurfaceType FaceTypedBSpline::getType() const +{ + return GeomAbs_BSplineSurface; +} + +TopoDS_Face FaceTypedBSpline::buildFace(const FaceVectorType &faces) const +{ + std::vector wires; + + std::vector splitEdges; + this->boundarySplit(faces, splitEdges); + if (splitEdges.empty()) + return TopoDS_Face(); + std::vector::iterator splitIt; + for (splitIt = splitEdges.begin(); splitIt != splitEdges.end(); ++splitIt) + { + BRepLib_MakeWire wireMaker; + EdgeVectorType::iterator it; + for (it = (*splitIt).begin(); it != (*splitIt).end(); ++it) + wireMaker.Add(*it); + TopoDS_Wire currentWire = wireMaker.Wire(); + wires.push_back(currentWire); + } + + std::sort(wires.begin(), wires.end(), ModelRefine::WireSort()); + + //make face from surface and outer wire. + Handle(Geom_BSplineSurface) surface = Handle(Geom_BSplineSurface)::DownCast(BRep_Tool::Surface(faces.at(0))); + if (!surface) + return TopoDS_Face(); + std::vector::iterator wireIt; + wireIt = wires.begin(); + BRepBuilderAPI_MakeFace faceMaker(surface, *wireIt); + if (!faceMaker.IsDone()) + return TopoDS_Face(); + + //add additional boundaries. + for (wireIt++; wireIt != wires.end(); ++wireIt) + { + faceMaker.Add(*wireIt); + if (!faceMaker.IsDone()) + return TopoDS_Face(); + } + + //fix newly constructed face. Orientation doesn't seem to get fixed the first call. + ShapeFix_Face faceFixer(faceMaker.Face()); + faceFixer.SetContext(new ShapeBuild_ReShape()); + faceFixer.Perform(); + if (faceFixer.Status(ShapeExtend_FAIL)) + return TopoDS_Face(); + faceFixer.FixOrientation(); + faceFixer.Perform(); + if (faceFixer.Status(ShapeExtend_FAIL)) + return TopoDS_Face(); + + return faceFixer.Face(); +} + +FaceTypedBSpline& ModelRefine::getBSplineObject() +{ + static FaceTypedBSpline object; + return object; +} + +///////////////////////////////////////////////////////////////////////////////////////////////////////// + FaceUniter::FaceUniter(const TopoDS_Shell &shellIn) : modifiedSignal(false) { workShell = shellIn; @@ -766,6 +925,7 @@ bool FaceUniter::process() deletedShapes.clear(); typeObjects.push_back(&getPlaneObject()); typeObjects.push_back(&getCylinderObject()); + typeObjects.push_back(&getBSplineObject()); //add more face types. ModelRefine::FaceTypeSplitter splitter; diff --git a/src/Mod/Part/App/modelRefine.h b/src/Mod/Part/App/modelRefine.h index 503dd1bf8..29e97ccbb 100644 --- a/src/Mod/Part/App/modelRefine.h +++ b/src/Mod/Part/App/modelRefine.h @@ -95,6 +95,18 @@ namespace ModelRefine }; FaceTypedCylinder& getCylinderObject(); + class FaceTypedBSpline : public FaceTypedBase + { + private: + FaceTypedBSpline(); + public: + virtual bool isEqual(const TopoDS_Face &faceOne, const TopoDS_Face &faceTwo) const; + virtual GeomAbs_SurfaceType getType() const; + virtual TopoDS_Face buildFace(const FaceVectorType &faces) const; + friend FaceTypedBSpline& getBSplineObject(); + }; + FaceTypedBSpline& getBSplineObject(); + class FaceTypeSplitter { typedef std::map SplitMapType;