1 // Copyright (C) 2014-2015 EDF-R&D
2 // This library is free software; you can redistribute it and/or
3 // modify it under the terms of the GNU Lesser General Public
4 // License as published by the Free Software Foundation; either
5 // version 2.1 of the License, or (at your option) any later version.
7 // This library is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 // Lesser General Public License for more details.
12 // You should have received a copy of the GNU Lesser General Public
13 // License along with this library; if not, write to the Free Software
14 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 #include <HYDROData_TopoCurve.h>
21 #include <Approx_Curve3d.hxx>
22 #include <BRep_Builder.hxx>
23 #include <BRepAdaptor_Curve.hxx>
24 #include <BRepAdaptor_HCurve.hxx>
25 #include <BRepBuilderAPI_MakeEdge.hxx>
26 #include <Extrema_ExtCC.hxx>
27 #include <Extrema_ExtPC.hxx>
28 #include <BRepExtrema_DistShapeShape.hxx>
29 #include <GeomAPI_Interpolate.hxx>
30 #include <Geom_BSplineCurve.hxx>
31 #include <Precision.hxx>
32 #include <ShapeAnalysis_TransferParametersProj.hxx>
33 #include <ShapeBuild_Edge.hxx>
34 #include <TColgp_Array1OfVec.hxx>
35 #include <TColgp_HArray1OfPnt.hxx>
36 #include <TColStd_HArray1OfBoolean.hxx>
37 #include <TopExp_Explorer.hxx>
39 #include <TopoDS_Wire.hxx>
40 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
41 #include <TopTools_ListOfShape.hxx>
47 #include "HYDRO_trace.hxx"
48 #include <BRepTools.hxx>
50 /*! The type is intended to traverse the container
51 * either from the begin to the end or vice versa.
53 template<typename ContainerType, typename IteratorType>
57 IteratorType myIterator; //!< The iterator.
58 IteratorType myIteratorLimit; //!< The iterator limit.
60 //! The pointer to the method to traverse the next item.
61 IteratorType& (IteratorType::*myNext)();
66 const ContainerType& theContainer,
67 const bool theIsForward)
71 myIterator = theContainer.begin();
72 myIteratorLimit = theContainer.end();
73 myNext = &IteratorType::operator++;
77 myIterator = --theContainer.end();
78 myIteratorLimit = --theContainer.begin();
79 myNext = &IteratorType::operator--;
83 //! Returna 'true' if the container contains not yet traversed item.
86 return myIterator != myIteratorLimit;
89 //! Traverses to the next item.
90 IteratorType& operator ++()
92 return (myIterator.*myNext)();
95 //! Returns the iterator.
96 IteratorType& operator *() {return myIterator;}
99 /*! Inserts the value after the position.
102 template<typename ItemType> static void InsertAfter(
103 const typename std::list<ItemType>::iterator& thePosition,
104 const ItemType& theValue,
105 std::list<ItemType>& theList)
107 typename std::list<ItemType>::iterator aEIt2 = thePosition;
108 if (++aEIt2 != theList.end())
110 theList.insert(aEIt2, theValue);
114 theList.push_back(theValue);
118 /*! Converts the curve to a smooth cubic B-spline using the deflection.
121 static Handle(Geom_BSplineCurve) BSpline(
122 const BRepAdaptor_Curve& theCurve, const double theDeflection)
124 Handle(BRepAdaptor_HCurve) aCurve = new BRepAdaptor_HCurve(theCurve);
125 Approx_Curve3d aConverter(aCurve, theDeflection, GeomAbs_C1, 4, 3);
126 Handle(Geom_BSplineCurve) aBSpline;
127 return aConverter.HasResult() ? aConverter.Curve() : aBSpline;
130 /*! Replaces the vertex of the edge considering the edge orientation.
133 static TopoDS_Edge ReplaceVertex(
134 const TopoDS_Edge& theEdge, const bool theIsEndVertex)
136 TopoDS_Vertex aVertices[] = {
137 TopExp::FirstVertex(theEdge, Standard_True),
138 TopExp::LastVertex(theEdge, Standard_True)};
139 aVertices[theIsEndVertex ? 1 : 0].EmptyCopy();
140 TopoDS_Edge aNewEdge = TopoDS::Edge(theEdge.Oriented(TopAbs_FORWARD));
142 ShapeBuild_Edge().CopyReplaceVertices(aNewEdge, aVertices[0], aVertices[1]);
143 aNewEdge.Orientation(theEdge.Orientation());
147 /*! Projects the point to the curve.
150 double ProjectPointToCurve(
151 const gp_XYZ& thePoint,
152 const Adaptor3d_Curve& theCurve,
153 double& theParameter)
155 // Calculate the nearest curve internal extremum.
156 Extrema_ExtPC aAlgo(thePoint, theCurve);
158 double aMinSqDist = DBL_MAX;
161 const int aECount = aAlgo.NbExt();
162 for (int aEN = 1; aEN <= aECount; ++aEN)
164 const gp_XYZ& aP = aAlgo.Point(aEN).Value().XYZ();
165 const double aSqDist = (thePoint - aP).SquareModulus();
166 if (aMinSqDist > aSqDist)
168 aMinSqDist = aSqDist;
174 // Calculate the nearest curve end extremum.
175 const double aParams[] =
176 {theCurve.FirstParameter(), theCurve.LastParameter()};
177 const gp_XYZ aEnds[] =
178 {theCurve.Value(aParams[0]).XYZ(), theCurve.Value(aParams[1]).XYZ()};
179 const double aSqDists[] = {
180 (thePoint - aEnds[0]).SquareModulus(),
181 (thePoint - aEnds[1]).SquareModulus()};
182 for (int aEI = 0; aEI < 2; ++aEI)
184 if (aMinSqDist > aSqDists[aEI])
186 aMinSqDist = aSqDists[aEI];
193 theParameter = aParams[-aMinEN];
197 const Extrema_POnCurv& aPOnC = aAlgo.Point(aMinEN);
198 const gp_XYZ& aP = aPOnC.Value().XYZ();
199 theParameter = aPOnC.Parameter();
200 for (int aEI = 0; aEI < 2; ++aEI)
202 if (Abs(theParameter - aParams[aEI]) < Precision::PConfusion() ||
203 (aP - aEnds[aEI]).SquareModulus() < Precision::SquareConfusion())
205 theParameter = aParams[aEI];
211 // Projects the point to the edge.
212 static double ProjectPointToEdge(
213 const gp_XYZ& thePoint, const TopoDS_Edge& theEdge, double& theParameter)
215 return ProjectPointToCurve(thePoint, BRepAdaptor_Curve(theEdge), theParameter);
218 /*! Adds the parameter to the curve parameter list.
221 static int AddParameter(
222 const Adaptor3d_Curve& theCurve,
223 const double theParameter,
224 std::list<double>& theParameters)
226 // Check the coincidence.
227 std::list<double> aEndParams;
228 aEndParams.push_back(theCurve.FirstParameter());
229 aEndParams.push_back(theCurve.LastParameter());
230 std::list<double>* aParams[] = {&theParameters, &aEndParams};
231 const gp_XYZ aPoint = theCurve.Value(theParameter).XYZ();
232 for (int aLI = 0; aLI < 2; ++aLI)
234 std::list<double>::iterator aPIt = aParams[aLI]->begin();
235 std::list<double>::iterator aLastPIt = aParams[aLI]->end();
236 for (int aPI = 0; aPIt != aLastPIt; ++aPI, ++aPIt)
238 const double aParam = *aPIt;
239 if (Abs(theParameter - aParam) < Precision::PConfusion() ||
240 (theCurve.Value(aParam).XYZ() - aPoint).SquareModulus() <=
241 Precision::SquareConfusion())
248 theParameters.push_front(aEndParams.front());
252 theParameters.push_back(aEndParams.back());
261 // Calculate the position to insert.
262 std::list<double>::iterator aPIt = theParameters.begin();
263 std::list<double>::iterator aLastPIt = theParameters.end();
264 if (aPIt != aLastPIt && *aPIt < theParameter)
266 for (++aPIt; aPIt != aLastPIt && *aPIt < theParameter; ++aPIt);
267 if (aPIt != aLastPIt)
269 theParameters.insert(aPIt, theParameter);
273 theParameters.push_back(theParameter);
278 theParameters.push_front(theParameter);
283 /*! Intersects the first curve by the second one and
284 * adds the intersection parameters to the ordered list.
286 static int IntersectShape(
287 const TopoDS_Edge& theEdge1,
288 const TopoDS_Edge& theEdge2,
289 std::list<double>& theParameters)
291 if (theEdge1.IsSame(theEdge2))
292 Standard_ConstructionError::Raise("The lines to make intersection must be different");
295 BRepAdaptor_Curve aCurve1 = BRepAdaptor_Curve(theEdge1);
297 // --- Calculate Lines Intersections Points: two times, changing the order (sometimes intersections not detected)
299 BRepExtrema_DistShapeShape dst(theEdge1, theEdge2); // first order
302 DEBTRACE("nb solutions found: " << dst.NbSolution());
304 for (int i = 1; i <= dst.NbSolution(); i++)
306 P1 = dst.PointOnShape1(i);
307 P2 = dst.PointOnShape2(i);
308 Standard_Real Dist = P1.Distance(P2);
309 DEBTRACE("distance solution "<< i << " : " << Dist);
310 if (Dist <= Precision::Confusion())
313 dst.ParOnEdgeS1(i, par1);
314 DEBTRACE("parameter: " << par1);
315 nbSols += AddParameter(aCurve1, par1, theParameters); // add only new parameters
319 DEBTRACE("not an Intersection Point");
324 BRepExtrema_DistShapeShape dst2(theEdge2, theEdge1); // second order
327 DEBTRACE("nb solutions found: " << dst.NbSolution());
329 for (int i = 1; i <= dst2.NbSolution(); i++)
331 P1 = dst2.PointOnShape1(i);
332 P2 = dst2.PointOnShape2(i);
333 Standard_Real Dist = P1.Distance(P2);
334 DEBTRACE("distance solution "<< i << " : " << Dist);
335 if (Dist <= Precision::Confusion())
338 dst2.ParOnEdgeS2(i, par1);
339 DEBTRACE("parameter: " << par1);
340 nbSols += AddParameter(aCurve1, par1, theParameters); // add only new parameters
344 DEBTRACE("not an Intersection Point");
351 /*! Intersects the first edge by the second one and
352 * adds the intersection parameters to the ordered list.
354 static int IntersectEdge(
355 const TopoDS_Edge& theEdge1,
356 const TopoDS_Edge& theEdge2,
357 std::list<double>& theParameters)
359 return IntersectShape(theEdge1, theEdge2, theParameters);
362 /*! Returns the curve tangent in the position: 0 - start, 1 - end.
365 static gp_XYZ Tangent(const Adaptor3d_Curve& theCurve, const int thePosition)
367 const Standard_Real aParam = (thePosition == 0) ?
368 theCurve.FirstParameter() : theCurve.LastParameter();
371 theCurve.D1(aParam, aP, aV);
372 Standard_Real aNorm = aV.Magnitude();
373 aNorm = (aNorm >= Precision::PConfusion()) ? aNorm : 0;
374 return ((1 / aNorm) * aV).XYZ();
377 /*! Returns the edge tangent in the position: 0 - start, 1 - end.
380 static gp_XYZ Tangent(const TopoDS_Edge& theEdge, const int thePosition)
382 BRepAdaptor_Curve aCurve(theEdge);
383 return Tangent(BRepAdaptor_Curve(theEdge), thePosition);
386 static bool Interpolate(
387 const gp_XYZ thePoint1,
388 const gp_XYZ thePoint2,
389 const gp_XYZ theTangent1,
390 const gp_XYZ theTangent2,
391 Handle(Geom_BSplineCurve)& theBSpline)
393 Handle(TColgp_HArray1OfPnt) aPs = new TColgp_HArray1OfPnt(1, 2);
394 TColgp_Array1OfVec aTs(1, 2);
395 Handle(TColStd_HArray1OfBoolean) aTFs = new TColStd_HArray1OfBoolean(1, 2);
396 aPs->SetValue(1, thePoint1);
397 aPs->SetValue(2, thePoint2);
398 aTs.SetValue(1, theTangent1);
399 aTs.SetValue(2, theTangent2);
400 aTFs->SetValue(1, Standard_True);
401 aTFs->SetValue(2, Standard_True);
402 GeomAPI_Interpolate aInterpolator(aPs, Standard_False, 0);
403 aInterpolator.Load(aTs, aTFs, Standard_False);
404 aInterpolator.Perform();
405 const bool aResult = (aInterpolator.IsDone() == Standard_True);
408 theBSpline = aInterpolator.Curve();
413 bool HYDROData_TopoCurve::Initialize(const TopoDS_Wire& theWire)
415 // Check for non-emptiness.
417 TopTools_IndexedDataMapOfShapeListOfShape aVertexToEdges;
418 TopExp::MapShapesAndAncestors(theWire,
419 TopAbs_VERTEX, TopAbs_EDGE, aVertexToEdges);
420 const int aVCount = aVertexToEdges.Extent(); // number of edges (an edge can be a spline with intermediate vertices)
421 DEBTRACE("initialize VCount= "<< aVCount);
427 // Check for 1 manifoldness.
428 bool isClosed = false;
431 for (int aVN = 1; aVN <= aVCount; ++aVN)
433 const int aEdgeCount = aVertexToEdges.FindFromIndex(aVN).Extent();
443 isClosed = (aEndCount == 0);
444 if (!isClosed && aEndCount != 2)
449 std::string brepName = "theWireToSplit";
451 BRepTools::Write( theWire, brepName.c_str() );
453 // Find the start, i.e. the end which is the first vertex (or just the first vertex when closed) ==> aVN
457 for (; aVertexToEdges.FindFromIndex(aVN).Extent() == 2; ++aVN);
458 if (!aVertexToEdges.FindKey(aVN).IsEqual(TopExp::FirstVertex(
459 TopoDS::Edge(aVertexToEdges.FindFromIndex(aVN).First()), Standard_True)))
461 for (; aVertexToEdges.FindFromIndex(aVN).Extent() == 2; ++aVN);
466 TopTools_ListOfShape& aEdges = aVertexToEdges.ChangeFromIndex(1);
467 if (!aVertexToEdges.FindKey(aVN).IsEqual(
468 TopExp::FirstVertex(TopoDS::Edge(aEdges.First()), Standard_True)))
470 const TopoDS_Shape aEdge = aEdges.First();
471 aEdges.First() = aEdges.Last();
472 aEdges.Last() = aEdge;
476 // Calculate the edge order ==> list in myEdges
477 TopTools_ListOfShape* aEdges = &aVertexToEdges.ChangeFromIndex(aVN); // 1 or 2 edges from first vertex
478 while (!aEdges->IsEmpty())
480 const TopoDS_Edge aEdge = TopoDS::Edge(aEdges->First());
481 aEdges->RemoveFirst();
482 myEdges.push_back(aEdge); // add an edge in the list
483 int aVN2 = aVertexToEdges.FindIndex(TopExp::FirstVertex(aEdge));
486 aVN2 = aVertexToEdges.FindIndex(TopExp::LastVertex(aEdge));
488 aVN = aVN2; // next vertex
490 aEdges = &aVertexToEdges.ChangeFromIndex(aVN2);
491 const TopoDS_Edge aEdge2 = TopoDS::Edge(aEdges->First());
492 if (aEdge2.IsEqual(aEdge))
494 aEdges->RemoveFirst();
499 aEdges->Append(aEdge2); // next edge
503 // Check for connectedness and free vertex.
504 return (aVCount - myEdges.size()) == (isClosed ? 0 : 1);
507 TopoDS_Wire HYDROData_TopoCurve::Wire() const
510 BRep_Builder aBuilder;
511 aBuilder.MakeWire(aWire);
512 std::list<TopoDS_Edge>::const_iterator aEItLast = myEdges.end();
513 std::list<TopoDS_Edge>::const_iterator aEIt = myEdges.begin();
514 for (; aEIt != aEItLast; ++aEIt)
516 aBuilder.Add(aWire, *aEIt);
521 bool HYDROData_TopoCurve::Cut(
522 const std::list<TopoDS_Edge>::iterator& theEdgePosition,
523 const double theParameter,
524 HYDROData_TopoCurve& theCurve)
526 bool aResult = false;
529 std::list<TopoDS_Edge>::iterator aFirstEIt = myEdges.begin();
530 std::list<TopoDS_Edge>::iterator aEIt = aFirstEIt;
531 for (; aEIt != theEdgePosition; ++aEIt);
534 TopoDS_Edge aEdge = *aEIt;
535 BRepAdaptor_Curve aCurve(aEdge);
537 const double aEdgeEndParams[] =
538 {aCurve.FirstParameter(), aCurve.LastParameter()};
539 if (Abs(theParameter - aEdgeEndParams[0]) < Precision::PConfusion())
543 else if (Abs(theParameter - aEdgeEndParams[1]) < Precision::PConfusion())
547 const TopAbs_Orientation aOrient = aEdge.Orientation();
548 if (aOrient == TopAbs_REVERSED)
552 const bool isClosed = IsClosed();
553 DEBTRACE("aParamI: " << aParamI << " isClosed: "<< isClosed);
556 aEdge.Orientation(TopAbs_FORWARD);
557 TopoDS_Vertex aSplitV1, aSplitV2;
558 BRep_Builder().MakeVertex(
559 aSplitV1, aCurve.Value(theParameter), Precision::Confusion());
560 BRep_Builder().MakeVertex(
561 aSplitV2, aCurve.Value(theParameter), Precision::Confusion());
562 TopoDS_Edge aEParts[] = {
563 ShapeBuild_Edge().CopyReplaceVertices(aEdge, TopoDS_Vertex(),
564 TopoDS::Vertex(aSplitV1.Oriented(TopAbs_REVERSED))),
565 ShapeBuild_Edge().CopyReplaceVertices(aEdge, aSplitV2, TopoDS_Vertex())};
566 ShapeBuild_Edge().CopyPCurves(aEParts[0], aEdge);
567 ShapeBuild_Edge().CopyPCurves(aEParts[1], aEdge);
568 BRep_Builder().SameRange(aEParts[0], Standard_False);
569 BRep_Builder().SameRange(aEParts[1], Standard_False);
570 BRep_Builder().SameParameter(aEParts[0], Standard_False);
571 BRep_Builder().SameParameter(aEParts[1], Standard_False);
572 ShapeAnalysis_TransferParametersProj aSATPP(aEdge, TopoDS_Face());
573 aSATPP.SetMaxTolerance(Precision::Confusion());
574 aSATPP.TransferRange(aEParts[0],
575 aEdgeEndParams[0], theParameter, Standard_False);
576 aSATPP.TransferRange(aEParts[1],
577 theParameter, aEdgeEndParams[1], Standard_False);
578 aEParts[0].Orientation(aOrient);
579 aEParts[1].Orientation(aOrient);
581 const int aFirstPI = (aOrient != TopAbs_REVERSED) ? 0 : 1;
582 *aEIt = aEParts[aFirstPI];
583 InsertAfter(aEIt, aEParts[1 - aFirstPI], myEdges);
590 TopoDS_Edge aNewEdge = ReplaceVertex(aEdge, (aParamI == 0) ? false : true);
596 std::list<TopoDS_Edge>::iterator aEdgePosition = theEdgePosition;
597 if (isClosed || ++aEdgePosition != myEdges.end())
604 if (isClosed || theEdgePosition != aFirstEIt)
611 // Calculate the curve parts.
612 std::list<TopoDS_Edge>::iterator aLastEIt = myEdges.end();
613 if (aEIt != aFirstEIt && aEIt != aLastEIt)
615 std::list<TopoDS_Edge>* aEdges = !isClosed ? &theCurve.myEdges : &myEdges;
616 aEdges->splice(aEdges->begin(), myEdges, aEIt, aLastEIt);
622 void HYDROData_TopoCurve::Cut(
623 const std::list<TopoDS_Edge>::const_iterator& theEdgePosition,
624 const double theParameter,
625 HYDROData_TopoCurve& theCurve1,
626 HYDROData_TopoCurve& theCurve2) const
629 std::list<TopoDS_Edge>::const_iterator aEPos = myEdges.begin();
630 std::list<TopoDS_Edge>::iterator aEPos1 = theCurve1.myEdges.begin();
631 for (; aEPos != theEdgePosition; ++aEPos1, ++aEPos);
632 theCurve1.Cut(aEPos1, theParameter, theCurve2);
635 bool HYDROData_TopoCurve::Cut(
636 const std::deque<std::list<double> >& theParameters,
637 std::deque<HYDROData_TopoCurve>& theCurves) const
639 bool aResult = false;
640 HYDROData_TopoCurve aCurves[2];
643 std::list<TopoDS_Edge>::iterator aEIt = aCurves[0].myEdges.begin();
644 std::deque<std::list<double> >::const_iterator aPLIt = theParameters.begin();
645 for (std::deque<std::list<double> >::const_iterator aLastPLIt =
646 theParameters.end(); aPLIt != aLastPLIt; ++aPLIt)
648 TopoDS_Edge aNextEdge;
650 std::list<TopoDS_Edge>::iterator aNextEIt = aEIt;
652 if (aNextEIt != aCurves[aCI].myEdges.end())
654 aNextEdge = *aNextEIt;
658 for (Iterator<std::list<double>, std::list<double>::const_iterator> aPIt(
659 *aPLIt, (aEIt->Orientation() != TopAbs_REVERSED)); aPIt.More(); ++aPIt)
661 const int aCI1 = 1 - aCI;
662 aResult |= aCurves[aCI].Cut(aEIt, **aPIt, aCurves[aCI1]);
663 if (!aCurves[aCI1].IsEmpty())
665 theCurves.push_back(HYDROData_TopoCurve());
666 theCurves.back().append(aCurves[aCI]);
667 aEIt = aCurves[aCI1].myEdges.begin();
672 aEIt = aCurves[aCI].myEdges.begin();
676 if (!aNextEdge.IsNull() && !aEIt->IsEqual(aNextEdge))
681 theCurves.push_back(aCurves[aCI]);
685 double HYDROData_TopoCurve::Project(
686 const gp_XYZ& thePoint,
687 std::list<TopoDS_Edge>::const_iterator& theEdgeIterator,
688 double& theParameter) const
690 double aMinSqDist = DBL_MAX;
691 std::list<TopoDS_Edge>::const_iterator aEIt = myEdges.begin();
692 std::list<TopoDS_Edge>::const_iterator aLastEIt = myEdges.end();
693 for (; aEIt != aLastEIt; ++aEIt)
696 const double aSqDist = ProjectPointToEdge(thePoint, *aEIt, aParam);
697 if (aMinSqDist > aSqDist)
699 aMinSqDist = aSqDist;
700 theEdgeIterator = aEIt;
701 theParameter = aParam;
707 int HYDROData_TopoCurve::Intersect(
708 const TopoDS_Wire& theWire,
709 std::deque<std::list<double> >& theParameters) const
711 std::string brepName = "theWireTool";
713 BRepTools::Write( theWire, brepName.c_str() );
716 theParameters.resize(myEdges.size());
717 DEBTRACE("myEdges.size() " << myEdges.size());
718 std::list<TopoDS_Edge>::const_iterator aEIt = myEdges.begin();
719 std::list<TopoDS_Edge>::const_iterator aLastEIt = myEdges.end();
720 std::deque<std::list<double> >::iterator aPIt = theParameters.begin();
721 for (; aEIt != aLastEIt; ++aPIt, ++aEIt)
724 const TopoDS_Edge& aEdge = *aEIt;
725 std::list<double>& aParams = *aPIt;
726 TopExp_Explorer aEIt2(theWire, TopAbs_EDGE);
727 for (; aEIt2.More(); aEIt2.Next())
729 aIntCount += IntersectEdge(aEdge,TopoDS::Edge(aEIt2.Current()), aParams);
730 DEBTRACE("aParams.size() " << aParams.size());
733 DEBTRACE("aIntCount " << aIntCount);
737 void HYDROData_TopoCurve::CloseCurve()
739 const TopoDS_Vertex aVertex = TopoDS::Vertex(TopExp::LastVertex(
740 myEdges.back(), Standard_True).Oriented(TopAbs_FORWARD));
741 TopoDS_Edge& aEdge = myEdges.front();
742 const TopoDS_Edge aForwardEdge = TopoDS::Edge(aEdge.Oriented(TopAbs_FORWARD));
743 aEdge = TopoDS::Edge(ShapeBuild_Edge().CopyReplaceVertices(
744 aForwardEdge, aVertex, TopoDS_Vertex()).Oriented(aEdge.Orientation()));
747 void HYDROData_TopoCurve::Merge(
748 const int thePosition, HYDROData_TopoCurve& theCurve)
750 if (thePosition == 0)
752 const TopoDS_Vertex aVertex = TopoDS::Vertex(TopExp::LastVertex(
753 theCurve.myEdges.back(), Standard_True).Oriented(TopAbs_FORWARD));
754 TopoDS_Edge& aEdge = myEdges.front();
755 aEdge = TopoDS::Edge(ShapeBuild_Edge().CopyReplaceVertices(
756 TopoDS::Edge(aEdge.Oriented(TopAbs_FORWARD)), aVertex, TopoDS_Vertex()).
757 Oriented(aEdge.Orientation()));
762 const TopoDS_Vertex aVertex = TopoDS::Vertex(TopExp::FirstVertex(
763 theCurve.myEdges.front(), Standard_True).Oriented(TopAbs_REVERSED));
764 TopoDS_Edge& aEdge = myEdges.back();
765 aEdge = TopoDS::Edge(ShapeBuild_Edge().CopyReplaceVertices(
766 TopoDS::Edge(aEdge.Oriented(TopAbs_FORWARD)), TopoDS_Vertex(), aVertex).
767 Oriented(aEdge.Orientation()));
772 void HYDROData_TopoCurve::Merge(
773 const double theTolerance, std::deque<HYDROData_TopoCurve>& theCurves)
775 // Process the curve closeness.
776 const double aSqTol = theTolerance * theTolerance;
777 const gp_XYZ aPs[] = {
778 BRep_Tool::Pnt(TopExp::FirstVertex(myEdges.front(), Standard_True)).XYZ(),
779 BRep_Tool::Pnt(TopExp::LastVertex(myEdges.back(), Standard_True)).XYZ()};
780 bool isClosed = IsClosed();
781 if (!isClosed && (aPs[0] - aPs[1]).SquareModulus() <= aSqTol)
787 // Find the merge places.
788 HYDROData_TopoCurve* aCurves[] = {NULL, NULL};
792 std::deque<HYDROData_TopoCurve>::iterator aCIt = theCurves.begin();
793 std::deque<HYDROData_TopoCurve>::iterator aLastCIt = theCurves.end();
794 for (; aCIt != aLastCIt; ++aCIt)
796 HYDROData_TopoCurve& aCurve = *aCIt;
797 if (aCurve.IsEmpty() || aCurve.IsClosed())
802 const gp_XYZ aP1 = BRep_Tool::Pnt(
803 TopExp::FirstVertex(aCurve.myEdges.front(), Standard_True)).XYZ();
804 if (aCurves[0] == NULL && (aPs[1] - aP1).SquareModulus() <= aSqTol)
806 aCurves[0] = &aCurve;
809 const gp_XYZ aP2 = BRep_Tool::Pnt(
810 TopExp::LastVertex(aCurve.myEdges.back(), Standard_True)).XYZ();
811 if (aCurves[1] == NULL && (aPs[0] - aP2).SquareModulus() <= aSqTol)
813 aCurves[1] = &aCurve;
814 aOrder = (aCurves[0] == NULL) ? 1 : 0;
819 if (aCurves[0] == NULL && aCurves[1] == NULL)
821 theCurves.push_back(HYDROData_TopoCurve());
822 theCurves.back().append(*this);
824 else if (aCurves[1] == NULL)
826 aCurves[0]->Merge(0, *this);
828 else if (aCurves[0] == NULL)
830 aCurves[1]->Merge(1, *this);
834 aCurves[aOrder]->Merge(aOrder, *this);
835 if (aCurves[0] != aCurves[1])
837 aCurves[aOrder]->Merge(aOrder, *aCurves[1 - aOrder]);
841 aCurves[aOrder]->CloseCurve();
846 bool HYDROData_TopoCurve::Connect(
847 const Standard_Real theTolerance, std::deque<HYDROData_TopoCurve>& theCurves)
849 const double aSqTol = theTolerance * theTolerance;
850 const gp_XYZ aPs[] = {
851 BRep_Tool::Pnt(TopExp::FirstVertex(myEdges.front(), Standard_True)).XYZ(),
852 BRep_Tool::Pnt(TopExp::LastVertex(myEdges.back(), Standard_True)).XYZ()};
853 bool isClosed = IsClosed();
854 if (!isClosed && (aPs[0] - aPs[1]).SquareModulus() <= aSqTol)
862 std::deque<HYDROData_TopoCurve>::iterator aCIt = theCurves.begin();
863 std::deque<HYDROData_TopoCurve>::iterator aLastCIt = theCurves.end();
864 for (; aCIt != aLastCIt; ++aCIt)
866 HYDROData_TopoCurve& aCurve2 = *aCIt;
867 if (aCurve2.IsEmpty() || aCurve2.IsClosed())
872 const TopoDS_Edge* aEdges2[] =
873 {&aCurve2.myEdges.front(), &aCurve2.myEdges.back()};
874 const gp_XYZ aPs2[] = {
875 BRep_Tool::Pnt(TopExp::FirstVertex(*aEdges2[0], Standard_True)).XYZ(),
876 BRep_Tool::Pnt(TopExp::LastVertex(*aEdges2[1], Standard_True)).XYZ()};
877 const double aSqDists[] =
878 {(aPs[1] - aPs2[0]).SquareModulus(), (aPs[0] - aPs2[1]).SquareModulus()};
879 const int aOrder = (aSqDists[0] <= aSqDists[1]) ? 0 : 1;
880 if (aSqDists[aOrder] > aSqTol)
882 const TopoDS_Edge& aEdge =
883 (aOrder == 0) ? myEdges.back() : myEdges.front();
884 const gp_XYZ aPs3[] = {aPs[1 - aOrder], aPs2[aOrder]};
886 {Tangent(aEdge, 1 - aOrder), Tangent(*aEdges2[aOrder], aOrder)};
887 Handle(Geom_BSplineCurve) aBSpline;
888 if (!Interpolate(aPs3[aOrder], aPs3[1 - aOrder],
889 aTs[aOrder], aTs[1 - aOrder], aBSpline))
894 HYDROData_TopoCurve aECurve = BRepBuilderAPI_MakeEdge(aBSpline).Edge();
895 aCurve2.Merge(aOrder, aECurve);
897 aCurve2.Merge(aOrder, *this);
898 if (aSqDists[1 - aOrder] <= aSqTol)
900 aCurve2.CloseCurve();
906 theCurves.push_back(HYDROData_TopoCurve());
907 theCurves.back().append(*this);
911 int HYDROData_TopoCurve::BSplinePiecewiseCurve(
912 const double theDeflection, HYDROData_TopoCurve& theCurve) const
915 std::list<TopoDS_Edge>::const_iterator aLastEIt = myEdges.end();
916 std::list<TopoDS_Edge>::const_iterator aEIt = myEdges.begin();
917 TopoDS_Vertex aEndVertex;
918 TopoDS_Edge aPrevEdge;
919 for (; aEIt != aLastEIt; ++aEIt)
921 Handle(Geom_BSplineCurve) aBSpline =
922 ::BSpline(BRepAdaptor_Curve(*aEIt), theDeflection);
923 if (aBSpline.IsNull())
928 if (aEIt->Orientation() == TopAbs_REVERSED)
934 BRep_Builder().MakeEdge(aEdge, aBSpline, Precision::Confusion());
935 TopoDS_Vertex aVertex;
936 BRep_Builder().MakeVertex(aVertex,
937 aBSpline->Value(aBSpline->FirstParameter()), Precision::Confusion());
938 if (!aPrevEdge.IsNull())
940 BRep_Builder().Add(aPrevEdge, aVertex.Oriented(TopAbs_REVERSED));
944 aEndVertex = aVertex;
946 BRep_Builder().Add(aEdge, aVertex);
947 theCurve.myEdges.push_back(aEdge);
948 aPieceCount += aBSpline->NbKnots() - 1;
954 BRepAdaptor_Curve aCurve(aPrevEdge);
955 BRep_Builder().MakeVertex(aEndVertex,
956 aCurve.Value(aCurve.LastParameter()), Precision::Confusion());
958 BRep_Builder().Add(aPrevEdge, aEndVertex.Oriented(TopAbs_REVERSED));
962 bool HYDROData_TopoCurve::ValuesInKnots(std::list<gp_XYZ>& theValues) const
964 std::list<TopoDS_Edge>::const_iterator aLastEIt = myEdges.end();
965 std::list<TopoDS_Edge>::const_iterator aEIt = myEdges.begin();
966 for (; aEIt != aLastEIt; ++aEIt)
968 Handle(Geom_BSplineCurve) aCurve;
970 TopLoc_Location aLoc;
972 aCurve = Handle(Geom_BSplineCurve)::
973 DownCast(BRep_Tool::Curve(*aEIt, aLoc, aParams[0], aParams[1]));
974 if (!aLoc.IsIdentity() || aEIt->Orientation() != TopAbs_FORWARD ||
981 for (int aNbKnots = aCurve->NbKnots(), aKN = 1; aKN < aNbKnots; ++aKN)
983 theValues.push_back(aCurve->Value(aCurve->Knot(aKN)).XYZ());
989 TopLoc_Location aLoc;
991 Handle(Geom_Curve) aCurve =
992 BRep_Tool::Curve(myEdges.back(), aLoc, aParams[0], aParams[1]);
993 theValues.push_back(aCurve->Value(aParams[1]).XYZ());