973c2be1 |
1 | // Created on: 2012-06-09 |
2 | // Created by: jgv@ROLEX |
3 | // Copyright (c) 2012-2014 OPEN CASCADE SAS |
4 | // |
5 | // This file is part of Open CASCADE Technology software library. |
6 | // |
d5f74e42 |
7 | // This library is free software; you can redistribute it and/or modify it under |
8 | // the terms of the GNU Lesser General Public License version 2.1 as published |
973c2be1 |
9 | // by the Free Software Foundation, with special exception defined in the file |
10 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
11 | // distribution for complete text of the license and disclaimer of any warranty. |
12 | // |
13 | // Alternatively, this file may be used under the terms of Open CASCADE |
14 | // commercial license or contractual agreement. |
2277323d |
15 | |
42cf5bc1 |
16 | |
2277323d |
17 | #include <BRep_Builder.hxx> |
42cf5bc1 |
18 | #include <BRep_Tool.hxx> |
19 | #include <BRepLib.hxx> |
20 | #include <BRepLib_MakeEdge.hxx> |
389b9d5c |
21 | #include <BRepLib_MakeFace.hxx> |
42cf5bc1 |
22 | #include <BRepTopAdaptor_TopolTool.hxx> |
23 | #include <GC_MakeCircle.hxx> |
24 | #include <Geom2d_Line.hxx> |
389b9d5c |
25 | #include <GCE2d_MakeLine.hxx> |
2277323d |
26 | #include <Geom2d_TrimmedCurve.hxx> |
2277323d |
27 | #include <Geom2dConvert.hxx> |
2277323d |
28 | #include <Geom2dConvert_CompCurveToBSplineCurve.hxx> |
2277323d |
29 | #include <Geom_BezierCurve.hxx> |
42cf5bc1 |
30 | #include <Geom_BSplineCurve.hxx> |
31 | #include <Geom_Circle.hxx> |
32 | #include <Geom_CylindricalSurface.hxx> |
33 | #include <Geom_ElementarySurface.hxx> |
34 | #include <Geom_Line.hxx> |
35 | #include <Geom_OffsetSurface.hxx> |
f16a6cc5 |
36 | #include <Geom_Plane.hxx> |
42cf5bc1 |
37 | #include <Geom_RectangularTrimmedSurface.hxx> |
38 | #include <Geom_Surface.hxx> |
39 | #include <Geom_SurfaceOfLinearExtrusion.hxx> |
40 | #include <Geom_SurfaceOfRevolution.hxx> |
41 | #include <Geom_SweptSurface.hxx> |
42 | #include <Geom_TrimmedCurve.hxx> |
43 | #include <GeomAdaptor_HSurface.hxx> |
44 | #include <GeomConvert.hxx> |
45 | #include <GeomConvert_CompCurveToBSplineCurve.hxx> |
46 | #include <GeomLib_IsPlanarSurface.hxx> |
47 | #include <gp_Cylinder.hxx> |
48 | #include <gp_Dir.hxx> |
49 | #include <gp_Lin.hxx> |
50 | #include <IntPatch_ImpImpIntersection.hxx> |
51 | #include <ShapeAnalysis_Edge.hxx> |
2277323d |
52 | #include <ShapeAnalysis_WireOrder.hxx> |
53 | #include <ShapeBuild_Edge.hxx> |
42cf5bc1 |
54 | #include <ShapeBuild_ReShape.hxx> |
2277323d |
55 | #include <ShapeFix_Edge.hxx> |
42cf5bc1 |
56 | #include <ShapeFix_Face.hxx> |
2277323d |
57 | #include <ShapeFix_Shell.hxx> |
42cf5bc1 |
58 | #include <ShapeFix_Wire.hxx> |
42cf5bc1 |
59 | #include <ShapeUpgrade_UnifySameDomain.hxx> |
60 | #include <Standard_Type.hxx> |
61 | #include <TColGeom2d_Array1OfBSplineCurve.hxx> |
62 | #include <TColGeom2d_HArray1OfBSplineCurve.hxx> |
63 | #include <TColGeom2d_SequenceOfBoundedCurve.hxx> |
389b9d5c |
64 | #include <TColGeom2d_SequenceOfCurve.hxx> |
42cf5bc1 |
65 | #include <TColGeom_Array1OfBSplineCurve.hxx> |
66 | #include <TColGeom_HArray1OfBSplineCurve.hxx> |
42cf5bc1 |
67 | #include <TColGeom_SequenceOfSurface.hxx> |
68 | #include <TColStd_Array1OfReal.hxx> |
69 | #include <TColStd_MapOfInteger.hxx> |
70 | #include <TopExp.hxx> |
71 | #include <TopExp_Explorer.hxx> |
72 | #include <TopoDS.hxx> |
73 | #include <TopoDS_Edge.hxx> |
74 | #include <TopoDS_Face.hxx> |
75 | #include <TopoDS_Shape.hxx> |
76 | #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx> |
77 | #include <TopTools_IndexedMapOfShape.hxx> |
78 | #include <TopTools_ListIteratorOfListOfShape.hxx> |
b4d4dbe8 |
79 | #include <TopTools_MapOfShape.hxx> |
42cf5bc1 |
80 | #include <TopTools_SequenceOfShape.hxx> |
f7d70540 |
81 | #include <gp_Circ.hxx> |
82 | #include <BRepAdaptor_Curve.hxx> |
f0144633 |
83 | #include <BRepAdaptor_Curve2d.hxx> |
389b9d5c |
84 | #include <BRepAdaptor_Surface.hxx> |
f0144633 |
85 | #include <gp_Vec2d.hxx> |
389b9d5c |
86 | #include <Extrema_ExtPS.hxx> |
87 | #include <BRepTools.hxx> |
88 | #include <BRepTopAdaptor_FClass2d.hxx> |
f7d70540 |
89 | |
25e59720 |
90 | IMPLEMENT_STANDARD_RTTIEXT(ShapeUpgrade_UnifySameDomain,Standard_Transient) |
92efcf78 |
91 | |
f7d70540 |
92 | struct SubSequenceOfEdges |
93 | { |
94 | TopTools_SequenceOfShape SeqsEdges; |
95 | TopoDS_Edge UnionEdges; |
96 | }; |
97 | |
389b9d5c |
98 | static Standard_Real TrueValueOfOffset(const Standard_Real theValue, |
99 | const Standard_Real thePeriod) |
100 | { |
101 | if (theValue > 0.) |
102 | return thePeriod; |
103 | |
104 | return (-thePeriod); |
105 | } |
106 | |
107 | //======================================================================= |
108 | //function : UpdateBoundaries |
109 | //purpose : auxilary |
110 | //======================================================================= |
111 | static void UpdateBoundaries(const Handle(Geom2d_Curve)& thePCurve, |
112 | const Standard_Real theFirst, |
113 | const Standard_Real theLast, |
114 | Standard_Real& theUfirst, |
115 | Standard_Real& theUlast) |
116 | { |
117 | const Standard_Integer NbSamples = 4; |
118 | Standard_Real Delta = (theLast - theFirst)/NbSamples; |
119 | |
120 | for (Standard_Integer i = 0; i <= NbSamples; i++) |
121 | { |
122 | Standard_Real aParam = theFirst + i*Delta; |
123 | gp_Pnt2d aPoint = thePCurve->Value(aParam); |
124 | if (aPoint.X() < theUfirst) |
125 | theUfirst = aPoint.X(); |
126 | if (aPoint.X() > theUlast) |
127 | theUlast = aPoint.X(); |
128 | } |
129 | } |
130 | |
131 | static void RemoveEdgeFromMap(const TopoDS_Edge& theEdge, |
132 | TopTools_IndexedDataMapOfShapeListOfShape& theVEmap) |
133 | { |
134 | TopoDS_Vertex VV [2]; |
135 | TopExp::Vertices(theEdge, VV[0], VV[1]); |
136 | for (Standard_Integer i = 0; i < 2; i++) |
137 | { |
138 | TopTools_ListOfShape& Elist = theVEmap.ChangeFromKey(VV[i]); |
139 | TopTools_ListIteratorOfListOfShape itl(Elist); |
140 | while (itl.More()) |
141 | { |
142 | const TopoDS_Shape& anEdge = itl.Value(); |
143 | if (anEdge.IsSame(theEdge)) |
144 | Elist.Remove(itl); |
145 | else |
146 | itl.Next(); |
147 | } |
148 | } |
149 | } |
150 | |
151 | static Standard_Real ComputeMinEdgeSize(const TopTools_SequenceOfShape& theEdges, |
152 | const TopoDS_Face& theRefFace, |
153 | TopTools_MapOfShape& theEdgesMap) |
154 | { |
155 | Standard_Real MinSize = RealLast(); |
156 | |
157 | for (Standard_Integer ind = 1; ind <= theEdges.Length(); ind++) |
158 | { |
159 | const TopoDS_Edge& anEdge = TopoDS::Edge(theEdges(ind)); |
160 | theEdgesMap.Add(anEdge); |
161 | TopoDS_Vertex V1, V2; |
162 | TopExp::Vertices(anEdge, V1, V2); |
163 | BRepAdaptor_Curve2d BAcurve2d(anEdge, theRefFace); |
164 | gp_Pnt2d FirstP2d = BAcurve2d.Value(BAcurve2d.FirstParameter()); |
165 | gp_Pnt2d LastP2d = BAcurve2d.Value(BAcurve2d.LastParameter()); |
166 | Standard_Real aSqDist; |
167 | if (V1.IsSame(V2) && |
168 | !BRep_Tool::Degenerated(anEdge)) |
169 | { |
170 | gp_Pnt2d MidP2d = BAcurve2d.Value((BAcurve2d.FirstParameter()+BAcurve2d.LastParameter())/2); |
171 | aSqDist = FirstP2d.SquareDistance(MidP2d); |
172 | } |
173 | else |
174 | aSqDist = FirstP2d.SquareDistance(LastP2d); |
175 | if (aSqDist < MinSize) |
176 | MinSize = aSqDist; |
177 | } |
178 | MinSize = Sqrt(MinSize); |
179 | return MinSize; |
180 | } |
181 | |
182 | static void FindFaceWithMaxUbound(const TopTools_SequenceOfShape& theFaces, |
183 | const TopoDS_Face& theRefFace, |
184 | const TopTools_MapOfShape& theEdgesMap, |
185 | Standard_Real& theUmax, |
186 | Standard_Integer& theIndFaceMax) |
187 | { |
188 | theUmax = RealFirst(); |
189 | theIndFaceMax = 0; |
190 | for (Standard_Integer ii = 1; ii <= theFaces.Length(); ii++) |
191 | { |
192 | const TopoDS_Face& face_ii = TopoDS::Face(theFaces(ii)); |
193 | Standard_Real Ufirst = RealLast(), Ulast = RealFirst(); |
194 | TopExp_Explorer Explo(face_ii, TopAbs_EDGE); |
195 | for (; Explo.More(); Explo.Next()) |
196 | { |
197 | const TopoDS_Edge& anEdge = TopoDS::Edge(Explo.Current()); |
198 | if (!theEdgesMap.Contains(anEdge)) |
199 | continue; |
200 | Standard_Real fpar, lpar; |
201 | Handle(Geom2d_Curve) aPCurve = BRep_Tool::CurveOnSurface(anEdge, theRefFace, fpar, lpar); |
202 | UpdateBoundaries(aPCurve, fpar, lpar, Ufirst, Ulast); |
203 | } |
204 | if (Ulast > theUmax) |
205 | { |
206 | theUmax = Ulast; |
207 | theIndFaceMax = ii; |
208 | } |
209 | } |
210 | } |
211 | |
212 | static void RelocatePCurvesToNewUorigin(const TopTools_SequenceOfShape& theEdges, |
213 | const TopoDS_Shape& theFirstFace, |
214 | const TopoDS_Face& theRefFace, |
215 | const Standard_Real theCoordTol, |
216 | const Standard_Real theUperiod, |
217 | TopTools_IndexedDataMapOfShapeListOfShape& theVEmap, |
218 | NCollection_DataMap<TopoDS_Shape, Handle(Geom2d_Curve)>& theEdgeNewPCurve, |
219 | TopTools_MapOfShape& theUsedEdges) |
220 | { |
221 | TopTools_MapOfShape EdgesOfFirstFace; |
222 | TopExp::MapShapes(theFirstFace, EdgesOfFirstFace); |
223 | |
224 | for (;;) //walk by contours |
225 | { |
226 | //try to find the start edge that: |
227 | //1. belongs to outer edges of first face; |
228 | //2. has minimum U-coord of its start point |
229 | TopoDS_Edge StartEdge; |
230 | TopAbs_Orientation anOr = TopAbs_FORWARD; |
231 | Standard_Real anUmin = RealLast(); |
232 | for (Standard_Integer ii = 1; ii <= theEdges.Length(); ii++) |
233 | { |
234 | const TopoDS_Edge& anEdge = TopoDS::Edge(theEdges(ii)); |
235 | if (theUsedEdges.Contains(anEdge)) |
236 | continue; |
237 | if (EdgesOfFirstFace.Contains(anEdge)) |
238 | { |
239 | if (StartEdge.IsNull()) |
240 | { |
241 | StartEdge = anEdge; |
242 | BRepAdaptor_Curve2d StartBAcurve(StartEdge, theRefFace); |
243 | Standard_Real aFirstParam, aLastParam; |
244 | if (StartEdge.Orientation() == TopAbs_FORWARD) |
245 | { |
246 | aFirstParam = StartBAcurve.FirstParameter(); |
247 | aLastParam = StartBAcurve.LastParameter(); |
248 | } |
249 | else |
250 | { |
251 | aFirstParam = StartBAcurve.LastParameter(); |
252 | aLastParam = StartBAcurve.FirstParameter(); |
253 | } |
254 | gp_Pnt2d aFirstPoint = StartBAcurve.Value(aFirstParam); |
255 | gp_Pnt2d aLastPoint = StartBAcurve.Value(aLastParam); |
256 | if (aFirstPoint.X() < aLastPoint.X()) |
257 | { |
258 | anUmin = aFirstPoint.X(); |
259 | anOr = TopAbs_FORWARD; |
260 | } |
261 | else |
262 | { |
263 | anUmin = aLastPoint.X(); |
264 | anOr = TopAbs_REVERSED; |
265 | } |
266 | } |
267 | else |
268 | { |
269 | BRepAdaptor_Curve2d aBAcurve(anEdge, theRefFace); |
270 | Standard_Real aFirstParam, aLastParam; |
271 | if (anEdge.Orientation() == TopAbs_FORWARD) |
272 | { |
273 | aFirstParam = aBAcurve.FirstParameter(); |
274 | aLastParam = aBAcurve.LastParameter(); |
275 | } |
276 | else |
277 | { |
278 | aFirstParam = aBAcurve.LastParameter(); |
279 | aLastParam = aBAcurve.FirstParameter(); |
280 | } |
281 | gp_Pnt2d aFirstPoint = aBAcurve.Value(aFirstParam); |
282 | gp_Pnt2d aLastPoint = aBAcurve.Value(aLastParam); |
283 | if (aFirstPoint.X() < anUmin) |
284 | { |
285 | StartEdge = anEdge; |
286 | anUmin = aFirstPoint.X(); |
287 | anOr = TopAbs_FORWARD; |
288 | } |
289 | if (aLastPoint.X() < anUmin) |
290 | { |
291 | StartEdge = anEdge; |
292 | anUmin = aLastPoint.X(); |
293 | anOr = TopAbs_REVERSED; |
294 | } |
295 | } |
296 | } //if (EdgesOfFirstFace.Contains(anEdge)) |
297 | } //for (Standard_Integer ii = 1; ii <= edges.Length(); ii++) |
298 | |
299 | if (StartEdge.IsNull()) //all contours are passed |
300 | break; |
301 | |
302 | TopoDS_Vertex StartVertex = (anOr == TopAbs_FORWARD)? |
303 | TopExp::FirstVertex(StartEdge, Standard_True) : TopExp::LastVertex(StartEdge, Standard_True); |
304 | TopoDS_Edge CurEdge = StartEdge; |
305 | Standard_Real fpar, lpar; |
306 | Handle(Geom2d_Curve) CurPCurve = BRep_Tool::CurveOnSurface(CurEdge, theRefFace, fpar, lpar); |
307 | CurPCurve = new Geom2d_TrimmedCurve(CurPCurve, fpar, lpar); |
308 | theEdgeNewPCurve.Bind(CurEdge, CurPCurve); |
309 | if (CurEdge.Orientation() == TopAbs_REVERSED) |
310 | { Standard_Real tmp = fpar; fpar = lpar; lpar = tmp; } |
311 | //Standard_Real StartParam = (anOr == TopAbs_FORWARD)? fpar : lpar; |
312 | Standard_Real CurParam = (anOr == TopAbs_FORWARD)? lpar : fpar; |
313 | //gp_Pnt2d StartPoint = CurPCurve->Value(StartParam); |
314 | gp_Pnt2d CurPoint = CurPCurve->Value(CurParam); |
315 | for (;;) //collect pcurves of a contour |
316 | { |
317 | RemoveEdgeFromMap(CurEdge, theVEmap); |
318 | theUsedEdges.Add(CurEdge); |
319 | TopoDS_Vertex CurVertex = (anOr == TopAbs_FORWARD)? |
320 | TopExp::LastVertex(CurEdge, Standard_True) : TopExp::FirstVertex(CurEdge, Standard_True); |
321 | |
322 | const TopTools_ListOfShape& Elist = theVEmap.FindFromKey(CurVertex); |
323 | if (Elist.IsEmpty()) |
324 | break; //end of contour in 3d |
325 | |
326 | TopTools_ListIteratorOfListOfShape itl(Elist); |
327 | for (; itl.More(); itl.Next()) |
328 | { |
329 | const TopoDS_Edge& anEdge = TopoDS::Edge(itl.Value()); |
330 | if (anEdge.IsSame(CurEdge)) |
331 | continue; |
332 | TopoDS_Vertex aFirstVertex = (anOr == TopAbs_FORWARD)? |
333 | TopExp::FirstVertex(anEdge, Standard_True) : TopExp::LastVertex(anEdge, Standard_True); |
334 | if (!aFirstVertex.IsSame(CurVertex)) //may be if CurVertex is deg.vertex |
335 | continue; |
336 | |
337 | Handle(Geom2d_Curve) aPCurve = BRep_Tool::CurveOnSurface(anEdge, theRefFace, fpar, lpar); |
338 | aPCurve = new Geom2d_TrimmedCurve(aPCurve, fpar, lpar); |
339 | if (anEdge.Orientation() == TopAbs_REVERSED) |
340 | { Standard_Real tmp = fpar; fpar = lpar; lpar = tmp; } |
341 | Standard_Real aParam = (anOr == TopAbs_FORWARD)? fpar : lpar; |
342 | gp_Pnt2d aPoint = aPCurve->Value(aParam); |
343 | Standard_Real anOffset = CurPoint.X() - aPoint.X(); |
344 | if (!(Abs(anOffset) < theCoordTol || |
345 | Abs(Abs(anOffset) - theUperiod) < theCoordTol)) |
346 | continue; //may be if CurVertex is deg.vertex |
347 | |
348 | if (Abs(anOffset) > theUperiod/2) |
349 | { |
350 | anOffset = TrueValueOfOffset(anOffset, theUperiod); |
351 | gp_Vec2d aVec(anOffset, 0.); |
352 | Handle(Geom2d_Curve) aNewPCurve = Handle(Geom2d_Curve)::DownCast(aPCurve->Copy()); |
353 | aNewPCurve->Translate(aVec); |
354 | aPCurve = aNewPCurve; |
355 | } |
356 | theEdgeNewPCurve.Bind(anEdge, aPCurve); |
357 | CurEdge = anEdge; |
358 | TopAbs_Orientation CurOr = TopAbs::Compose(anOr, CurEdge.Orientation()); |
359 | CurParam = (CurOr == TopAbs_FORWARD)? |
360 | aPCurve->LastParameter() : aPCurve->FirstParameter(); |
361 | CurPoint = aPCurve->Value(CurParam); |
362 | break; |
363 | } |
364 | } //for (;;) (collect pcurves of a contour) |
365 | } //for (;;) (walk by contours) |
366 | } |
367 | |
368 | static void InsertWiresIntoFaces(const TopTools_SequenceOfShape& theWires, |
369 | const TopTools_SequenceOfShape& theFaces, |
370 | const TopoDS_Face& theRefFace) |
371 | { |
372 | BRep_Builder BB; |
373 | for (Standard_Integer ii = 1; ii <= theWires.Length(); ii++) |
374 | { |
375 | const TopoDS_Wire& aWire = TopoDS::Wire(theWires(ii)); |
376 | TopoDS_Iterator iter(aWire); |
377 | const TopoDS_Edge& anEdge = TopoDS::Edge(iter.Value()); |
378 | BRepAdaptor_Curve2d BAcurve2d(anEdge, theRefFace); |
379 | gp_Pnt2d aPnt2d = BAcurve2d.Value((BAcurve2d.FirstParameter() + BAcurve2d.LastParameter())/2.); |
8e7dc6f4 |
380 | TopoDS_Shape RequiredFace; |
389b9d5c |
381 | for (Standard_Integer jj = 1; jj <= theFaces.Length(); jj++) |
382 | { |
383 | const TopoDS_Face& aFace = TopoDS::Face(theFaces(jj)); |
384 | BRepTopAdaptor_FClass2d Classifier(aFace, Precision::Confusion()); |
385 | TopAbs_State aStatus = Classifier.Perform(aPnt2d); |
386 | if (aStatus == TopAbs_IN) |
387 | { |
8e7dc6f4 |
388 | RequiredFace = aFace.Oriented (TopAbs_FORWARD); |
389b9d5c |
389 | break; |
390 | } |
391 | } |
8e7dc6f4 |
392 | if (!RequiredFace.IsNull()) |
393 | { |
394 | BB.Add(RequiredFace, aWire); |
395 | } |
396 | else |
397 | { |
398 | Standard_ASSERT_INVOKE ("ShapeUpgrade_UnifySameDomain: wire remains unclassified"); |
399 | } |
389b9d5c |
400 | } |
401 | } |
402 | |
403 | static TopoDS_Face FindCommonFace(const TopoDS_Edge& theEdge1, |
404 | const TopoDS_Edge& theEdge2, |
405 | const TopTools_IndexedDataMapOfShapeListOfShape& theVFmap, |
406 | TopAbs_Orientation& theOrOfE1OnFace, |
407 | TopAbs_Orientation& theOrOfE2OnFace) |
408 | { |
409 | TopoDS_Vertex aVertex; |
410 | TopExp::CommonVertex(theEdge1, theEdge2, aVertex); |
411 | const TopTools_ListOfShape& Flist = theVFmap.FindFromKey(aVertex); |
412 | TopTools_ListIteratorOfListOfShape itl(Flist); |
413 | for (; itl.More(); itl.Next()) |
414 | { |
415 | TopoDS_Face aFace = TopoDS::Face(itl.Value()); |
416 | aFace.Orientation(TopAbs_FORWARD); |
417 | Standard_Boolean e1found = Standard_False, e2found = Standard_False; |
418 | TopExp_Explorer Explo(aFace, TopAbs_EDGE); |
419 | for (; Explo.More(); Explo.Next()) |
420 | { |
421 | const TopoDS_Shape& anEdge = Explo.Current(); |
422 | if (anEdge.IsSame(theEdge1)) |
423 | { |
424 | e1found = Standard_True; |
425 | theOrOfE1OnFace = anEdge.Orientation(); |
426 | } |
427 | if (anEdge.IsSame(theEdge2)) |
428 | { |
429 | e2found = Standard_True; |
430 | theOrOfE2OnFace = anEdge.Orientation(); |
431 | } |
432 | if (e1found && e2found) |
433 | return aFace; |
434 | } |
435 | } |
436 | |
437 | TopoDS_Face NullFace; |
438 | return NullFace; |
439 | } |
440 | |
441 | static Standard_Boolean FindClosestPoints(const TopoDS_Edge& theEdge1, |
442 | const TopoDS_Edge& theEdge2, |
443 | const TopTools_IndexedDataMapOfShapeListOfShape& theVFmap, |
444 | TopoDS_Face& theCommonFace, |
445 | Standard_Real& theMinSqDist, |
446 | TopAbs_Orientation& OrOfE1OnFace, |
447 | TopAbs_Orientation& OrOfE2OnFace, |
448 | Standard_Integer& theIndOnE1, |
449 | Standard_Integer& theIndOnE2, |
450 | gp_Pnt2d* PointsOnEdge1, |
451 | gp_Pnt2d* PointsOnEdge2) |
452 | |
453 | { |
454 | theCommonFace = FindCommonFace(theEdge1, theEdge2, theVFmap, OrOfE1OnFace, OrOfE2OnFace); |
455 | if (theCommonFace.IsNull()) |
456 | return Standard_False; |
457 | |
458 | Standard_Real fpar1, lpar1, fpar2, lpar2; |
459 | Handle(Geom2d_Curve) PCurve1 = BRep_Tool::CurveOnSurface(theEdge1, theCommonFace, fpar1, lpar1); |
460 | Handle(Geom2d_Curve) PCurve2 = BRep_Tool::CurveOnSurface(theEdge2, theCommonFace, fpar2, lpar2); |
461 | PointsOnEdge1[0] = PCurve1->Value(fpar1); |
462 | PointsOnEdge1[1] = PCurve1->Value(lpar1); |
463 | PointsOnEdge2[0] = PCurve2->Value(fpar2); |
464 | PointsOnEdge2[1] = PCurve2->Value(lpar2); |
465 | theMinSqDist = RealLast(); |
466 | theIndOnE1 = -1; |
467 | theIndOnE2 = -1; |
468 | for (Standard_Integer ind1 = 0; ind1 < 2; ind1++) |
469 | for (Standard_Integer ind2 = 0; ind2 < 2; ind2++) |
470 | { |
471 | Standard_Real aSqDist = PointsOnEdge1[ind1].SquareDistance(PointsOnEdge2[ind2]); |
472 | if (aSqDist < theMinSqDist) |
473 | { |
474 | theMinSqDist = aSqDist; |
475 | theIndOnE1 = ind1; theIndOnE2 = ind2; |
476 | } |
477 | } |
478 | return Standard_True; |
479 | } |
480 | |
481 | //======================================================================= |
482 | //function : ReconstructMissedSeam |
483 | //purpose : auxilary |
484 | //======================================================================= |
485 | static void ReconstructMissedSeam(const TopTools_SequenceOfShape& theEdges, |
486 | const TopTools_MapOfShape& theUsedEdges, |
487 | const TopoDS_Face& theFrefFace, |
488 | const TopoDS_Vertex& theCurVertex, |
489 | const gp_Pnt2d& theCurPoint, |
490 | const Standard_Real theUperiod, |
491 | const Standard_Real theFaceUmin, |
492 | const Standard_Real theCoordTol, |
493 | TopoDS_Edge& theNextEdge, |
494 | TopoDS_Wire& theNewWire, |
495 | gp_Pnt2d& theNextPoint, |
496 | gp_Pnt2d& theStartOfNextEdge, |
497 | TopoDS_Vertex& theLastVertexOfSeam, |
498 | TopTools_IndexedDataMapOfShapeListOfShape& theVEmap) |
499 | |
500 | { |
501 | Handle(Geom_Surface) RefSurf = BRep_Tool::Surface(theFrefFace); |
502 | GeomAbs_Shape aContinuity = (RefSurf->IsUPeriodic())? GeomAbs_CN : GeomAbs_C0; |
503 | |
504 | Standard_Real Ydir = 1.; //up |
505 | if (Abs(theCurPoint.X() - theFaceUmin) <= theCoordTol) |
506 | Ydir = -1.; //down |
507 | |
508 | //Consider as the candidate to be next edge: |
509 | //only the edge that has first point with X-coordinate close to X-coordinate of theCurPoint |
510 | //Choose from candidates the edge that is closest to theCurPoint in the defined direction Ydir |
511 | Standard_Real MinDeltaY = RealLast(); |
512 | for (Standard_Integer ind = 1; ind <= theEdges.Length(); ind++) |
513 | { |
514 | const TopoDS_Edge& aCandidate = TopoDS::Edge(theEdges(ind)); |
515 | if (theUsedEdges.Contains(aCandidate)) |
516 | continue; |
517 | BRepAdaptor_Curve2d BAcurve2d(aCandidate, theFrefFace); |
518 | Standard_Real CandParam = (aCandidate.Orientation() == TopAbs_FORWARD)? |
519 | BAcurve2d.FirstParameter() : BAcurve2d.LastParameter(); |
520 | gp_Pnt2d CandPoint = BAcurve2d.Value(CandParam); |
521 | Standard_Real DeltaX = Abs(CandPoint.X() - theCurPoint.X()); |
522 | if (DeltaX > theCoordTol) |
523 | continue; |
524 | |
525 | Standard_Real DeltaY = CandPoint.Y() - theCurPoint.Y(); |
526 | DeltaY *= Ydir; |
527 | if (DeltaY < 0.) //on the other side from CurPoint |
528 | continue; |
529 | if (DeltaY < MinDeltaY) |
530 | { |
531 | MinDeltaY = DeltaY; |
532 | theNextEdge = aCandidate; |
533 | theStartOfNextEdge = CandPoint; |
534 | } |
535 | } |
536 | |
537 | //Build missed seam edge |
538 | theLastVertexOfSeam = TopExp::FirstVertex(theNextEdge, Standard_True); //with orientation |
539 | Standard_Real CurTol = BRep_Tool::Tolerance(theCurVertex); |
540 | Standard_Real LastTol = BRep_Tool::Tolerance(theLastVertexOfSeam); |
541 | Standard_Real anU = (CurTol < LastTol)? theCurPoint.X() : theStartOfNextEdge.X(); |
542 | Handle(Geom_Curve) Uiso = RefSurf->UIso(anU); |
543 | TopoDS_Vertex V1, V2; |
544 | Standard_Real Param1, Param2; |
545 | if (Ydir > 0) |
546 | { |
547 | V1 = theCurVertex; V2 = theLastVertexOfSeam; |
548 | Param1 = theCurPoint.Y(); Param2 = theStartOfNextEdge.Y(); |
549 | } |
550 | else |
551 | { |
552 | V1 = theLastVertexOfSeam; V2 = theCurVertex; |
553 | Param1 = theStartOfNextEdge.Y(); Param2 = theCurPoint.Y(); |
554 | } |
555 | TopoDS_Edge MissedSeam = BRepLib_MakeEdge(Uiso, V1, V2, Param1, Param2); |
556 | Standard_Real Vorigin = 0.; |
557 | //Correct Param1 and Param2 if needed: |
558 | //when Uiso-curve is periodic and Param1 and Param2 do not fit into V-range of surface, |
559 | //BRepLib_MakeEdge may shift Param1 and Param2 |
560 | Standard_Real InitialParam1 = Param1, InitialParam2 = Param2; |
561 | Handle(Geom_Curve) MissedCurve = BRep_Tool::Curve(MissedSeam, Param1, Param2); |
562 | if ((Param1 != InitialParam1 || Param2 != InitialParam2) && |
563 | MissedCurve->IsPeriodic()) |
564 | { |
565 | //Vorigin = -(MissedCurve->Period()); |
566 | Vorigin = -(Param1 - InitialParam1); |
567 | } |
568 | ///////////////////////////////////// |
569 | Handle(Geom2d_Line) PC1 = new Geom2d_Line(gp_Pnt2d(anU, Vorigin), gp_Dir2d(0., 1.)); |
570 | gp_Vec2d Offset(theUperiod, 0.); |
571 | if (Ydir > 0) |
572 | Offset *= -1; |
573 | Handle(Geom2d_Curve) PC2 = Handle(Geom2d_Curve)::DownCast(PC1->Copy()); |
574 | PC2->Translate(Offset); |
575 | |
576 | BRep_Builder BB; |
577 | if (Ydir > 0) |
578 | BB.UpdateEdge(MissedSeam, PC1, PC2, theFrefFace, 0.); |
579 | else |
580 | BB.UpdateEdge(MissedSeam, PC2, PC1, theFrefFace, 0.); |
581 | BB.Continuity(MissedSeam, theFrefFace, theFrefFace, aContinuity); |
582 | if (Ydir < 0) |
583 | MissedSeam.Reverse(); |
584 | |
585 | BB.Add(theNewWire, MissedSeam); |
586 | //add newly created edge into VEmap |
587 | MissedSeam.Reverse(); |
588 | TopExp::MapShapesAndUniqueAncestors(MissedSeam, TopAbs_VERTEX, TopAbs_EDGE, theVEmap); |
589 | |
590 | BRepAdaptor_Curve2d BAcurve2d(theNextEdge, theFrefFace); |
591 | Standard_Real ParamOfNextPoint = (theNextEdge.Orientation() == TopAbs_FORWARD)? |
592 | BAcurve2d.LastParameter() : BAcurve2d.FirstParameter(); |
593 | theNextPoint = BAcurve2d.Value(ParamOfNextPoint); |
594 | } |
595 | |
596 | //======================================================================= |
597 | //function : TransformPCurves |
598 | //purpose : auxilary |
599 | //======================================================================= |
600 | static void TransformPCurves(const TopoDS_Face& theRefFace, |
601 | const TopoDS_Face& theFace, |
602 | TopTools_MapOfShape& theMapEdgesWithTemporaryPCurves) |
603 | { |
63da0df9 |
604 | BRepAdaptor_Surface BAsurf(theFace, Standard_True); //with real bounds of face |
389b9d5c |
605 | |
606 | Standard_Real Uperiod = 0., Vperiod = 0.; |
607 | Handle(Geom_Surface) RefSurf = BRep_Tool::Surface(theRefFace); |
608 | if (RefSurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) |
609 | RefSurf = (Handle(Geom_RectangularTrimmedSurface)::DownCast(RefSurf))->BasisSurface(); |
610 | if (RefSurf->IsUPeriodic()) |
611 | Uperiod = RefSurf->UPeriod(); |
612 | if (RefSurf->IsVPeriodic()) |
613 | Vperiod = RefSurf->VPeriod(); |
614 | |
615 | GeomAdaptor_Surface RefGAsurf(RefSurf); |
616 | |
617 | Standard_Real Ufirst = BAsurf.FirstUParameter(), |
618 | Ulast = BAsurf.LastUParameter(), |
619 | Vfirst = BAsurf.FirstVParameter(), |
620 | Vlast = BAsurf.LastVParameter(); |
621 | |
622 | Standard_Real u_mid = (Ufirst + Ulast)/2, v_mid = (Vfirst + Vlast)/2; |
623 | gp_Pnt MidPoint = BAsurf.Value(u_mid, v_mid); |
624 | Extrema_ExtPS ProjPS(MidPoint, RefGAsurf, |
625 | Precision::PConfusion(), Precision::PConfusion()); |
626 | Standard_Integer indmin = 1; |
627 | for (Standard_Integer iext = 2; iext <= ProjPS.NbExt(); iext++) |
628 | if (ProjPS.SquareDistance(iext) < ProjPS.SquareDistance(indmin)) |
629 | indmin = iext; |
630 | |
631 | Standard_Real uu, vv; |
632 | ProjPS.Point(indmin).Parameter(uu,vv); |
633 | //Check uu and vv |
634 | if (Abs(u_mid + Uperiod - uu) <= Precision::PConfusion()) |
635 | uu = u_mid; |
636 | if (Abs(u_mid - uu) <= Precision::PConfusion()) |
637 | uu = u_mid; |
638 | if (Abs(v_mid + Vperiod - vv) <= Precision::PConfusion()) |
639 | vv = v_mid; |
640 | if (Abs(v_mid - vv) <= Precision::PConfusion()) |
641 | vv = v_mid; |
642 | gp_Vec2d Translation(uu - u_mid, vv - v_mid); |
643 | |
644 | Standard_Boolean X_Reverse = Standard_False, Y_Reverse = Standard_False; |
645 | Standard_Real u_dx, v_dx, u_dy, v_dy; |
646 | |
647 | Standard_Real Delta = (Precision::IsInfinite(Ufirst) || Precision::IsInfinite(Ulast))? |
648 | 1. : (Ulast - Ufirst)/4; |
649 | Standard_Real Offset = (Uperiod == 0.)? Delta : Min(Uperiod/8, Delta); |
650 | Standard_Real u1 = u_mid + Offset, v1 = v_mid; |
651 | gp_Pnt DX = BAsurf.Value(u1, v1); |
652 | ProjPS.Perform(DX); |
653 | indmin = 1; |
654 | for (Standard_Integer iext = 2; iext <= ProjPS.NbExt(); iext++) |
655 | if (ProjPS.SquareDistance(iext) < ProjPS.SquareDistance(indmin)) |
656 | indmin = iext; |
657 | |
658 | ProjPS.Point(indmin).Parameter(u_dx, v_dx); |
659 | if (Uperiod != 0. && |
660 | Abs(uu - u_dx) > Uperiod/2) |
661 | { |
662 | if (uu < Uperiod/2 && |
663 | u_dx > Uperiod/2) |
664 | X_Reverse = Standard_True; |
665 | } |
666 | else if (u_dx < uu) |
667 | X_Reverse = Standard_True; |
668 | |
669 | Delta = (Precision::IsInfinite(Vfirst) || Precision::IsInfinite(Vlast))? |
670 | 1. : (Vlast - Vfirst)/4; |
671 | Offset = (Vperiod == 0.)? Delta : Min(Vperiod/8, Delta); |
672 | Standard_Real u2 = u_mid, v2 = v_mid + Offset; |
673 | gp_Pnt DY = BAsurf.Value(u2, v2); |
674 | ProjPS.Perform(DY); |
675 | indmin = 1; |
676 | for (Standard_Integer iext = 2; iext <= ProjPS.NbExt(); iext++) |
677 | if (ProjPS.SquareDistance(iext) < ProjPS.SquareDistance(indmin)) |
678 | indmin = iext; |
679 | |
680 | ProjPS.Point(indmin).Parameter(u_dy, v_dy); |
681 | if (Vperiod != 0. && |
682 | Abs(vv - v_dy) > Vperiod/2) |
683 | { |
684 | if (vv < Vperiod/2 && |
685 | v_dy > Vperiod/2) |
686 | Y_Reverse = Standard_True; |
687 | } |
688 | else if (v_dy < vv) |
689 | Y_Reverse = Standard_True; |
690 | |
691 | gp_Trsf2d aTrsf; |
692 | if (X_Reverse && Y_Reverse) |
693 | aTrsf.SetMirror(gp::Origin2d()); |
694 | else if (X_Reverse) |
695 | aTrsf.SetMirror(gp::OY2d()); |
696 | else if (Y_Reverse) |
697 | aTrsf.SetMirror(gp::OX2d()); |
698 | |
699 | aTrsf.SetTranslationPart(Translation); |
700 | |
701 | BRep_Builder BB; |
702 | TopExp_Explorer Explo(theFace, TopAbs_EDGE); |
703 | for (; Explo.More(); Explo.Next()) |
704 | { |
705 | const TopoDS_Edge& anEdge = TopoDS::Edge(Explo.Current()); |
706 | if (BRep_Tool::Degenerated(anEdge) && |
707 | aTrsf.Form() != gp_Identity) |
708 | continue; |
709 | if (BRepTools::IsReallyClosed(anEdge, theFace)) |
710 | continue; |
711 | |
712 | Standard_Real fpar, lpar; |
713 | Handle(Geom2d_Curve) PCurveOnRef = BRep_Tool::CurveOnSurface(anEdge, theRefFace, fpar, lpar); |
714 | if (!PCurveOnRef.IsNull()) |
715 | continue; |
716 | |
717 | Handle(Geom2d_Curve) aPCurve = BRep_Tool::CurveOnSurface(anEdge, theFace, fpar, lpar); |
718 | Handle(Geom2d_Curve) aNewPCurve = Handle(Geom2d_Curve)::DownCast(aPCurve->Copy()); |
719 | if (aTrsf.Form() != gp_Identity) |
720 | aNewPCurve->Transform(aTrsf); |
721 | |
722 | Standard_Real tmp_first, tmp_last; |
723 | Handle(Geom2d_Curve) aPCurveOnRefFace = BRep_Tool::CurveOnSurface(anEdge, theRefFace, |
724 | tmp_first, tmp_last); |
725 | if (aPCurveOnRefFace.IsNull()) |
726 | theMapEdgesWithTemporaryPCurves.Add(anEdge); |
727 | |
728 | BB.UpdateEdge(anEdge, aNewPCurve, theRefFace, 0.); |
729 | BB.Range(anEdge, fpar, lpar); |
730 | } |
731 | } |
732 | |
733 | //======================================================================= |
734 | //function : AddPCurves |
735 | //purpose : auxilary |
736 | //======================================================================= |
737 | static void AddPCurves(const TopTools_SequenceOfShape& theFaces, |
738 | const TopoDS_Face& theRefFace, |
739 | TopTools_MapOfShape& theMapEdgesWithTemporaryPCurves) |
740 | { |
741 | BRepAdaptor_Surface RefBAsurf(theRefFace, Standard_False); |
742 | |
743 | GeomAbs_SurfaceType aType = RefBAsurf.GetType(); |
744 | if (aType == GeomAbs_Plane) |
745 | return; |
746 | |
747 | for (Standard_Integer i = 1; i <= theFaces.Length(); i++) |
748 | { |
749 | const TopoDS_Face& aFace = TopoDS::Face(theFaces(i)); |
750 | if (aFace.IsSame(theRefFace)) |
751 | continue; |
752 | |
753 | TransformPCurves(theRefFace, aFace, theMapEdgesWithTemporaryPCurves); |
754 | } |
755 | } |
756 | |
2277323d |
757 | //======================================================================= |
758 | //function : AddOrdinaryEdges |
759 | //purpose : auxilary |
760 | //======================================================================= |
761 | // adds edges from the shape to the sequence |
762 | // seams and equal edges are dropped |
763 | // Returns true if one of original edges dropped |
764 | static Standard_Boolean AddOrdinaryEdges(TopTools_SequenceOfShape& edges, |
765 | const TopoDS_Shape aShape, |
766 | Standard_Integer& anIndex) |
767 | { |
768 | //map of edges |
769 | TopTools_IndexedMapOfShape aNewEdges; |
770 | //add edges without seams |
771 | for(TopExp_Explorer exp(aShape,TopAbs_EDGE); exp.More(); exp.Next()) { |
772 | TopoDS_Shape edge = exp.Current(); |
773 | if(aNewEdges.Contains(edge)) |
3f5aa017 |
774 | aNewEdges.RemoveKey(edge); |
2277323d |
775 | else |
776 | aNewEdges.Add(edge); |
777 | } |
778 | |
779 | Standard_Boolean isDropped = Standard_False; |
780 | //merge edges and drop seams |
781 | Standard_Integer i; |
782 | for (i = 1; i <= edges.Length(); i++) { |
783 | TopoDS_Shape current = edges(i); |
784 | if(aNewEdges.Contains(current)) { |
785 | |
3f5aa017 |
786 | aNewEdges.RemoveKey(current); |
2277323d |
787 | edges.Remove(i); |
788 | i--; |
789 | |
790 | if(!isDropped) { |
791 | isDropped = Standard_True; |
792 | anIndex = i; |
793 | } |
794 | } |
795 | } |
796 | |
9ed6494b |
797 | //add edges to the sequence |
2277323d |
798 | for (i = 1; i <= aNewEdges.Extent(); i++) |
799 | edges.Append(aNewEdges(i)); |
800 | |
801 | return isDropped; |
802 | } |
803 | |
804 | //======================================================================= |
805 | //function : getCylinder |
806 | //purpose : auxilary |
807 | //======================================================================= |
808 | static Standard_Boolean getCylinder(Handle(Geom_Surface)& theInSurface, |
809 | gp_Cylinder& theOutCylinder) |
810 | { |
811 | Standard_Boolean isCylinder = Standard_False; |
812 | |
813 | if (theInSurface->IsKind(STANDARD_TYPE(Geom_CylindricalSurface))) { |
814 | Handle(Geom_CylindricalSurface) aGC = Handle(Geom_CylindricalSurface)::DownCast(theInSurface); |
815 | |
816 | theOutCylinder = aGC->Cylinder(); |
817 | isCylinder = Standard_True; |
818 | } |
819 | else if (theInSurface->IsKind(STANDARD_TYPE(Geom_SurfaceOfRevolution))) { |
820 | Handle(Geom_SurfaceOfRevolution) aRS = |
821 | Handle(Geom_SurfaceOfRevolution)::DownCast(theInSurface); |
822 | Handle(Geom_Curve) aBasis = aRS->BasisCurve(); |
823 | if (aBasis->IsKind(STANDARD_TYPE(Geom_Line))) { |
824 | Handle(Geom_Line) aBasisLine = Handle(Geom_Line)::DownCast(aBasis); |
825 | gp_Dir aDir = aRS->Direction(); |
826 | gp_Dir aBasisDir = aBasisLine->Position().Direction(); |
827 | if (aBasisDir.IsParallel(aDir, Precision::Angular())) { |
828 | // basis line is parallel to the revolution axis: it is a cylinder |
829 | gp_Pnt aLoc = aRS->Location(); |
830 | Standard_Real aR = aBasisLine->Lin().Distance(aLoc); |
831 | gp_Ax3 aCylAx (aLoc, aDir); |
832 | |
833 | theOutCylinder = gp_Cylinder(aCylAx, aR); |
834 | isCylinder = Standard_True; |
835 | } |
836 | } |
837 | } |
838 | else if (theInSurface->IsKind(STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion))) { |
839 | Handle(Geom_SurfaceOfLinearExtrusion) aLES = |
840 | Handle(Geom_SurfaceOfLinearExtrusion)::DownCast(theInSurface); |
841 | Handle(Geom_Curve) aBasis = aLES->BasisCurve(); |
842 | if (aBasis->IsKind(STANDARD_TYPE(Geom_Circle))) { |
843 | Handle(Geom_Circle) aBasisCircle = Handle(Geom_Circle)::DownCast(aBasis); |
844 | gp_Dir aDir = aLES->Direction(); |
845 | gp_Dir aBasisDir = aBasisCircle->Position().Direction(); |
846 | if (aBasisDir.IsParallel(aDir, Precision::Angular())) { |
847 | // basis circle is normal to the extrusion axis: it is a cylinder |
848 | gp_Pnt aLoc = aBasisCircle->Location(); |
849 | Standard_Real aR = aBasisCircle->Radius(); |
850 | gp_Ax3 aCylAx (aLoc, aDir); |
851 | |
852 | theOutCylinder = gp_Cylinder(aCylAx, aR); |
853 | isCylinder = Standard_True; |
854 | } |
855 | } |
856 | } |
857 | else { |
858 | } |
859 | |
860 | return isCylinder; |
861 | } |
862 | |
863 | //======================================================================= |
864 | //function : ClearRts |
865 | //purpose : auxilary |
866 | //======================================================================= |
867 | static Handle(Geom_Surface) ClearRts(const Handle(Geom_Surface)& aSurface) |
868 | { |
869 | if(aSurface->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) { |
870 | Handle(Geom_RectangularTrimmedSurface) rts = |
871 | Handle(Geom_RectangularTrimmedSurface)::DownCast(aSurface); |
872 | return rts->BasisSurface(); |
873 | } |
874 | return aSurface; |
875 | } |
876 | |
10ce3246 |
877 | //======================================================================= |
878 | //function : GetNormalToSurface |
879 | //purpose : Gets the normal to surface by the given parameter on edge. |
880 | // Returns True if normal was computed. |
881 | //======================================================================= |
882 | static Standard_Boolean GetNormalToSurface(const TopoDS_Face& theFace, |
883 | const TopoDS_Edge& theEdge, |
884 | const Standard_Real theP, |
885 | gp_Dir& theNormal) |
886 | { |
887 | Standard_Real f, l; |
888 | // get 2d curve to get point in 2d |
889 | const Handle(Geom2d_Curve)& aC2d = BRep_Tool::CurveOnSurface(theEdge, theFace, f, l); |
890 | if (aC2d.IsNull()) { |
891 | return Standard_False; |
892 | } |
893 | // |
894 | // 2d point |
895 | gp_Pnt2d aP2d; |
896 | aC2d->D0(theP, aP2d); |
897 | // |
898 | // get D1 |
899 | gp_Vec aDU, aDV; |
900 | gp_Pnt aP3d; |
901 | TopLoc_Location aLoc; |
902 | const Handle(Geom_Surface)& aS = BRep_Tool::Surface(theFace, aLoc); |
903 | aS->D1(aP2d.X(), aP2d.Y(), aP3d, aDU, aDV); |
904 | // |
905 | // compute normal |
906 | gp_Vec aVNormal = aDU.Crossed(aDV); |
907 | if (aVNormal.Magnitude() < Precision::Confusion()) { |
908 | return Standard_False; |
909 | } |
910 | // |
911 | if (theFace.Orientation() == TopAbs_REVERSED) { |
912 | aVNormal.Reverse(); |
913 | } |
914 | // |
915 | aVNormal.Transform(aLoc.Transformation()); |
916 | theNormal = gp_Dir(aVNormal); |
917 | return Standard_True; |
918 | } |
919 | |
2277323d |
920 | //======================================================================= |
921 | //function : IsSameDomain |
922 | //purpose : |
923 | //======================================================================= |
924 | static Standard_Boolean IsSameDomain(const TopoDS_Face& aFace, |
2ba9eb30 |
925 | const TopoDS_Face& aCheckedFace, |
926 | const Standard_Real theLinTol, |
927 | const Standard_Real theAngTol) |
2277323d |
928 | { |
929 | //checking the same handles |
930 | TopLoc_Location L1, L2; |
931 | Handle(Geom_Surface) S1, S2; |
932 | |
933 | S1 = BRep_Tool::Surface(aFace,L1); |
934 | S2 = BRep_Tool::Surface(aCheckedFace,L2); |
935 | |
936 | if (S1 == S2 && L1 == L2) |
937 | return Standard_True; |
938 | |
2277323d |
939 | S1 = BRep_Tool::Surface(aFace); |
940 | S2 = BRep_Tool::Surface(aCheckedFace); |
941 | |
942 | S1 = ClearRts(S1); |
943 | S2 = ClearRts(S2); |
944 | |
945 | //Handle(Geom_OffsetSurface) aGOFS1, aGOFS2; |
946 | //aGOFS1 = Handle(Geom_OffsetSurface)::DownCast(S1); |
947 | //aGOFS2 = Handle(Geom_OffsetSurface)::DownCast(S2); |
948 | //if (!aGOFS1.IsNull()) S1 = aGOFS1->BasisSurface(); |
949 | //if (!aGOFS2.IsNull()) S2 = aGOFS2->BasisSurface(); |
950 | |
2ba9eb30 |
951 | // case of two planar surfaces: |
952 | // all kinds of surfaces checked, including b-spline and bezier |
953 | GeomLib_IsPlanarSurface aPlanarityChecker1(S1, theLinTol); |
954 | if (aPlanarityChecker1.IsPlanar()) { |
955 | GeomLib_IsPlanarSurface aPlanarityChecker2(S2, theLinTol); |
956 | if (aPlanarityChecker2.IsPlanar()) { |
957 | gp_Pln aPln1 = aPlanarityChecker1.Plan(); |
958 | gp_Pln aPln2 = aPlanarityChecker2.Plan(); |
959 | |
960 | if (aPln1.Position().Direction().IsParallel(aPln2.Position().Direction(), theAngTol) && |
961 | aPln1.Distance(aPln2) < theLinTol) { |
962 | return Standard_True; |
963 | } |
964 | } |
965 | } |
966 | |
2277323d |
967 | // case of two elementary surfaces: use OCCT tool |
968 | // elementary surfaces: ConicalSurface, CylindricalSurface, |
969 | // Plane, SphericalSurface and ToroidalSurface |
970 | if (S1->IsKind(STANDARD_TYPE(Geom_ElementarySurface)) && |
971 | S2->IsKind(STANDARD_TYPE(Geom_ElementarySurface))) |
972 | { |
973 | Handle(GeomAdaptor_HSurface) aGA1 = new GeomAdaptor_HSurface(S1); |
974 | Handle(GeomAdaptor_HSurface) aGA2 = new GeomAdaptor_HSurface(S2); |
975 | |
976 | Handle(BRepTopAdaptor_TopolTool) aTT1 = new BRepTopAdaptor_TopolTool(); |
977 | Handle(BRepTopAdaptor_TopolTool) aTT2 = new BRepTopAdaptor_TopolTool(); |
978 | |
979 | try { |
2ba9eb30 |
980 | IntPatch_ImpImpIntersection anIIInt(aGA1, aTT1, aGA2, aTT2, theLinTol, theLinTol); |
2277323d |
981 | if (!anIIInt.IsDone() || anIIInt.IsEmpty()) |
982 | return Standard_False; |
983 | |
984 | return anIIInt.TangentFaces(); |
985 | } |
a738b534 |
986 | catch (Standard_Failure const&) { |
2277323d |
987 | return Standard_False; |
988 | } |
989 | } |
990 | |
2277323d |
991 | // case of two cylindrical surfaces, at least one of which is a swept surface |
992 | // swept surfaces: SurfaceOfLinearExtrusion, SurfaceOfRevolution |
993 | if ((S1->IsKind(STANDARD_TYPE(Geom_CylindricalSurface)) || |
994 | S1->IsKind(STANDARD_TYPE(Geom_SweptSurface))) && |
995 | (S2->IsKind(STANDARD_TYPE(Geom_CylindricalSurface)) || |
996 | S2->IsKind(STANDARD_TYPE(Geom_SweptSurface)))) |
997 | { |
998 | gp_Cylinder aCyl1, aCyl2; |
999 | if (getCylinder(S1, aCyl1) && getCylinder(S2, aCyl2)) { |
2ba9eb30 |
1000 | if (fabs(aCyl1.Radius() - aCyl2.Radius()) < theLinTol) { |
2277323d |
1001 | gp_Dir aDir1 = aCyl1.Position().Direction(); |
1002 | gp_Dir aDir2 = aCyl2.Position().Direction(); |
1003 | if (aDir1.IsParallel(aDir2, Precision::Angular())) { |
1004 | gp_Pnt aLoc1 = aCyl1.Location(); |
1005 | gp_Pnt aLoc2 = aCyl2.Location(); |
1006 | gp_Vec aVec12 (aLoc1, aLoc2); |
2ba9eb30 |
1007 | if (aVec12.SquareMagnitude() < theLinTol*theLinTol || |
2277323d |
1008 | aVec12.IsParallel(aDir1, Precision::Angular())) { |
1009 | return Standard_True; |
1010 | } |
1011 | } |
1012 | } |
1013 | } |
1014 | } |
1015 | |
1016 | return Standard_False; |
1017 | } |
1018 | |
632175c3 |
1019 | //======================================================================= |
1020 | //function : UpdateMapOfShapes |
1021 | //purpose : |
1022 | //======================================================================= |
1023 | static void UpdateMapOfShapes(TopTools_MapOfShape& theMapOfShapes, |
1024 | Handle(ShapeBuild_ReShape)& theContext) |
1025 | { |
1026 | for (TopTools_MapIteratorOfMapOfShape it(theMapOfShapes); it.More(); it.Next()) { |
1027 | const TopoDS_Shape& aShape = it.Value(); |
1028 | TopoDS_Shape aContextShape = theContext->Apply(aShape); |
1029 | if (!aContextShape.IsSame(aShape)) |
1030 | theMapOfShapes.Add(aContextShape); |
1031 | } |
1032 | } |
1033 | |
2277323d |
1034 | //======================================================================= |
1035 | //function : GlueEdgesWithPCurves |
1036 | //purpose : Glues the pcurves of the sequence of edges |
1037 | // and glues their 3d curves |
1038 | //======================================================================= |
1039 | static TopoDS_Edge GlueEdgesWithPCurves(const TopTools_SequenceOfShape& aChain, |
1040 | const TopoDS_Vertex& FirstVertex, |
1041 | const TopoDS_Vertex& LastVertex) |
1042 | { |
1043 | Standard_Integer i, j; |
1044 | |
1045 | TopoDS_Edge FirstEdge = TopoDS::Edge(aChain(1)); |
2277323d |
1046 | TColGeom_SequenceOfSurface SurfSeq; |
fbfdf61a |
1047 | NCollection_Sequence<TopLoc_Location> LocSeq; |
2277323d |
1048 | |
fbfdf61a |
1049 | for (int aCurveIndex = 0;; aCurveIndex++) |
2277323d |
1050 | { |
fbfdf61a |
1051 | Handle(Geom2d_Curve) aCurve; |
1052 | Handle(Geom_Surface) aSurface; |
1053 | TopLoc_Location aLocation; |
1054 | Standard_Real aFirst, aLast; |
1055 | BRep_Tool::CurveOnSurface (FirstEdge, aCurve, aSurface, aLocation, aFirst, aLast, aCurveIndex); |
1056 | if (aCurve.IsNull()) |
1057 | break; |
1058 | |
1059 | SurfSeq.Append(aSurface); |
1060 | LocSeq.Append(aLocation); |
2277323d |
1061 | } |
1062 | |
1063 | Standard_Real fpar, lpar; |
1064 | BRep_Tool::Range(FirstEdge, fpar, lpar); |
1065 | TopoDS_Edge PrevEdge = FirstEdge; |
1066 | TopoDS_Vertex CV; |
1067 | Standard_Real MaxTol = 0.; |
1068 | |
1069 | TopoDS_Edge ResEdge; |
1070 | BRep_Builder BB; |
1071 | |
1072 | Standard_Integer nb_curve = aChain.Length(); //number of curves |
1073 | TColGeom_Array1OfBSplineCurve tab_c3d(0,nb_curve-1); //array of the curves |
1074 | TColStd_Array1OfReal tabtolvertex(0,nb_curve-1); //(0,nb_curve-2); //array of the tolerances |
1075 | |
1076 | TopoDS_Vertex PrevVertex = FirstVertex; |
1077 | for (i = 1; i <= nb_curve; i++) |
1078 | { |
1079 | TopoDS_Edge anEdge = TopoDS::Edge(aChain(i)); |
1080 | TopoDS_Vertex VF, VL; |
1081 | TopExp::Vertices(anEdge, VF, VL); |
1082 | Standard_Boolean ToReverse = (!VF.IsSame(PrevVertex)); |
1083 | |
1084 | Standard_Real Tol1 = BRep_Tool::Tolerance(VF); |
1085 | Standard_Real Tol2 = BRep_Tool::Tolerance(VL); |
1086 | if (Tol1 > MaxTol) |
1087 | MaxTol = Tol1; |
1088 | if (Tol2 > MaxTol) |
1089 | MaxTol = Tol2; |
1090 | |
1091 | if (i > 1) |
1092 | { |
1093 | TopExp::CommonVertex(PrevEdge, anEdge, CV); |
1094 | Standard_Real Tol = BRep_Tool::Tolerance(CV); |
1095 | tabtolvertex(i-2) = Tol; |
1096 | } |
1097 | |
1098 | Handle(Geom_Curve) aCurve = BRep_Tool::Curve(anEdge, fpar, lpar); |
1099 | Handle(Geom_TrimmedCurve) aTrCurve = new Geom_TrimmedCurve(aCurve, fpar, lpar); |
1100 | tab_c3d(i-1) = GeomConvert::CurveToBSplineCurve(aTrCurve); |
1101 | GeomConvert::C0BSplineToC1BSplineCurve(tab_c3d(i-1), Precision::Confusion()); |
1102 | if (ToReverse) |
1103 | tab_c3d(i-1)->Reverse(); |
1104 | PrevVertex = (ToReverse)? VF : VL; |
1105 | PrevEdge = anEdge; |
1106 | } |
1107 | Handle(TColGeom_HArray1OfBSplineCurve) concatcurve; //array of the concatenated curves |
1108 | Handle(TColStd_HArray1OfInteger) ArrayOfIndices; //array of the remining Vertex |
4a361058 |
1109 | Standard_Boolean closed_flag = Standard_False; |
2277323d |
1110 | GeomConvert::ConcatC1(tab_c3d, |
1111 | tabtolvertex, |
1112 | ArrayOfIndices, |
1113 | concatcurve, |
4a361058 |
1114 | closed_flag, |
2277323d |
1115 | Precision::Confusion()); //C1 concatenation |
1116 | |
1117 | if (concatcurve->Length() > 1) |
1118 | { |
1119 | GeomConvert_CompCurveToBSplineCurve Concat(concatcurve->Value(concatcurve->Lower())); |
1120 | |
1121 | for (i = concatcurve->Lower()+1; i <= concatcurve->Upper(); i++) |
1122 | Concat.Add( concatcurve->Value(i), MaxTol, Standard_True ); |
1123 | |
1124 | concatcurve->SetValue(concatcurve->Lower(), Concat.BSplineCurve()); |
1125 | } |
1126 | Handle(Geom_BSplineCurve) ResCurve = concatcurve->Value(concatcurve->Lower()); |
1127 | |
1128 | TColGeom2d_SequenceOfBoundedCurve ResPCurves; |
2277323d |
1129 | for (j = 1; j <= SurfSeq.Length(); j++) |
1130 | { |
1131 | TColGeom2d_Array1OfBSplineCurve tab_c2d(0,nb_curve-1); //array of the pcurves |
1132 | |
1133 | PrevVertex = FirstVertex; |
1134 | PrevEdge = FirstEdge; |
2277323d |
1135 | for (i = 1; i <= nb_curve; i++) |
1136 | { |
1137 | TopoDS_Edge anEdge = TopoDS::Edge(aChain(i)); |
1138 | TopoDS_Vertex VF, VL; |
1139 | TopExp::Vertices(anEdge, VF, VL); |
1140 | Standard_Boolean ToReverse = (!VF.IsSame(PrevVertex)); |
1141 | |
2277323d |
1142 | Handle(Geom2d_Curve) aPCurve = |
fbfdf61a |
1143 | BRep_Tool::CurveOnSurface(anEdge, SurfSeq(j), LocSeq(j), fpar, lpar); |
1144 | if (aPCurve.IsNull()) |
1145 | continue; |
2277323d |
1146 | Handle(Geom2d_TrimmedCurve) aTrPCurve = new Geom2d_TrimmedCurve(aPCurve, fpar, lpar); |
1147 | tab_c2d(i-1) = Geom2dConvert::CurveToBSplineCurve(aTrPCurve); |
1148 | Geom2dConvert::C0BSplineToC1BSplineCurve(tab_c2d(i-1), Precision::Confusion()); |
1149 | if (ToReverse) |
1150 | tab_c2d(i-1)->Reverse(); |
1151 | PrevVertex = (ToReverse)? VF : VL; |
1152 | PrevEdge = anEdge; |
1153 | } |
1154 | Handle(TColGeom2d_HArray1OfBSplineCurve) concatc2d; //array of the concatenated curves |
1155 | Handle(TColStd_HArray1OfInteger) ArrayOfInd2d; //array of the remining Vertex |
4a361058 |
1156 | closed_flag = Standard_False; |
2277323d |
1157 | Geom2dConvert::ConcatC1(tab_c2d, |
1158 | tabtolvertex, |
1159 | ArrayOfInd2d, |
1160 | concatc2d, |
4a361058 |
1161 | closed_flag, |
2277323d |
1162 | Precision::Confusion()); //C1 concatenation |
1163 | |
1164 | if (concatc2d->Length() > 1) |
1165 | { |
1166 | Geom2dConvert_CompCurveToBSplineCurve Concat2d(concatc2d->Value(concatc2d->Lower())); |
1167 | |
1168 | for (i = concatc2d->Lower()+1; i <= concatc2d->Upper(); i++) |
1169 | Concat2d.Add( concatc2d->Value(i), MaxTol, Standard_True ); |
1170 | |
1171 | concatc2d->SetValue(concatc2d->Lower(), Concat2d.BSplineCurve()); |
1172 | } |
1173 | Handle(Geom2d_BSplineCurve) aResPCurve = concatc2d->Value(concatc2d->Lower()); |
1174 | ResPCurves.Append(aResPCurve); |
1175 | } |
1176 | |
1177 | ResEdge = BRepLib_MakeEdge(ResCurve, |
1178 | FirstVertex, LastVertex, |
1179 | ResCurve->FirstParameter(), ResCurve->LastParameter()); |
1180 | BB.SameRange(ResEdge, Standard_False); |
1181 | BB.SameParameter(ResEdge, Standard_False); |
1182 | for (j = 1; j <= ResPCurves.Length(); j++) |
1183 | { |
fbfdf61a |
1184 | BB.UpdateEdge(ResEdge, ResPCurves(j), SurfSeq(j), LocSeq(j), MaxTol); |
1185 | BB.Range(ResEdge, SurfSeq(j), LocSeq(j), ResPCurves(j)->FirstParameter(), ResPCurves(j)->LastParameter()); |
2277323d |
1186 | } |
1187 | |
1188 | BRepLib::SameParameter(ResEdge, MaxTol, Standard_True); |
1189 | |
1190 | return ResEdge; |
1191 | } |
1192 | |
cef6867c |
1193 | //======================================================================= |
1194 | //function : MergeSubSeq |
1195 | //purpose : Merges a sequence of edges into one edge if possible |
1196 | //======================================================================= |
1197 | |
389b9d5c |
1198 | static Standard_Boolean MergeSubSeq(const TopTools_SequenceOfShape& theChain, |
1199 | const TopTools_IndexedDataMapOfShapeListOfShape& theVFmap, |
632175c3 |
1200 | TopoDS_Edge& OutEdge, |
1201 | double theAngTol, |
1202 | Standard_Boolean ConcatBSplines, |
1203 | Standard_Boolean isSafeInputMode, |
1204 | Handle(ShapeBuild_ReShape)& theContext) |
2277323d |
1205 | { |
2277323d |
1206 | ShapeAnalysis_Edge sae; |
f7d70540 |
1207 | BRep_Builder B; |
2277323d |
1208 | // union edges in chain |
f7d70540 |
1209 | int j; |
2277323d |
1210 | Standard_Real fp1,lp1,fp2,lp2; |
f7d70540 |
1211 | Standard_Boolean IsUnionOfLinesPossible = Standard_True; |
1212 | Standard_Boolean IsUnionOfCirclesPossible = Standard_True; |
1213 | Handle(Geom_Curve) c3d1, c3d2; |
389b9d5c |
1214 | for(j = 1; j < theChain.Length(); j++) |
f7d70540 |
1215 | { |
389b9d5c |
1216 | TopoDS_Edge edge1 = TopoDS::Edge(theChain.Value(j)); |
1217 | TopoDS_Edge edge2 = TopoDS::Edge(theChain.Value(j+1)); |
f7d70540 |
1218 | |
389b9d5c |
1219 | if (BRep_Tool::Degenerated(edge1) && |
1220 | BRep_Tool::Degenerated(edge2)) |
1221 | { |
1222 | //Find the closest points in 2d |
1223 | TopoDS_Edge edgeFirst = TopoDS::Edge(theChain.First()); |
1224 | TopoDS_Edge edgeLast = TopoDS::Edge(theChain.Last()); |
1225 | TopoDS_Face CommonFace; |
1226 | Standard_Real MinSqDist; |
1227 | TopAbs_Orientation OrOfE1OnFace, OrOfE2OnFace; |
1228 | Standard_Integer IndOnE1, IndOnE2; |
1229 | gp_Pnt2d PointsOnEdge1 [2], PointsOnEdge2 [2]; |
1230 | if (!FindClosestPoints(edgeFirst, edgeLast, theVFmap, CommonFace, |
1231 | MinSqDist, OrOfE1OnFace, OrOfE2OnFace, |
1232 | IndOnE1, IndOnE2, PointsOnEdge1, PointsOnEdge2)) |
1233 | return Standard_False; |
1234 | |
1235 | //Define indices corresponding to extremities of future edge |
1236 | IndOnE1 = 1 - IndOnE1; |
1237 | IndOnE2 = 1 - IndOnE2; |
1238 | |
1239 | //Construct new degenerated edge |
1240 | gp_Pnt2d StartPoint = PointsOnEdge1[IndOnE1]; |
1241 | gp_Pnt2d EndPoint = PointsOnEdge2[IndOnE2]; |
1242 | if ((OrOfE1OnFace == TopAbs_FORWARD && IndOnE1 == 1) || |
1243 | (OrOfE1OnFace == TopAbs_REVERSED && IndOnE1 == 0)) |
1244 | { gp_Pnt2d Tmp = StartPoint; StartPoint = EndPoint; EndPoint = Tmp; } |
1245 | |
1246 | Handle(Geom2d_Line) aLine = GCE2d_MakeLine(StartPoint, EndPoint); |
1247 | |
1248 | TopoDS_Vertex aVertex = TopExp::FirstVertex(edgeFirst); |
1249 | TopoDS_Vertex StartVertex = aVertex, EndVertex = aVertex; |
1250 | StartVertex.Orientation(TopAbs_FORWARD); |
1251 | EndVertex.Orientation(TopAbs_REVERSED); |
1252 | |
1253 | TopoDS_Edge NewEdge; |
1254 | B.MakeEdge(NewEdge); |
1255 | B.UpdateEdge(NewEdge, aLine, CommonFace, Precision::Confusion()); |
1256 | B.Range(NewEdge, 0., StartPoint.Distance(EndPoint)); |
1257 | B.Add (NewEdge, StartVertex); |
1258 | B.Add (NewEdge, EndVertex); |
1259 | B.Degenerated(NewEdge, Standard_True); |
1260 | OutEdge = NewEdge; |
1261 | return Standard_True; |
1262 | } |
1263 | |
1264 | c3d1 = BRep_Tool::Curve(edge1,fp1,lp1); |
f7d70540 |
1265 | c3d2 = BRep_Tool::Curve(edge2,fp2,lp2); |
1266 | |
1267 | if(c3d1.IsNull() || c3d2.IsNull()) |
1268 | return Standard_False; |
b4d4dbe8 |
1269 | |
2277323d |
1270 | while(c3d1->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) { |
1271 | Handle(Geom_TrimmedCurve) tc = |
1272 | Handle(Geom_TrimmedCurve)::DownCast(c3d1); |
1273 | c3d1 = tc->BasisCurve(); |
1274 | } |
2277323d |
1275 | while(c3d2->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) { |
1276 | Handle(Geom_TrimmedCurve) tc = |
1277 | Handle(Geom_TrimmedCurve)::DownCast(c3d2); |
1278 | c3d2 = tc->BasisCurve(); |
1279 | } |
1280 | if( c3d1->IsKind(STANDARD_TYPE(Geom_Line)) && c3d2->IsKind(STANDARD_TYPE(Geom_Line)) ) { |
2277323d |
1281 | Handle(Geom_Line) L1 = Handle(Geom_Line)::DownCast(c3d1); |
1282 | Handle(Geom_Line) L2 = Handle(Geom_Line)::DownCast(c3d2); |
1283 | gp_Dir Dir1 = L1->Position().Direction(); |
1284 | gp_Dir Dir2 = L2->Position().Direction(); |
632175c3 |
1285 | if(!Dir1.IsParallel(Dir2,theAngTol)) |
f7d70540 |
1286 | IsUnionOfLinesPossible = Standard_False; |
2277323d |
1287 | } |
f7d70540 |
1288 | else |
1289 | IsUnionOfLinesPossible = Standard_False; |
2277323d |
1290 | if( c3d1->IsKind(STANDARD_TYPE(Geom_Circle)) && c3d2->IsKind(STANDARD_TYPE(Geom_Circle)) ) { |
2277323d |
1291 | Handle(Geom_Circle) C1 = Handle(Geom_Circle)::DownCast(c3d1); |
1292 | Handle(Geom_Circle) C2 = Handle(Geom_Circle)::DownCast(c3d2); |
1293 | gp_Pnt P01 = C1->Location(); |
1294 | gp_Pnt P02 = C2->Location(); |
b4d4dbe8 |
1295 | if (P01.Distance(P02) > Precision::Confusion()) |
f7d70540 |
1296 | IsUnionOfCirclesPossible = Standard_False; |
1297 | } |
1298 | else |
1299 | IsUnionOfCirclesPossible = Standard_False; |
1300 | } |
1301 | if (IsUnionOfLinesPossible && IsUnionOfCirclesPossible) |
1302 | return Standard_False; |
1303 | |
1304 | //union of lines is possible |
1305 | if (IsUnionOfLinesPossible) |
1306 | { |
632175c3 |
1307 | TopoDS_Vertex V[2]; |
389b9d5c |
1308 | V[0] = sae.FirstVertex(TopoDS::Edge(theChain.First())); |
632175c3 |
1309 | gp_Pnt PV1 = BRep_Tool::Pnt(V[0]); |
389b9d5c |
1310 | V[1] = sae.LastVertex(TopoDS::Edge(theChain.Last())); |
632175c3 |
1311 | gp_Pnt PV2 = BRep_Tool::Pnt(V[1]); |
f7d70540 |
1312 | gp_Vec Vec(PV1, PV2); |
632175c3 |
1313 | if (isSafeInputMode) { |
1314 | for (int k = 0; k < 2; k++) { |
1315 | if (!theContext->IsRecorded(V[k])) { |
1316 | TopoDS_Vertex Vcopy = TopoDS::Vertex(V[k].EmptyCopied()); |
1317 | theContext->Replace(V[k], Vcopy); |
1318 | V[k] = Vcopy; |
1319 | } |
1320 | else |
1321 | V[k] = TopoDS::Vertex(theContext->Apply(V[k])); |
1322 | } |
1323 | } |
f7d70540 |
1324 | Handle(Geom_Line) L = new Geom_Line(gp_Ax1(PV1,Vec)); |
1325 | Standard_Real dist = PV1.Distance(PV2); |
1326 | Handle(Geom_TrimmedCurve) tc = new Geom_TrimmedCurve(L,0.0,dist); |
1327 | TopoDS_Edge E; |
1328 | B.MakeEdge (E, tc ,Precision::Confusion()); |
632175c3 |
1329 | B.Add (E,V[0]); B.Add (E,V[1]); |
1330 | B.UpdateVertex(V[0], 0., E, 0.); |
1331 | B.UpdateVertex(V[1], dist, E, 0.); |
f7d70540 |
1332 | OutEdge = E; |
1333 | return Standard_True; |
1334 | } |
1335 | |
1336 | if (IsUnionOfCirclesPossible) |
1337 | { |
1338 | double f,l; |
389b9d5c |
1339 | TopoDS_Edge FE = TopoDS::Edge(theChain.First()); |
f7d70540 |
1340 | Handle(Geom_Curve) c3d = BRep_Tool::Curve(FE,f,l); |
1341 | |
1342 | while(c3d->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) { |
1343 | Handle(Geom_TrimmedCurve) tc = |
1344 | Handle(Geom_TrimmedCurve)::DownCast(c3d); |
1345 | c3d = tc->BasisCurve(); |
1346 | } |
1347 | Handle(Geom_Circle) Cir = Handle(Geom_Circle)::DownCast(c3d); |
1348 | |
632175c3 |
1349 | TopoDS_Vertex V[2]; |
1350 | V[0] = sae.FirstVertex(FE); |
389b9d5c |
1351 | V[1] = sae.LastVertex(TopoDS::Edge(theChain.Last())); |
f7d70540 |
1352 | TopoDS_Edge E; |
632175c3 |
1353 | if (V[0].IsSame(V[1])) { |
f7d70540 |
1354 | // closed chain |
dd2f1b75 |
1355 | BRepAdaptor_Curve adef(FE); |
1356 | Handle(Geom_Circle) Cir1; |
1357 | double FP, LP; |
1358 | if ( FE.Orientation() == TopAbs_FORWARD) |
1359 | { |
1360 | FP = adef.FirstParameter(); |
1361 | LP = adef.LastParameter(); |
1362 | } |
1363 | else |
1364 | { |
1365 | FP = adef.LastParameter(); |
1366 | LP = adef.FirstParameter(); |
1367 | } |
1368 | if (Abs(FP) < Precision::PConfusion()) |
1369 | { |
f0144633 |
1370 | B.MakeEdge (E,Cir, Precision::Confusion()); |
632175c3 |
1371 | B.Add(E,V[0]); |
1372 | B.Add(E,V[1]); |
f0144633 |
1373 | E.Orientation(FE.Orientation()); |
1374 | } |
dd2f1b75 |
1375 | else |
1376 | { |
1377 | GC_MakeCircle MC1 (adef.Value(FP), adef.Value((FP + LP) * 0.5), adef.Value(LP)); |
1378 | if (MC1.IsDone()) |
1379 | Cir1 = MC1.Value(); |
1380 | else |
1381 | return Standard_False; |
1382 | B.MakeEdge (E, Cir1, Precision::Confusion()); |
632175c3 |
1383 | B.Add(E,V[0]); |
1384 | B.Add(E,V[1]); |
dd2f1b75 |
1385 | } |
f7d70540 |
1386 | } |
1387 | else { |
632175c3 |
1388 | if (isSafeInputMode) { |
1389 | for (int k = 0; k < 2; k++) { |
1390 | if (!theContext->IsRecorded(V[k])) { |
1391 | TopoDS_Vertex Vcopy = TopoDS::Vertex(V[k].EmptyCopied()); |
1392 | theContext->Replace(V[k], Vcopy); |
1393 | V[k] = Vcopy; |
1394 | } |
1395 | else |
1396 | V[k] = TopoDS::Vertex(theContext->Apply(V[k])); |
1397 | } |
1398 | } |
1399 | gp_Pnt PV1 = BRep_Tool::Pnt(V[0]); |
1400 | gp_Pnt PV2 = BRep_Tool::Pnt(V[1]); |
dd2f1b75 |
1401 | TopoDS_Vertex VM = sae.LastVertex(FE); |
1402 | gp_Pnt PVM = BRep_Tool::Pnt(VM); |
1403 | GC_MakeCircle MC (PV1,PVM,PV2); |
f7d70540 |
1404 | Handle(Geom_Circle) C = MC.Value(); |
1405 | gp_Pnt P0 = C->Location(); |
1406 | gp_Dir D1(gp_Vec(P0,PV1)); |
1407 | gp_Dir D2(gp_Vec(P0,PV2)); |
1408 | Standard_Real fpar = C->XAxis().Direction().Angle(D1); |
1409 | if(fabs(fpar)>Precision::Confusion()) { |
1410 | // check orientation |
1411 | gp_Dir ND = C->XAxis().Direction().Crossed(D1); |
1412 | if(ND.IsOpposite(C->Axis().Direction(),Precision::Confusion())) { |
1413 | fpar = -fpar; |
2277323d |
1414 | } |
f7d70540 |
1415 | } |
1416 | Standard_Real lpar = C->XAxis().Direction().Angle(D2); |
1417 | if(fabs(lpar)>Precision::Confusion()) { |
1418 | // check orientation |
1419 | gp_Dir ND = C->XAxis().Direction().Crossed(D2); |
1420 | if(ND.IsOpposite(C->Axis().Direction(),Precision::Confusion())) { |
1421 | lpar = -lpar; |
2277323d |
1422 | } |
2277323d |
1423 | } |
f7d70540 |
1424 | if (lpar < fpar) lpar += 2*M_PI; |
1425 | Handle(Geom_TrimmedCurve) tc = new Geom_TrimmedCurve(C,fpar,lpar); |
1426 | B.MakeEdge (E,tc,Precision::Confusion()); |
632175c3 |
1427 | B.Add(E,V[0]); |
1428 | B.Add(E,V[1]); |
1429 | B.UpdateVertex(V[0], fpar, E, 0.); |
1430 | B.UpdateVertex(V[1], lpar, E, 0.); |
2277323d |
1431 | } |
f7d70540 |
1432 | OutEdge = E; |
1433 | return Standard_True; |
2277323d |
1434 | } |
389b9d5c |
1435 | if (theChain.Length() > 1 && ConcatBSplines) { |
2277323d |
1436 | // second step: union edges with various curves |
1437 | // skl for bug 0020052 from Mantis: perform such unions |
1438 | // only if curves are bspline or bezier |
f7d70540 |
1439 | |
389b9d5c |
1440 | TopoDS_Vertex VF = sae.FirstVertex(TopoDS::Edge(theChain.First())); |
1441 | TopoDS_Vertex VL = sae.LastVertex(TopoDS::Edge(theChain.Last())); |
f7d70540 |
1442 | Standard_Boolean NeedUnion = Standard_True; |
389b9d5c |
1443 | for(j = 1; j <= theChain.Length(); j++) { |
1444 | TopoDS_Edge edge = TopoDS::Edge(theChain.Value(j)); |
b4d4dbe8 |
1445 | TopLoc_Location Loc; |
2277323d |
1446 | Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge,Loc,fp1,lp1); |
1447 | if(c3d.IsNull()) continue; |
1448 | while(c3d->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) { |
1449 | Handle(Geom_TrimmedCurve) tc = |
1450 | Handle(Geom_TrimmedCurve)::DownCast(c3d); |
1451 | c3d = tc->BasisCurve(); |
1452 | } |
1453 | if( ( c3d->IsKind(STANDARD_TYPE(Geom_BSplineCurve)) || |
1454 | c3d->IsKind(STANDARD_TYPE(Geom_BezierCurve)) ) ) continue; |
f7d70540 |
1455 | NeedUnion = Standard_False; |
2277323d |
1456 | break; |
1457 | } |
1458 | if(NeedUnion) { |
0797d9d3 |
1459 | #ifdef OCCT_DEBUG |
04232180 |
1460 | std::cout<<"can not make analitical union => make approximation"<<std::endl; |
2277323d |
1461 | #endif |
389b9d5c |
1462 | TopoDS_Edge E = GlueEdgesWithPCurves(theChain, VF, VL); |
f7d70540 |
1463 | OutEdge = E; |
1464 | return Standard_True; |
2277323d |
1465 | } |
1466 | else { |
0797d9d3 |
1467 | #ifdef OCCT_DEBUG |
04232180 |
1468 | std::cout<<"can not make approximation for such types of curves"<<std::endl; |
2277323d |
1469 | #endif |
1470 | return Standard_False; |
1471 | } |
1472 | } |
f7d70540 |
1473 | return Standard_False; |
1474 | } |
1475 | |
cef6867c |
1476 | //======================================================================= |
1477 | //function : IsMergingPossible |
1478 | //purpose : Checks if merging of two edges is possible |
1479 | //======================================================================= |
1480 | |
f7d70540 |
1481 | static Standard_Boolean IsMergingPossible(const TopoDS_Edge& edge1, const TopoDS_Edge& edge2, |
1f59dfa9 |
1482 | double theAngTol, double theLinTol, |
1483 | const TopTools_MapOfShape& AvoidEdgeVrt, const bool theLineDirectionOk, |
389b9d5c |
1484 | const gp_Pnt& theFirstPoint, const gp_Vec& theDirectionVec, |
1485 | const TopTools_IndexedDataMapOfShapeListOfShape& theVFmap) |
f7d70540 |
1486 | { |
389b9d5c |
1487 | Standard_Boolean IsDegE1 = BRep_Tool::Degenerated(edge1); |
1488 | Standard_Boolean IsDegE2 = BRep_Tool::Degenerated(edge2); |
1489 | |
1490 | if (IsDegE1 && IsDegE2) |
1491 | { |
1492 | //Find connstion point in 2d |
1493 | TopoDS_Face CommonFace; |
1494 | Standard_Real MinSqDist; |
1495 | TopAbs_Orientation OrOfE1OnFace, OrOfE2OnFace; |
1496 | Standard_Integer IndOnE1, IndOnE2; |
1497 | gp_Pnt2d PointsOnEdge1 [2], PointsOnEdge2 [2]; |
1498 | if (!FindClosestPoints(edge1, edge2, theVFmap, CommonFace, |
1499 | MinSqDist, OrOfE1OnFace, OrOfE2OnFace, |
1500 | IndOnE1, IndOnE2, PointsOnEdge1, PointsOnEdge2)) |
1501 | return Standard_False; |
1502 | |
1503 | if (MinSqDist <= Precision::SquareConfusion()) |
1504 | return Standard_True; |
1505 | |
1506 | return Standard_False; |
1507 | } |
1508 | else if (IsDegE1 || IsDegE2) |
1509 | return Standard_False; |
1510 | |
f7d70540 |
1511 | TopoDS_Vertex CV = TopExp::LastVertex(edge1, Standard_True); |
9ed6494b |
1512 | if (CV.IsNull() || AvoidEdgeVrt.Contains(CV)) |
f7d70540 |
1513 | return Standard_False; |
1514 | |
1515 | BRepAdaptor_Curve ade1(edge1); |
1516 | BRepAdaptor_Curve ade2(edge2); |
1517 | |
1518 | GeomAbs_CurveType t1 = ade1.GetType(); |
1519 | GeomAbs_CurveType t2 = ade2.GetType(); |
1520 | |
1521 | if( t1 == GeomAbs_Circle && t2 == GeomAbs_Circle) |
1522 | { |
1523 | if (ade1.Circle().Location().Distance(ade2.Circle().Location()) > Precision::Confusion()) |
1524 | return Standard_False; |
1525 | } |
1526 | |
1527 | if( ( (t1 != GeomAbs_BezierCurve && t1 != GeomAbs_BSplineCurve) || |
1528 | (t2 != GeomAbs_BezierCurve && t2 != GeomAbs_BSplineCurve)) && t1 != t2) |
1529 | return Standard_False; |
1530 | |
1531 | gp_Vec Diff1, Diff2; |
1532 | gp_Pnt P1, P2; |
1533 | if (edge1.Orientation() == TopAbs_FORWARD) |
1534 | ade1.D1(ade1.LastParameter(), P1, Diff1); |
1535 | else |
1536 | { |
1537 | ade1.D1(ade1.FirstParameter(), P1, Diff1); |
1538 | Diff1 = -Diff1; |
1539 | } |
1540 | |
1541 | if (edge2.Orientation() == TopAbs_FORWARD) |
1542 | ade2.D1(ade2.FirstParameter(), P2, Diff2); |
1543 | else |
1544 | { |
1545 | ade2.D1(ade2.LastParameter(), P2, Diff2); |
1546 | Diff2 = -Diff2; |
1547 | } |
1548 | |
632175c3 |
1549 | if (Diff1.Angle(Diff2) > theAngTol) |
f7d70540 |
1550 | return Standard_False; |
1551 | |
1f59dfa9 |
1552 | if (theLineDirectionOk && t2 == GeomAbs_Line) |
1553 | { |
cf12784f |
1554 | // Check that the accumulated deflection does not exceed the linear tolerance |
06084bb8 |
1555 | Standard_Real aLast = (edge2.Orientation() == TopAbs_FORWARD) ? |
1556 | ade2.LastParameter() : ade2.FirstParameter(); |
1557 | gp_Vec aCurV(theFirstPoint, ade2.Value(aLast)); |
1f59dfa9 |
1558 | Standard_Real aDD = theDirectionVec.CrossSquareMagnitude(aCurV); |
1559 | if (aDD > theLinTol*theLinTol) |
1560 | return Standard_False; |
cf12784f |
1561 | |
1562 | // Check that the accumulated angle does not exceed the angular tolerance. |
1563 | // For symmetry, check the angle between vectors of: |
1564 | // - first edge and resulting curve, and |
1565 | // - the last edge and resulting curve. |
1566 | if (theDirectionVec.Angle(aCurV) > theAngTol || Diff2.Angle(aCurV) > theAngTol) |
1567 | return Standard_False; |
1f59dfa9 |
1568 | } |
1569 | |
1570 | return Standard_True; |
1571 | } |
1572 | |
1573 | //======================================================================= |
1574 | //function : GetLineEdgePoints |
1575 | //purpose : |
1576 | //======================================================================= |
1577 | static Standard_Boolean GetLineEdgePoints(const TopoDS_Edge& theInpEdge, gp_Pnt& theFirstPoint, gp_Vec& theDirectionVec) |
1578 | { |
1579 | double f, l; |
1580 | Handle(Geom_Curve) aCur = BRep_Tool::Curve(theInpEdge, f, l); |
1581 | if(aCur.IsNull()) |
1582 | return Standard_False; |
1583 | |
1584 | Handle(Geom_TrimmedCurve) aTC = Handle(Geom_TrimmedCurve)::DownCast(aCur); |
1585 | if (!aTC.IsNull()) |
1586 | aCur = aTC->BasisCurve(); |
1587 | |
1588 | if (aCur->DynamicType() != STANDARD_TYPE(Geom_Line)) |
1589 | return Standard_False; |
1590 | |
06084bb8 |
1591 | if (theInpEdge.Orientation() == TopAbs_REVERSED) { |
1592 | Standard_Real tmp = f; |
1593 | f = l; |
1594 | l = tmp; |
1595 | } |
1596 | theFirstPoint = aCur->Value(f); |
1597 | gp_Pnt aLP = aCur->Value(l); |
1f59dfa9 |
1598 | theDirectionVec = aLP.XYZ().Subtracted(theFirstPoint.XYZ()); |
1599 | theDirectionVec.Normalize(); |
f7d70540 |
1600 | return Standard_True; |
1601 | } |
1602 | |
cef6867c |
1603 | //======================================================================= |
1604 | //function : GenerateSubSeq |
1605 | //purpose : Generates sub-sequences of edges from sequence of edges |
1606 | //Edges from each subsequences can be merged into the one edge |
1607 | //======================================================================= |
1608 | |
f7d70540 |
1609 | static void GenerateSubSeq (const TopTools_SequenceOfShape& anInpEdgeSeq, |
1610 | NCollection_Sequence<SubSequenceOfEdges>& SeqOfSubSeqOfEdges, |
1f59dfa9 |
1611 | Standard_Boolean IsClosed, double theAngTol, double theLinTol, |
389b9d5c |
1612 | const TopTools_MapOfShape& AvoidEdgeVrt, |
1613 | const TopTools_IndexedDataMapOfShapeListOfShape& theVFmap) |
f7d70540 |
1614 | { |
1615 | Standard_Boolean isOk = Standard_False; |
1616 | TopoDS_Edge edge1, edge2; |
1617 | |
1618 | SubSequenceOfEdges SubSeq; |
1f59dfa9 |
1619 | TopoDS_Edge RefEdge = TopoDS::Edge(anInpEdgeSeq(1)); |
1620 | SubSeq.SeqsEdges.Append(RefEdge); |
f7d70540 |
1621 | SeqOfSubSeqOfEdges.Append(SubSeq); |
1622 | |
1f59dfa9 |
1623 | gp_Pnt aFirstPoint; |
1624 | gp_Vec aDirectionVec; |
1625 | Standard_Boolean isLineDirectionOk = GetLineEdgePoints(RefEdge, aFirstPoint, aDirectionVec); |
1626 | |
f7d70540 |
1627 | for (int i = 1; i < anInpEdgeSeq.Length(); i++) |
1628 | { |
1629 | edge1 = TopoDS::Edge(anInpEdgeSeq(i)); |
1630 | edge2 = TopoDS::Edge(anInpEdgeSeq(i+1)); |
389b9d5c |
1631 | isOk = IsMergingPossible(edge1, edge2, theAngTol, theLinTol, |
1632 | AvoidEdgeVrt, isLineDirectionOk, aFirstPoint, aDirectionVec, theVFmap); |
f7d70540 |
1633 | if (!isOk) |
1634 | { |
51740958 |
1635 | SubSequenceOfEdges aSubSeq; |
1636 | aSubSeq.SeqsEdges.Append(edge2); |
1637 | SeqOfSubSeqOfEdges.Append(aSubSeq); |
1f59dfa9 |
1638 | isLineDirectionOk = GetLineEdgePoints(edge2, aFirstPoint, aDirectionVec); |
f7d70540 |
1639 | } |
1640 | else |
1641 | SeqOfSubSeqOfEdges.ChangeLast().SeqsEdges.Append(edge2); |
1642 | } |
1643 | /// check first and last chain segments |
1644 | if (IsClosed && SeqOfSubSeqOfEdges.Length() > 1) |
1645 | { |
1646 | edge1 = TopoDS::Edge(anInpEdgeSeq.Last()); |
1647 | edge2 = TopoDS::Edge(anInpEdgeSeq.First()); |
389b9d5c |
1648 | if (IsMergingPossible(edge1, edge2, theAngTol, theLinTol, |
1649 | AvoidEdgeVrt, Standard_False, aFirstPoint, aDirectionVec, theVFmap)) |
f7d70540 |
1650 | { |
1651 | SeqOfSubSeqOfEdges.ChangeLast().SeqsEdges.Append(SeqOfSubSeqOfEdges.ChangeFirst().SeqsEdges); |
1652 | SeqOfSubSeqOfEdges.Remove(1); |
1653 | } |
1654 | } |
1655 | } |
1656 | |
f7d70540 |
1657 | //======================================================================= |
1658 | //function : MergeEdges |
1659 | //purpose : auxilary |
1660 | //======================================================================= |
f98965d2 |
1661 | static Standard_Boolean MergeEdges(TopTools_SequenceOfShape& SeqEdges, |
389b9d5c |
1662 | const TopTools_IndexedDataMapOfShapeListOfShape& theVFmap, |
632175c3 |
1663 | const Standard_Real theAngTol, |
1f59dfa9 |
1664 | const Standard_Real theLinTol, |
f7d70540 |
1665 | const Standard_Boolean ConcatBSplines, |
632175c3 |
1666 | const Standard_Boolean isSafeInputMode, |
1667 | Handle(ShapeBuild_ReShape)& theContext, |
f7d70540 |
1668 | NCollection_Sequence<SubSequenceOfEdges>& SeqOfSubSeqOfEdges, |
9ed6494b |
1669 | const TopTools_MapOfShape& NonMergVrt) |
f7d70540 |
1670 | { |
f98965d2 |
1671 | TopTools_IndexedDataMapOfShapeListOfShape aMapVE; |
f7d70540 |
1672 | Standard_Integer j; |
1673 | TopTools_MapOfShape VerticesToAvoid; |
fb64d0f4 |
1674 | const Standard_Integer aNbE = SeqEdges.Length(); |
1675 | for (j = 1; j <= aNbE; j++) |
f7d70540 |
1676 | { |
1677 | TopoDS_Edge anEdge = TopoDS::Edge(SeqEdges(j)); |
389b9d5c |
1678 | // fill in the map V-E |
1679 | for (TopoDS_Iterator it(anEdge.Oriented(TopAbs_FORWARD)); it.More(); it.Next()) |
f7d70540 |
1680 | { |
389b9d5c |
1681 | TopoDS_Shape aV = it.Value(); |
1682 | if (aV.Orientation() == TopAbs_FORWARD || aV.Orientation() == TopAbs_REVERSED) |
f98965d2 |
1683 | { |
389b9d5c |
1684 | if (!aMapVE.Contains(aV)) |
1685 | aMapVE.Add(aV, TopTools_ListOfShape()); |
1686 | aMapVE.ChangeFromKey(aV).Append(anEdge); |
f98965d2 |
1687 | } |
f7d70540 |
1688 | } |
f7d70540 |
1689 | } |
f98965d2 |
1690 | VerticesToAvoid.Unite(NonMergVrt); |
f7d70540 |
1691 | |
f98965d2 |
1692 | // do loop while there are unused edges |
1693 | TopTools_MapOfShape aUsedEdges; |
fb64d0f4 |
1694 | |
1695 | for (Standard_Integer iE = 1; iE <= aNbE; ++iE) |
f98965d2 |
1696 | { |
fb64d0f4 |
1697 | TopoDS_Edge edge = TopoDS::Edge (SeqEdges (iE)); |
1698 | if (!aUsedEdges.Add (edge)) |
1699 | continue; |
f98965d2 |
1700 | |
1701 | // make chain for unite |
1702 | TopTools_SequenceOfShape aChain; |
38c2acd4 |
1703 | aChain.Append(edge); |
f98965d2 |
1704 | TopoDS_Vertex V[2]; |
1705 | TopExp::Vertices(edge, V[0], V[1], Standard_True); |
1706 | |
1707 | // connect more edges to the chain in both directions |
1708 | for (j = 0; j < 2; j++) |
1709 | { |
1710 | Standard_Boolean isAdded = Standard_True; |
1711 | while (isAdded) |
1712 | { |
1713 | isAdded = Standard_False; |
1714 | if (V[j].IsNull()) |
1715 | break; |
1716 | const TopTools_ListOfShape& aLE = aMapVE.FindFromKey(V[j]); |
1717 | for (TopTools_ListIteratorOfListOfShape itL(aLE); itL.More(); itL.Next()) |
1718 | { |
1719 | edge = TopoDS::Edge(itL.Value()); |
1720 | if (!aUsedEdges.Contains(edge)) |
1721 | { |
38c2acd4 |
1722 | TopoDS_Vertex V2[2]; |
1723 | TopExp::Vertices(edge, V2[0], V2[1], Standard_True); |
1724 | // the neighboring edge must have V[j] reversed and located on the opposite end |
1725 | if (V2[1 - j].IsEqual(V[j].Reversed())) |
1726 | { |
1727 | if (j == 0) |
1728 | aChain.Prepend(edge); |
1729 | else |
1730 | aChain.Append(edge); |
1731 | aUsedEdges.Add(edge); |
1732 | V[j] = V2[j]; |
1733 | isAdded = Standard_True; |
1734 | break; |
1735 | } |
1736 | } |
1737 | } |
f7d70540 |
1738 | } |
1739 | } |
f7d70540 |
1740 | |
f98965d2 |
1741 | if (aChain.Length() < 2) |
1742 | continue; |
2277323d |
1743 | |
38c2acd4 |
1744 | Standard_Boolean IsClosed = Standard_False; |
f98965d2 |
1745 | if (V[0].IsSame ( V[1] )) |
38c2acd4 |
1746 | IsClosed = Standard_True; |
f98965d2 |
1747 | |
1748 | // split chain by vertices at which merging is not possible |
1749 | NCollection_Sequence<SubSequenceOfEdges> aOneSeq; |
389b9d5c |
1750 | GenerateSubSeq(aChain, aOneSeq, IsClosed, theAngTol, theLinTol, VerticesToAvoid, theVFmap); |
f98965d2 |
1751 | |
1752 | // put sub-chains in the result |
1753 | SeqOfSubSeqOfEdges.Append(aOneSeq); |
1754 | } |
f7d70540 |
1755 | |
1756 | for (int i = 1; i <= SeqOfSubSeqOfEdges.Length(); i++) |
1757 | { |
1758 | TopoDS_Edge UE; |
1759 | if (SeqOfSubSeqOfEdges(i).SeqsEdges.Length() < 2) |
1760 | continue; |
389b9d5c |
1761 | if (MergeSubSeq(SeqOfSubSeqOfEdges(i).SeqsEdges, theVFmap, |
1762 | UE, theAngTol, |
632175c3 |
1763 | ConcatBSplines, isSafeInputMode, theContext)) |
f7d70540 |
1764 | SeqOfSubSeqOfEdges(i).UnionEdges = UE; |
1765 | } |
2277323d |
1766 | return Standard_True; |
1767 | } |
1768 | |
cef6867c |
1769 | //======================================================================= |
1770 | //function : MergeSeq |
f523acf0 |
1771 | //purpose : Tries to unify the sequence of edges with the set of |
1772 | // another edges which lies on the same geometry |
cef6867c |
1773 | //======================================================================= |
f98965d2 |
1774 | static Standard_Boolean MergeSeq (TopTools_SequenceOfShape& SeqEdges, |
389b9d5c |
1775 | const TopTools_IndexedDataMapOfShapeListOfShape& theVFmap, |
632175c3 |
1776 | const Standard_Real theAngTol, |
1f59dfa9 |
1777 | const Standard_Real theLinTol, |
f7d70540 |
1778 | const Standard_Boolean ConcatBSplines, |
632175c3 |
1779 | const Standard_Boolean isSafeInputMode, |
f7d70540 |
1780 | Handle(ShapeBuild_ReShape)& theContext, |
f523acf0 |
1781 | const TopTools_MapOfShape& nonMergVert) |
1782 | { |
f7d70540 |
1783 | NCollection_Sequence<SubSequenceOfEdges> SeqOfSubsSeqOfEdges; |
389b9d5c |
1784 | if (MergeEdges(SeqEdges, theVFmap, theAngTol, theLinTol, ConcatBSplines, isSafeInputMode, |
632175c3 |
1785 | theContext, SeqOfSubsSeqOfEdges, nonMergVert)) |
f7d70540 |
1786 | { |
1787 | for (Standard_Integer i = 1; i <= SeqOfSubsSeqOfEdges.Length(); i++ ) |
1788 | { |
1789 | if (SeqOfSubsSeqOfEdges(i).UnionEdges.IsNull()) |
1790 | continue; |
654c48b2 |
1791 | |
1792 | theContext->Merge(SeqOfSubsSeqOfEdges(i).SeqsEdges, |
1793 | SeqOfSubsSeqOfEdges(i).UnionEdges); |
f7d70540 |
1794 | } |
1795 | return Standard_True; |
1796 | } |
f523acf0 |
1797 | return Standard_False; |
f7d70540 |
1798 | } |
1799 | |
cef6867c |
1800 | //======================================================================= |
1801 | //function : CheckSharedVertices |
1802 | //purpose : Checks the sequence of edges on the presence of shared vertex |
1803 | //======================================================================= |
1804 | |
f7d70540 |
1805 | static void CheckSharedVertices(const TopTools_SequenceOfShape& theSeqEdges, |
1806 | const TopTools_IndexedDataMapOfShapeListOfShape& theMapEdgesVertex, |
9ed6494b |
1807 | const TopTools_MapOfShape& theMapKeepShape, |
f7d70540 |
1808 | TopTools_MapOfShape& theShareVertMap) |
1809 | { |
1810 | ShapeAnalysis_Edge sae; |
1811 | TopTools_SequenceOfShape SeqVertexes; |
1812 | TopTools_MapOfShape MapVertexes; |
1813 | for (Standard_Integer k = 1; k <= theSeqEdges.Length(); k++ ) |
1814 | { |
1815 | TopoDS_Vertex aV1 = sae.FirstVertex(TopoDS::Edge(theSeqEdges(k))); |
1816 | TopoDS_Vertex aV2 = sae.LastVertex(TopoDS::Edge(theSeqEdges(k))); |
1817 | if (!MapVertexes.Add(aV1)) |
1818 | SeqVertexes.Append(aV1); |
1819 | if (!MapVertexes.Add(aV2)) |
1820 | SeqVertexes.Append(aV2); |
1821 | } |
1822 | |
1823 | for (Standard_Integer k = 1; k <= SeqVertexes.Length()/* && !IsSharedVertexPresent*/; k++ ) |
1824 | { |
1825 | const TopTools_ListOfShape& ListEdgesV1 = theMapEdgesVertex.FindFromKey(SeqVertexes(k)); |
f1191d30 |
1826 | if (ListEdgesV1.Extent() > 2 || theMapKeepShape.Contains(SeqVertexes(k))) |
f7d70540 |
1827 | theShareVertMap.Add(SeqVertexes(k)); |
1828 | } |
1829 | //return theShareVertMap.IsEmpty() ? false : true; |
1830 | } |
1831 | |
2277323d |
1832 | //======================================================================= |
1833 | //function : ShapeUpgrade_UnifySameDomain |
1834 | //purpose : Constructor |
1835 | //======================================================================= |
1836 | |
1837 | ShapeUpgrade_UnifySameDomain::ShapeUpgrade_UnifySameDomain() |
2ba9eb30 |
1838 | : myLinTol(Precision::Confusion()), |
1839 | myAngTol(Precision::Angular()), |
1840 | myUnifyFaces(Standard_True), |
fe1a6e4e |
1841 | myUnifyEdges (Standard_True), |
1842 | myConcatBSplines (Standard_False), |
632175c3 |
1843 | myAllowInternal (Standard_False), |
654c48b2 |
1844 | mySafeInputMode(Standard_True), |
1845 | myHistory(new BRepTools_History) |
2277323d |
1846 | { |
2277323d |
1847 | myContext = new ShapeBuild_ReShape; |
1848 | } |
1849 | |
1850 | //======================================================================= |
1851 | //function : ShapeUpgrade_UnifySameDomain |
1852 | //purpose : Constructor |
1853 | //======================================================================= |
1854 | |
1855 | ShapeUpgrade_UnifySameDomain::ShapeUpgrade_UnifySameDomain(const TopoDS_Shape& aShape, |
1856 | const Standard_Boolean UnifyEdges, |
1857 | const Standard_Boolean UnifyFaces, |
1858 | const Standard_Boolean ConcatBSplines) |
fe1a6e4e |
1859 | : myInitShape (aShape), |
2ba9eb30 |
1860 | myLinTol(Precision::Confusion()), |
1861 | myAngTol(Precision::Angular()), |
1862 | myUnifyFaces(UnifyFaces), |
fe1a6e4e |
1863 | myUnifyEdges (UnifyEdges), |
1864 | myConcatBSplines (ConcatBSplines), |
1865 | myAllowInternal (Standard_False), |
632175c3 |
1866 | mySafeInputMode (Standard_True), |
654c48b2 |
1867 | myShape (aShape), |
1868 | myHistory(new BRepTools_History) |
2277323d |
1869 | { |
2277323d |
1870 | myContext = new ShapeBuild_ReShape; |
1871 | } |
1872 | |
1873 | //======================================================================= |
1874 | //function : Initialize |
1875 | //purpose : |
1876 | //======================================================================= |
1877 | |
1878 | void ShapeUpgrade_UnifySameDomain::Initialize(const TopoDS_Shape& aShape, |
1879 | const Standard_Boolean UnifyEdges, |
1880 | const Standard_Boolean UnifyFaces, |
1881 | const Standard_Boolean ConcatBSplines) |
1882 | { |
1883 | myInitShape = aShape; |
1884 | myShape = aShape; |
1885 | myUnifyEdges = UnifyEdges; |
1886 | myUnifyFaces = UnifyFaces; |
1887 | myConcatBSplines = ConcatBSplines; |
1888 | |
1889 | myContext->Clear(); |
9ed6494b |
1890 | myKeepShapes.Clear(); |
f523acf0 |
1891 | myHistory->Clear(); |
fe1a6e4e |
1892 | } |
1893 | |
1894 | //======================================================================= |
1895 | //function : AllowInternalEdges |
1896 | //purpose : |
1897 | //======================================================================= |
1898 | |
1899 | void ShapeUpgrade_UnifySameDomain::AllowInternalEdges (const Standard_Boolean theValue) |
1900 | { |
1901 | myAllowInternal = theValue; |
2277323d |
1902 | } |
1903 | |
632175c3 |
1904 | //======================================================================= |
1905 | //function : SetSafeInputMode |
1906 | //purpose : |
1907 | //======================================================================= |
1908 | |
1909 | void ShapeUpgrade_UnifySameDomain::SetSafeInputMode(Standard_Boolean theValue) |
1910 | { |
1911 | mySafeInputMode = theValue; |
1912 | } |
1913 | |
9ed6494b |
1914 | //======================================================================= |
1915 | //function : KeepShape |
1916 | //purpose : |
1917 | //======================================================================= |
1918 | |
1919 | void ShapeUpgrade_UnifySameDomain::KeepShape(const TopoDS_Shape& theShape) |
1920 | { |
1921 | if (theShape.ShapeType() == TopAbs_EDGE || theShape.ShapeType() == TopAbs_VERTEX) |
1922 | myKeepShapes.Add(theShape); |
1923 | } |
1924 | |
1925 | //======================================================================= |
1926 | //function : KeepShapes |
1927 | //purpose : |
1928 | //======================================================================= |
1929 | |
1930 | void ShapeUpgrade_UnifySameDomain::KeepShapes(const TopTools_MapOfShape& theShapes) |
1931 | { |
1932 | for (TopTools_MapIteratorOfMapOfShape it(theShapes); it.More(); it.Next()) { |
1933 | if (it.Value().ShapeType() == TopAbs_EDGE || it.Value().ShapeType() == TopAbs_VERTEX) |
1934 | myKeepShapes.Add(it.Value()); |
1935 | } |
1936 | } |
1937 | |
2277323d |
1938 | //======================================================================= |
1939 | //function : UnifyFaces |
1940 | //purpose : |
1941 | //======================================================================= |
1942 | |
1943 | void ShapeUpgrade_UnifySameDomain::UnifyFaces() |
1944 | { |
fe1a6e4e |
1945 | // creating map of edge faces for the whole shape |
1946 | TopTools_IndexedDataMapOfShapeListOfShape aGMapEdgeFaces; |
1947 | TopExp::MapShapesAndAncestors(myShape, TopAbs_EDGE, TopAbs_FACE, aGMapEdgeFaces); |
56091b56 |
1948 | |
1949 | // unify faces in each shell separately |
2277323d |
1950 | TopExp_Explorer exps; |
56091b56 |
1951 | for (exps.Init(myShape, TopAbs_SHELL); exps.More(); exps.Next()) |
977ad983 |
1952 | IntUnifyFaces(exps.Current(), aGMapEdgeFaces); |
56091b56 |
1953 | |
1954 | // gather all faces out of shells in one compound and unify them at once |
1955 | BRep_Builder aBB; |
1956 | TopoDS_Compound aCmp; |
1957 | aBB.MakeCompound(aCmp); |
1958 | Standard_Integer nbf = 0; |
1959 | for (exps.Init(myShape, TopAbs_FACE, TopAbs_SHELL); exps.More(); exps.Next(), nbf++) |
1960 | aBB.Add(aCmp, exps.Current()); |
1961 | |
1962 | if (nbf > 0) |
977ad983 |
1963 | IntUnifyFaces(aCmp, aGMapEdgeFaces); |
56091b56 |
1964 | |
1965 | myShape = myContext->Apply(myShape); |
1966 | } |
2277323d |
1967 | |
f16a6cc5 |
1968 | //======================================================================= |
1969 | //function : SetFixWireModes |
1970 | //purpose : |
1971 | //======================================================================= |
1972 | |
1973 | static void SetFixWireModes(ShapeFix_Face& theSff) |
1974 | { |
1975 | Handle(ShapeFix_Wire) aFixWire = theSff.FixWireTool(); |
1976 | aFixWire->FixSelfIntersectionMode() = 0; |
1977 | aFixWire->FixNonAdjacentIntersectingEdgesMode() = 0; |
1978 | aFixWire->FixLackingMode() = 0; |
1979 | aFixWire->FixNotchedEdgesMode() = 0; |
1980 | aFixWire->ModifyTopologyMode() = Standard_False; |
1981 | aFixWire->ModifyRemoveLoopMode() = 0; |
1982 | aFixWire->FixGapsByRangesMode() = Standard_False; |
1983 | aFixWire->FixSmallMode() = 0; |
1984 | } |
1985 | |
632175c3 |
1986 | //======================================================================= |
1987 | //function : IntUnifyFaces |
1988 | //purpose : |
1989 | //======================================================================= |
2277323d |
1990 | |
56091b56 |
1991 | void ShapeUpgrade_UnifySameDomain::IntUnifyFaces(const TopoDS_Shape& theInpShape, |
977ad983 |
1992 | TopTools_IndexedDataMapOfShapeListOfShape& theGMapEdgeFaces) |
56091b56 |
1993 | { |
1994 | // creating map of edge faces for the shape |
1995 | TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces; |
1996 | TopExp::MapShapesAndAncestors(theInpShape, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces); |
1997 | |
1998 | // map of processed shapes |
1999 | TopTools_MapOfShape aProcessed; |
2000 | |
56091b56 |
2001 | // processing each face |
f523acf0 |
2002 | TopExp_Explorer exp; |
56091b56 |
2003 | for (exp.Init(theInpShape, TopAbs_FACE); exp.More(); exp.Next()) { |
389b9d5c |
2004 | |
2005 | TopoDS_Face aFace = TopoDS::Face(exp.Current()); |
2277323d |
2006 | |
56091b56 |
2007 | if (aProcessed.Contains(aFace)) |
2008 | continue; |
2277323d |
2009 | |
f523acf0 |
2010 | // Boundary edges for the new face |
56091b56 |
2011 | TopTools_SequenceOfShape edges; |
2277323d |
2012 | |
f523acf0 |
2013 | Standard_Integer dummy; |
2014 | AddOrdinaryEdges(edges, aFace, dummy); |
2015 | |
2016 | // Faces to get unified with the current faces |
56091b56 |
2017 | TopTools_SequenceOfShape faces; |
f523acf0 |
2018 | |
2019 | // Add the current face for unification |
56091b56 |
2020 | faces.Append(aFace); |
2021 | |
f523acf0 |
2022 | // surface and location to construct result |
56091b56 |
2023 | TopLoc_Location aBaseLocation; |
2024 | Handle(Geom_Surface) aBaseSurface = BRep_Tool::Surface(aFace,aBaseLocation); |
2025 | aBaseSurface = ClearRts(aBaseSurface); |
389b9d5c |
2026 | TopAbs_Orientation RefFaceOrientation = aFace.Orientation(); |
2027 | |
2028 | //Take original surface |
2029 | TopoDS_Face RefFace; |
2030 | BRep_Builder BB; |
2031 | BB.MakeFace(RefFace, aBaseSurface, aBaseLocation, 0.); |
2032 | RefFace.Orientation(RefFaceOrientation); |
2033 | TopTools_MapOfShape MapEdgesWithTemporaryPCurves; //map of edges not lying on RefFace |
2034 | //these edges may be updated by temporary pcurves |
2035 | |
2036 | Standard_Real Uperiod = (aBaseSurface->IsUPeriodic())? aBaseSurface->UPeriod() : 0.; |
56091b56 |
2037 | |
2038 | // find adjacent faces to union |
2039 | Standard_Integer i; |
2040 | for (i = 1; i <= edges.Length(); i++) { |
2041 | TopoDS_Edge edge = TopoDS::Edge(edges(i)); |
2042 | if (BRep_Tool::Degenerated(edge)) |
2043 | continue; |
2277323d |
2044 | |
56091b56 |
2045 | // get connectivity of the edge in the global shape |
2046 | const TopTools_ListOfShape& aGList = theGMapEdgeFaces.FindFromKey(edge); |
9ed6494b |
2047 | if (!myAllowInternal && (aGList.Extent() != 2 || myKeepShapes.Contains(edge))) { |
f523acf0 |
2048 | // non manifold case is not processed unless myAllowInternal |
56091b56 |
2049 | continue; |
2050 | } |
10ce3246 |
2051 | // |
f523acf0 |
2052 | // Get the faces connected through the edge in the current shape |
2053 | const TopTools_ListOfShape& aList = aMapEdgeFaces.FindFromKey(edge); |
2054 | if (aList.Extent() < 2) { |
2055 | continue; |
2056 | } |
2057 | |
f16a6cc5 |
2058 | // for a planar face create and store pcurve of edge on face |
2059 | // to speed up all operations |
2060 | if (!mySafeInputMode && aBaseSurface->IsKind(STANDARD_TYPE(Geom_Plane))) |
2061 | BRepLib::BuildPCurveForEdgeOnPlane(edge, aFace); |
2062 | |
10ce3246 |
2063 | // get normal of the face to compare it with normals of other faces |
2064 | gp_Dir aDN1; |
2065 | // |
2066 | // take intermediate point on edge to compute the normal |
2067 | Standard_Real f, l; |
2068 | BRep_Tool::Range(edge, f, l); |
2069 | Standard_Real aTMid = (f + l) * .5; |
2070 | // |
389b9d5c |
2071 | Standard_Boolean bCheckNormals = GetNormalToSurface(aFace, edge, aTMid, aDN1); |
10ce3246 |
2072 | // |
f523acf0 |
2073 | // Process the faces |
56091b56 |
2074 | TopTools_ListIteratorOfListOfShape anIter(aList); |
2075 | for (; anIter.More(); anIter.Next()) { |
389b9d5c |
2076 | |
2077 | TopoDS_Face aCheckedFace = TopoDS::Face(anIter.Value()); |
2078 | if (aCheckedFace.IsSame(aFace)) |
fe1a6e4e |
2079 | continue; |
2277323d |
2080 | |
389b9d5c |
2081 | if (aProcessed.Contains(aCheckedFace)) |
56091b56 |
2082 | continue; |
2277323d |
2083 | |
10ce3246 |
2084 | if (bCheckNormals) { |
2085 | // get normal of checked face using the same parameter on edge |
2086 | gp_Dir aDN2; |
389b9d5c |
2087 | if (GetNormalToSurface(aCheckedFace, edge, aTMid, aDN2)) { |
10ce3246 |
2088 | // and check if the adjacent faces are having approximately same normals |
2089 | Standard_Real anAngle = aDN1.Angle(aDN2); |
2090 | if (anAngle > myAngTol) { |
2091 | continue; |
2092 | } |
2093 | } |
2094 | } |
2095 | // |
389b9d5c |
2096 | if (IsSameDomain(aFace,aCheckedFace, myLinTol, myAngTol)) { |
f0144633 |
2097 | |
389b9d5c |
2098 | if (AddOrdinaryEdges(edges,aCheckedFace,dummy)) { |
56091b56 |
2099 | // sequence edges is modified |
2100 | i = dummy; |
2277323d |
2101 | } |
56091b56 |
2102 | |
389b9d5c |
2103 | faces.Append(aCheckedFace); |
2104 | aProcessed.Add(aCheckedFace); |
56091b56 |
2105 | break; |
2277323d |
2106 | } |
2107 | } |
56091b56 |
2108 | } |
2277323d |
2109 | |
56091b56 |
2110 | if (faces.Length() > 1) { |
389b9d5c |
2111 | //Add correct pcurves for the reference surface to the edges of other faces |
2112 | AddPCurves(faces, RefFace, MapEdgesWithTemporaryPCurves); |
2113 | |
56091b56 |
2114 | // fill in the connectivity map for selected faces |
2115 | TopTools_IndexedDataMapOfShapeListOfShape aMapEF; |
2116 | for (i = 1; i <= faces.Length(); i++) { |
2117 | TopExp::MapShapesAndAncestors(faces(i), TopAbs_EDGE, TopAbs_FACE, aMapEF); |
2118 | } |
f523acf0 |
2119 | // Collect keep edges and multi-connected edges, i.e. edges that are internal to |
56091b56 |
2120 | // the set of selected faces and have connections to other faces. |
9ed6494b |
2121 | TopTools_ListOfShape aKeepEdges; |
56091b56 |
2122 | for (i = 1; i <= aMapEF.Extent(); i++) { |
2123 | const TopTools_ListOfShape& aLF = aMapEF(i); |
2124 | if (aLF.Extent() == 2) { |
2125 | const TopoDS_Shape& aE = aMapEF.FindKey(i); |
2126 | const TopTools_ListOfShape& aGLF = theGMapEdgeFaces.FindFromKey(aE); |
9ed6494b |
2127 | if (aGLF.Extent() > 2 || myKeepShapes.Contains(aE)) { |
2128 | aKeepEdges.Append(aE); |
fe1a6e4e |
2129 | } |
2130 | } |
9ed6494b |
2131 | } |
2132 | if (!aKeepEdges.IsEmpty()) { |
2133 | if (!myAllowInternal) { |
2134 | // Remove from the selection the faces which have no other connect edges |
f523acf0 |
2135 | // and contain multi-connected edges and/or keep edges. |
56091b56 |
2136 | TopTools_MapOfShape anAvoidFaces; |
9ed6494b |
2137 | TopTools_ListIteratorOfListOfShape it(aKeepEdges); |
56091b56 |
2138 | for (; it.More(); it.Next()) { |
2139 | const TopoDS_Shape& aE = it.Value(); |
2140 | const TopTools_ListOfShape& aLF = aMapEF.FindFromKey(aE); |
2141 | anAvoidFaces.Add(aLF.First()); |
2142 | anAvoidFaces.Add(aLF.Last()); |
2143 | } |
9ed6494b |
2144 | for (i = 1; i <= faces.Length(); i++) { |
56091b56 |
2145 | if (anAvoidFaces.Contains(faces(i))) { |
2146 | // update the boundaries of merged area, for that |
2147 | // remove from 'edges' the edges of this face and add to 'edges' |
2148 | // the edges of this face that were not present in 'edges' before |
9ed6494b |
2149 | Standard_Boolean hasConnectAnotherFaces = Standard_False; |
56091b56 |
2150 | TopExp_Explorer ex(faces(i), TopAbs_EDGE); |
9ed6494b |
2151 | for (; ex.More() && !hasConnectAnotherFaces; ex.Next()) { |
56091b56 |
2152 | TopoDS_Shape aE = ex.Current(); |
9ed6494b |
2153 | const TopTools_ListOfShape& aLF = aMapEF.FindFromKey(aE); |
2154 | if (aLF.Extent() > 1) { |
2155 | for (it.Init(aLF); it.More() && !hasConnectAnotherFaces; it.Next()) { |
2156 | if (!anAvoidFaces.Contains(it.Value())) |
2157 | hasConnectAnotherFaces = Standard_True; |
2158 | } |
2159 | } |
2160 | } |
2161 | if (!hasConnectAnotherFaces) { |
2162 | AddOrdinaryEdges(edges, faces(i), dummy); |
2163 | faces.Remove(i); |
2164 | i--; |
2165 | } |
2166 | } |
2167 | } |
2168 | // check if the faces with keep edges contained in |
2169 | // already updated the boundaries of merged area |
2170 | if (!faces.IsEmpty()) { |
2171 | TopTools_MapOfShape aMapFaces; |
2172 | for (i = 1; i <= faces.Length(); i++) { |
2173 | aMapFaces.Add(faces(i)); |
2174 | } |
2175 | for (it.Init(aKeepEdges); it.More(); it.Next()) { |
2176 | const TopoDS_Shape& aE = it.Value(); |
2177 | const TopTools_ListOfShape& aLF = aMapEF.FindFromKey(aE); |
2178 | if (aLF.Extent() < 2) |
2179 | continue; |
2180 | if (aMapFaces.Contains(aLF.First()) && |
2181 | aMapFaces.Contains(aLF.Last())) { |
2182 | for (i = 1; i <= faces.Length(); i++) { |
2183 | if (faces(i).IsEqual(aLF.First()) || |
2184 | faces(i).IsEqual(aLF.Last())) { |
2185 | AddOrdinaryEdges(edges, faces(i), dummy); |
2186 | faces.Remove(i); |
2187 | i--; |
2188 | } |
cb120537 |
2189 | } |
cb120537 |
2190 | } |
fe1a6e4e |
2191 | } |
2192 | } |
389b9d5c |
2193 | } //if (!myAllowInternal) |
2194 | else { //internal edges are allowed |
f523acf0 |
2195 | // add multi-connected and keep edges as internal in new face |
9ed6494b |
2196 | TopTools_ListIteratorOfListOfShape it(aKeepEdges); |
56091b56 |
2197 | for (; it.More(); it.Next()) { |
2198 | const TopoDS_Shape& aE = it.Value(); |
2199 | edges.Append(aE.Oriented(TopAbs_INTERNAL)); |
fe1a6e4e |
2200 | } |
2201 | } |
389b9d5c |
2202 | } //if (!aKeepEdges.IsEmpty()) |
2203 | } //if (faces.Length() > 1) |
2204 | |
2205 | TopTools_IndexedDataMapOfShapeListOfShape aMapEF; |
2206 | for (i = 1; i <= faces.Length(); i++) |
2207 | TopExp::MapShapesAndUniqueAncestors(faces(i), TopAbs_EDGE, TopAbs_FACE, aMapEF); |
2208 | |
2209 | //Correct orientation of edges |
2210 | for (Standard_Integer ii = 1; ii <= edges.Length(); ii++) |
2211 | { |
fb64d0f4 |
2212 | const TopoDS_Shape& anEdge = edges (ii); |
2213 | Standard_Integer indE = aMapEF.FindIndex (anEdge); |
2214 | const TopTools_ListOfShape& aLF = aMapEF (indE); |
389b9d5c |
2215 | if (myAllowInternal && |
2216 | myKeepShapes.Contains(anEdge) && |
2217 | aLF.Extent() == 2) |
2218 | edges(ii).Orientation(TopAbs_INTERNAL); |
2219 | |
2220 | if (anEdge.Orientation() != TopAbs_INTERNAL) |
fb64d0f4 |
2221 | edges (ii) = aMapEF.FindKey (indE); |
56091b56 |
2222 | } |
fe1a6e4e |
2223 | |
389b9d5c |
2224 | //Exclude internal edges |
2225 | TopTools_IndexedMapOfShape InternalEdges; |
2226 | Standard_Integer ind_e = 1; |
2227 | while (ind_e <= edges.Length()) |
2228 | { |
2229 | const TopoDS_Shape& anEdge = edges(ind_e); |
2230 | if (anEdge.Orientation() == TopAbs_INTERNAL) |
2231 | { |
2232 | InternalEdges.Add(anEdge); |
2233 | edges.Remove(ind_e); |
2234 | } |
2235 | else |
2236 | ind_e++; |
2237 | } |
2238 | |
2239 | if (RefFaceOrientation == TopAbs_REVERSED) |
2240 | for (Standard_Integer ii = 1; ii <= edges.Length(); ii++) |
2241 | edges(ii).Reverse(); |
2242 | TopoDS_Face F_RefFace = RefFace; |
2243 | F_RefFace.Orientation(TopAbs_FORWARD); |
2244 | |
56091b56 |
2245 | // all faces collected in the sequence. Perform union of faces |
389b9d5c |
2246 | if (faces.Length() > 1) |
2247 | { |
2248 | Standard_Real CoordTol = Precision::Confusion(); |
2249 | |
2250 | TopTools_IndexedDataMapOfShapeListOfShape VEmap; |
2251 | for (Standard_Integer ind = 1; ind <= edges.Length(); ind++) |
2252 | TopExp::MapShapesAndUniqueAncestors(edges(ind), TopAbs_VERTEX, TopAbs_EDGE, VEmap); |
2253 | |
2254 | //Perform relocating to new U-origin |
2255 | //Define boundaries in 2d space of RefFace |
2256 | if (Uperiod != 0.) |
2257 | { |
2258 | TopTools_MapOfShape edgesMap; |
2259 | CoordTol = ComputeMinEdgeSize(edges, F_RefFace, edgesMap); |
2260 | CoordTol /= 10.; |
2261 | CoordTol = Max(CoordTol, Precision::Confusion()); |
2262 | |
2263 | //try to find a real seam edge - if it exists, do nothing |
2264 | Standard_Boolean SeamFound = Standard_False; |
2265 | for (Standard_Integer ii = 1; ii <= faces.Length(); ii++) |
2266 | { |
2267 | const TopoDS_Face& face_ii = TopoDS::Face(faces(ii)); |
2268 | TopoDS_Wire anOuterWire = BRepTools::OuterWire(face_ii); |
2269 | TopoDS_Iterator itw(anOuterWire); |
2270 | for (; itw.More(); itw.Next()) |
2271 | { |
2272 | const TopoDS_Edge& anEdge = TopoDS::Edge(itw.Value()); |
2273 | if (BRepTools::IsReallyClosed(anEdge, face_ii)) |
2274 | { |
2275 | SeamFound = Standard_True; |
2276 | break; |
2277323d |
2277 | } |
2277323d |
2278 | } |
389b9d5c |
2279 | } |
2280 | |
2281 | if (!SeamFound) |
2282 | { |
2283 | //try to find the origin of U in 2d space |
2284 | //so that all the faces are in [origin, origin + Uperiod] |
2285 | Standard_Real Umax; |
2286 | Standard_Integer i_face_max; |
2287 | FindFaceWithMaxUbound(faces, F_RefFace, edgesMap, Umax, i_face_max); |
2288 | |
2289 | TopTools_MapOfShape UsedEdges; |
2290 | NCollection_DataMap<TopoDS_Shape, Handle(Geom2d_Curve)> EdgeNewPCurve; |
2291 | |
2292 | //Relocate pcurves to new U-origin |
2293 | RelocatePCurvesToNewUorigin(edges, faces(i_face_max), F_RefFace, CoordTol, Uperiod, |
2294 | VEmap, EdgeNewPCurve, UsedEdges); |
2295 | |
2296 | //PCurves from unused edges (may be degenerated edges) |
2297 | for (Standard_Integer ind = 1; ind <= edges.Length(); ind++) |
2298 | { |
2299 | const TopoDS_Edge& anEdge = TopoDS::Edge(edges(ind)); |
2300 | if (!UsedEdges.Contains(anEdge)) |
2301 | { |
2302 | Standard_Real fpar, lpar; |
2303 | Handle(Geom2d_Curve) aPCurve = BRep_Tool::CurveOnSurface(anEdge, F_RefFace, fpar, lpar); |
2304 | aPCurve = new Geom2d_TrimmedCurve(aPCurve, fpar, lpar); |
2305 | EdgeNewPCurve.Bind(anEdge, aPCurve); |
2277323d |
2306 | } |
2277323d |
2307 | } |
389b9d5c |
2308 | |
2309 | //Restore VEmap |
2310 | VEmap.Clear(); |
2311 | for (Standard_Integer ind = 1; ind <= edges.Length(); ind++) |
2312 | TopExp::MapShapesAndUniqueAncestors(edges(ind), TopAbs_VERTEX, TopAbs_EDGE, VEmap); |
2313 | |
2314 | //Find NewUmin and NewUmax |
2315 | Standard_Real NewUmin = RealLast(), NewUmax = RealFirst(); |
2316 | for (Standard_Integer ii = 1; ii <= edges.Length(); ii++) |
2317 | { |
2318 | const Handle(Geom2d_Curve)& aPCurve = EdgeNewPCurve(edges(ii)); |
2319 | UpdateBoundaries(aPCurve, aPCurve->FirstParameter(), aPCurve->LastParameter(), |
2320 | NewUmin, NewUmax); |
2321 | } |
2322 | |
2323 | if (NewUmax - NewUmin < Uperiod - CoordTol && |
2324 | !(-Precision::Confusion() < NewUmin && NewUmin < Uperiod+Precision::Confusion() && |
2325 | -Precision::Confusion() < NewUmax && NewUmax < Uperiod+Precision::Confusion())) |
2326 | { |
2327 | //we can build a face without seam edge: |
2328 | //update the edges with earlier computed relocated pcurves |
2329 | //fitting into (NewUorigin, NewUorigin + Uperiod) |
2330 | Standard_Real umin, umax, vmin, vmax; |
2331 | aBaseSurface->Bounds(umin, umax, vmin, vmax); |
2332 | Standard_Real RestSpaceInU = Uperiod - (NewUmax - NewUmin); |
2333 | Standard_Real NewUorigin = NewUmin - RestSpaceInU/2; |
2334 | if (NewUorigin < umin) |
2335 | NewUorigin = umin; |
2336 | Handle(Geom_Surface) NewSurf; |
2337 | if (NewUorigin == umin) |
2338 | NewSurf = aBaseSurface; |
2339 | else |
2340 | NewSurf = new Geom_RectangularTrimmedSurface(aBaseSurface, |
2341 | NewUorigin, NewUorigin + Uperiod, |
2342 | Standard_True); //trim U |
2343 | TopoDS_Face OldRefFace = RefFace; |
2344 | Handle(Geom2d_Curve) NullPCurve; |
2345 | RefFace.Nullify(); |
2346 | BB.MakeFace(RefFace, NewSurf, aBaseLocation, 0.); |
2347 | for (Standard_Integer ii = 1; ii <= edges.Length(); ii++) |
2348 | { |
2349 | TopoDS_Edge anEdge = TopoDS::Edge(edges(ii)); |
2350 | if (MapEdgesWithTemporaryPCurves.Contains(anEdge)) |
2351 | BB.UpdateEdge(anEdge, NullPCurve, OldRefFace, 0.); |
2352 | const Handle(Geom2d_Curve)& aPCurve = EdgeNewPCurve(anEdge); |
2353 | BB.UpdateEdge(anEdge, aPCurve, RefFace, 0.); |
2354 | } |
2355 | } |
2356 | } //if (!SeamFound) |
2357 | } //if (Uperiod != 0.) |
2358 | //////////////////////////////////// |
2359 | F_RefFace = RefFace; |
2360 | F_RefFace.Orientation(TopAbs_FORWARD); |
2361 | |
2362 | TopTools_SequenceOfShape NewFaces, NewWires; |
2363 | |
2364 | if (Uperiod == 0) |
2365 | { |
2366 | //Set the "period" for closed non-periodic surface |
2367 | TopLoc_Location aLoc; |
2368 | Handle(Geom_Surface) aSurf = BRep_Tool::Surface(RefFace, aLoc); |
2369 | if (aSurf->IsKind(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) |
2370 | aSurf = (Handle(Geom_RectangularTrimmedSurface)::DownCast(aSurf))->BasisSurface(); |
2371 | Standard_Real Ufirst, Ulast, Vfirst, Vlast; |
2372 | aSurf->Bounds(Ufirst, Ulast, Vfirst, Vlast); |
2373 | if (aSurf->IsUClosed()) |
2374 | Uperiod = Ulast - Ufirst; |
2375 | } |
2376 | |
2377 | TopTools_MapOfShape UsedEdges; |
2378 | |
2379 | Standard_Real FaceUmin = RealLast(); |
2380 | for (Standard_Integer ii = 1; ii <= edges.Length(); ii++) |
2381 | { |
2382 | const TopoDS_Edge& anEdge = TopoDS::Edge(edges(ii)); |
2383 | BRepAdaptor_Curve2d aBAcurve(anEdge, F_RefFace); |
2384 | gp_Pnt2d aFirstPoint = aBAcurve.Value(aBAcurve.FirstParameter()); |
2385 | gp_Pnt2d aLastPoint = aBAcurve.Value(aBAcurve.LastParameter()); |
2386 | if (aFirstPoint.X() < FaceUmin) |
2387 | FaceUmin = aFirstPoint.X(); |
2388 | if (aLastPoint.X() < FaceUmin) |
2389 | FaceUmin = aLastPoint.X(); |
2390 | } |
2391 | |
2392 | //Building new wires from <edges> |
2393 | //and build faces |
2394 | while (!edges.IsEmpty()) |
2395 | { |
2396 | //try to find non-degenerated edge |
2397 | TopoDS_Edge StartEdge = TopoDS::Edge(edges(1)); |
2398 | Standard_Integer istart = 1; |
2399 | while (BRep_Tool::Degenerated(StartEdge) && |
2400 | istart < edges.Length()) |
2401 | { |
2402 | istart++; |
2403 | StartEdge = TopoDS::Edge(edges(istart)); |
2277323d |
2404 | } |
2277323d |
2405 | |
389b9d5c |
2406 | TopoDS_Wire aNewWire; |
2407 | BB.MakeWire(aNewWire); |
2408 | BB.Add(aNewWire, StartEdge); |
2409 | RemoveEdgeFromMap(StartEdge, VEmap); |
2410 | |
2411 | Standard_Real fpar, lpar; |
2412 | Handle(Geom2d_Curve) StartPCurve = BRep_Tool::CurveOnSurface(StartEdge, F_RefFace, fpar, lpar); |
2413 | TopoDS_Vertex StartVertex, CurVertex; |
2414 | TopExp::Vertices(StartEdge, StartVertex, CurVertex, Standard_True); //with orientation |
2415 | Standard_Real StartParam, CurParam; |
2416 | if (StartEdge.Orientation() == TopAbs_FORWARD) |
2417 | { |
2418 | StartParam = fpar; CurParam = lpar; |
56091b56 |
2419 | } |
389b9d5c |
2420 | else |
2421 | { |
2422 | StartParam = lpar; CurParam = fpar; |
2423 | } |
2424 | gp_Pnt2d StartPoint = StartPCurve->Value(StartParam); |
2425 | gp_Pnt2d CurPoint = StartPCurve->Value(CurParam); |
2426 | |
2427 | TopoDS_Edge CurEdge = StartEdge; |
2428 | for (;;) //loop till the end of current new wire |
2429 | { |
2430 | TopoDS_Edge NextEdge; |
2431 | gp_Pnt2d NextPoint; |
2432 | |
2433 | const TopTools_ListOfShape& Elist = VEmap.FindFromKey(CurVertex); |
2434 | TopTools_ListIteratorOfListOfShape itl(Elist); |
2435 | if (Elist.IsEmpty()) |
2436 | { |
2437 | if (CurVertex.IsSame(StartVertex)) |
2438 | { |
2439 | //Points of two vertices coincide in 3d but may be not in 2d |
2440 | if (Uperiod != 0. && |
2441 | Abs(StartPoint.X() - CurPoint.X()) > Uperiod/2) //end of parametric space |
2442 | { |
2443 | //<edges> do not contain seams => we must reconstruct the seam up to <NextEdge> |
2444 | gp_Pnt2d StartOfNextEdge; |
2445 | TopoDS_Vertex LastVertexOfSeam; |
2446 | ReconstructMissedSeam(edges, UsedEdges, F_RefFace, CurVertex, |
2447 | CurPoint, Uperiod, FaceUmin, CoordTol, |
2448 | NextEdge, aNewWire, NextPoint, |
2449 | StartOfNextEdge, LastVertexOfSeam, VEmap); |
2450 | } |
2451 | else |
2452 | { |
2453 | break; //end of wire |
2454 | } |
2455 | } |
2456 | } |
2457 | |
2458 | if (NextEdge.IsNull()) |
2459 | { |
2460 | Standard_Boolean EndOfWire = Standard_False; |
2461 | |
2462 | TopTools_ListOfShape TmpElist, TrueElist; |
2463 | //<TrueElist> will be the list of candidates to become <NextEdge> |
2464 | for (itl.Initialize(Elist); itl.More(); itl.Next()) |
2465 | { |
2466 | const TopoDS_Edge& anEdge = TopoDS::Edge(itl.Value()); |
2467 | if (UsedEdges.Contains(anEdge)) |
2468 | continue; |
2469 | TopoDS_Vertex aFirstVertex = TopExp::FirstVertex(anEdge, Standard_True); |
2470 | if (!aFirstVertex.IsSame(CurVertex)) |
2471 | continue; |
2472 | TmpElist.Append(anEdge); |
2473 | } |
2474 | if (TmpElist.Extent() <= 1 || |
2475 | Uperiod != 0.) |
2476 | TrueElist.Assign(TmpElist); |
2477 | else |
2478 | { |
2479 | //we must choose the closest direction - the biggest angle |
2480 | Standard_Real MaxAngle = RealFirst(); |
2481 | TopoDS_Edge TrueEdge; |
2482 | Handle(Geom2d_Curve) CurPCurve = BRep_Tool::CurveOnSurface(CurEdge, F_RefFace, fpar, lpar); |
2483 | CurParam = (CurEdge.Orientation() == TopAbs_FORWARD)? lpar : fpar; |
2484 | gp_Vec2d CurDir; |
2485 | CurPCurve->D1(CurParam, CurPoint, CurDir); |
2486 | CurDir.Normalize(); |
2487 | if (CurEdge.Orientation() == TopAbs_REVERSED) |
2488 | CurDir.Reverse(); |
2489 | for (itl.Initialize(TmpElist); itl.More(); itl.Next()) |
2490 | { |
2491 | const TopoDS_Edge& anEdge = TopoDS::Edge(itl.Value()); |
2492 | Handle(Geom2d_Curve) aPCurve = BRep_Tool::CurveOnSurface(anEdge, F_RefFace, fpar, lpar); |
2493 | Standard_Real aParam = (anEdge.Orientation() == TopAbs_FORWARD)? fpar : lpar; |
2494 | gp_Pnt2d aPoint; |
2495 | gp_Vec2d aDir; |
2496 | aPCurve->D1(aParam, aPoint, aDir); |
2497 | aDir.Normalize(); |
2498 | if (anEdge.Orientation() == TopAbs_REVERSED) |
2499 | aDir.Reverse(); |
2500 | Standard_Real anAngle = CurDir.Angle(aDir); |
2501 | if (anAngle > MaxAngle) |
2502 | { |
2503 | MaxAngle = anAngle; |
2504 | TrueEdge = anEdge; |
2505 | } |
2506 | } |
2507 | TrueElist.Append(TrueEdge); |
2508 | } |
2509 | |
2510 | //Find next edge in TrueElist |
2511 | for (itl.Initialize(TrueElist); itl.More(); itl.Next()) |
2512 | { |
2513 | const TopoDS_Edge& anEdge = TopoDS::Edge(itl.Value()); |
2514 | |
2515 | Handle(Geom2d_Curve) aPCurve = BRep_Tool::CurveOnSurface(anEdge, F_RefFace, fpar, lpar); |
2516 | Standard_Real aParam = (anEdge.Orientation() == TopAbs_FORWARD)? fpar : lpar; |
2517 | gp_Pnt2d aPoint = aPCurve->Value(aParam); |
2518 | Standard_Real Diff = Abs(aPoint.X() - CurPoint.X()); |
2519 | if (Uperiod != 0. && |
2520 | Diff > CoordTol && |
2521 | Abs(Diff - Uperiod) > CoordTol) //may be is is a deg.vertex |
2522 | continue; |
2523 | |
2524 | //Check: may be <CurPoint> and <aPoint> are on Period from each other |
2525 | if (Uperiod != 0. && Diff > Uperiod/2) //end of parametric space |
2526 | { |
2527 | //<edges> do not contain seams => we must reconstruct the seam up to <NextEdge> |
2528 | gp_Pnt2d StartOfNextEdge; |
2529 | TopoDS_Vertex LastVertexOfSeam; |
2530 | ReconstructMissedSeam(edges, UsedEdges, F_RefFace, CurVertex, |
2531 | CurPoint, Uperiod, FaceUmin, CoordTol, |
2532 | NextEdge, aNewWire, NextPoint, |
2533 | StartOfNextEdge, LastVertexOfSeam, VEmap); |
2534 | |
2535 | //Check: may be it is the end |
2536 | if (LastVertexOfSeam.IsSame(StartVertex) && |
2537 | Abs(StartPoint.X() - StartOfNextEdge.X()) < Uperiod/2) |
2538 | EndOfWire = Standard_True; |
2539 | |
2540 | break; |
2541 | } //if (Uperiod != 0. && Abs(aPoint.X() - CurPoint.X()) > Uperiod/2) |
2542 | else |
2543 | { |
2544 | NextEdge = anEdge; |
2545 | Standard_Real LastParam = (NextEdge.Orientation() == TopAbs_FORWARD)? lpar : fpar; |
2546 | NextPoint = aPCurve->Value(LastParam); |
2547 | break; |
2548 | } |
2549 | } //for (itl.Initialize(TrueElist); itl.More(); itl.Next()) |
2550 | |
2551 | if (EndOfWire) |
2552 | break; |
2553 | } |
2554 | |
2555 | if (NextEdge.IsNull()) |
2556 | { |
2557 | //throw Standard_ConstructionError("Construction of unified wire failed: no proper edge found"); |
2558 | return; |
2559 | } |
2560 | else |
2561 | { |
2562 | CurPoint = NextPoint; |
2563 | CurEdge = NextEdge; |
2564 | CurVertex = TopExp::LastVertex(CurEdge, Standard_True); //with orientation |
2565 | BB.Add(aNewWire, CurEdge); |
2566 | UsedEdges.Add(CurEdge); |
2567 | RemoveEdgeFromMap(CurEdge, VEmap); |
2568 | } |
2569 | } //for (;;) |
a22151d8 |
2570 | aNewWire.Closed(Standard_True); |
389b9d5c |
2571 | UsedEdges.Add(StartEdge); |
2572 | |
2573 | //Remove used edges from sequence |
2574 | Standard_Integer ind = 1; |
2575 | while (ind <= edges.Length()) |
2576 | { |
2577 | if (UsedEdges.Contains(edges(ind))) |
2578 | edges.Remove(ind); |
2579 | else |
2580 | ind++; |
2581 | } |
2582 | |
2583 | //add just built wire to current face or save it in the sequence of wires |
2584 | Standard_Boolean EdgeOnBoundOfSurfFound = Standard_False; |
2585 | TopoDS_Iterator itw(aNewWire); |
2586 | for (; itw.More(); itw.Next()) |
2587 | { |
2588 | const TopoDS_Edge& anEdge = TopoDS::Edge(itw.Value()); |
2589 | if (BRep_Tool::IsClosed(anEdge, RefFace)) |
2590 | { |
2591 | EdgeOnBoundOfSurfFound = Standard_True; |
2592 | break; |
2593 | } |
2594 | } |
2595 | if (EdgeOnBoundOfSurfFound) //this wire can not be a hole |
2596 | { |
2597 | TopLoc_Location aLoc; |
2598 | Handle(Geom_Surface) aSurf = BRep_Tool::Surface(RefFace, aLoc); |
2599 | TopoDS_Face aResult; |
2600 | BB.MakeFace(aResult,aSurf,aLoc,0); |
2601 | BB.Add(aResult, aNewWire); |
2602 | aResult.Orientation(RefFaceOrientation); |
2603 | NewFaces.Append(aResult); |
2604 | } |
2605 | else //may be this wire is a hole |
2606 | { |
2607 | NewWires.Append(aNewWire); |
2608 | } |
2609 | } //while (!edges.IsEmpty()) |
2610 | |
2611 | //Build wires from internal edges |
2612 | TopTools_IndexedDataMapOfShapeListOfShape IntVEmap; |
2613 | for (Standard_Integer ii = 1; ii <= InternalEdges.Extent(); ii++) |
2614 | TopExp::MapShapesAndAncestors(InternalEdges(ii), TopAbs_VERTEX, TopAbs_EDGE, IntVEmap); |
2615 | TopTools_SequenceOfShape InternalWires; |
2616 | while (!InternalEdges.IsEmpty()) |
2617 | { |
2618 | TopoDS_Edge aFirstEdge = TopoDS::Edge(InternalEdges(1)); |
2619 | InternalEdges.RemoveFromIndex(1); |
2620 | TopoDS_Wire anInternalWire; |
2621 | BB.MakeWire(anInternalWire); |
2622 | BB.Add(anInternalWire, aFirstEdge); |
2623 | TopoDS_Edge EndEdges [2]; |
2624 | EndEdges[0] = EndEdges[1] = aFirstEdge; |
2625 | TopoDS_Vertex VV [2]; |
2626 | TopExp::Vertices(aFirstEdge, VV[0], VV[1]); |
2627 | for (;;) |
2628 | { |
2629 | if (VV[0].IsSame(VV[1])) //closed wire |
2630 | break; |
2631 | Standard_Boolean found = Standard_False; |
2632 | for (Standard_Integer ii = 0; ii < 2; ii++) |
2633 | { |
2634 | const TopTools_ListOfShape& Elist = IntVEmap.FindFromKey(VV[ii]); |
2635 | TopTools_ListIteratorOfListOfShape itl(Elist); |
2636 | for (; itl.More(); itl.Next()) |
2637 | { |
2638 | TopoDS_Edge anEdge = TopoDS::Edge(itl.Value()); |
2639 | if (anEdge.IsSame(EndEdges[ii])) |
2640 | continue; |
2641 | found = Standard_True; |
2642 | InternalEdges.RemoveKey(anEdge); |
2643 | BB.Add(anInternalWire, anEdge); |
2644 | TopoDS_Vertex V1, V2; |
2645 | TopExp::Vertices(anEdge, V1, V2); |
2646 | VV[ii] = (V1.IsSame(VV[ii]))? V2 : V1; |
2647 | EndEdges[ii] = anEdge; |
2648 | break; |
38c2acd4 |
2649 | } |
2277323d |
2650 | } |
389b9d5c |
2651 | if (!found) //end of open wire |
2652 | break; |
56091b56 |
2653 | } |
389b9d5c |
2654 | InternalWires.Append(anInternalWire); |
56091b56 |
2655 | } |
2277323d |
2656 | |
389b9d5c |
2657 | //Insert new faces instead of old ones |
2658 | if (NewFaces.IsEmpty()) |
f16a6cc5 |
2659 | { |
389b9d5c |
2660 | //one face without seam |
2661 | TopLoc_Location aLoc; |
2662 | Handle(Geom_Surface) aSurf = BRep_Tool::Surface(RefFace, aLoc); |
2663 | TopoDS_Face aResult; |
2664 | BB.MakeFace(aResult,aSurf,aLoc,0.); |
2665 | for (Standard_Integer ii = 1; ii <= NewWires.Length(); ii++) |
2666 | BB.Add(aResult, NewWires(ii)); |
2667 | for (Standard_Integer ii = 1; ii <= InternalWires.Length(); ii++) |
2668 | BB.Add(aResult, InternalWires(ii)); |
2669 | aResult.Orientation(RefFaceOrientation); |
f16a6cc5 |
2670 | myContext->Merge(faces, aResult); |
2277323d |
2671 | } |
389b9d5c |
2672 | else if (NewFaces.Length() == 1) |
2673 | { |
c5cee322 |
2674 | TopoDS_Shape aNewFace = NewFaces(1).Oriented (TopAbs_FORWARD); |
389b9d5c |
2675 | for (Standard_Integer ii = 1; ii <= NewWires.Length(); ii++) |
c5cee322 |
2676 | BB.Add(aNewFace, NewWires(ii)); |
389b9d5c |
2677 | for (Standard_Integer ii = 1; ii <= InternalWires.Length(); ii++) |
c5cee322 |
2678 | BB.Add(aNewFace, InternalWires(ii)); |
389b9d5c |
2679 | myContext->Merge(faces, NewFaces(1)); |
2680 | } |
2681 | else |
2682 | { |
2683 | //Insert new wires and internal wires into correspondent faces |
2684 | InsertWiresIntoFaces(NewWires, NewFaces, RefFace); |
2685 | InsertWiresIntoFaces(InternalWires, NewFaces, RefFace); |
2686 | |
2687 | NCollection_Sequence<TopTools_MapOfShape> Emaps; |
2688 | for (Standard_Integer ii = 1; ii <= faces.Length(); ii++) |
2689 | { |
2690 | TopTools_MapOfShape aEmap; |
2691 | TopExp::MapShapes(faces(ii), aEmap); |
2692 | Emaps.Append(aEmap); |
2693 | } |
2694 | for (Standard_Integer ii = 1; ii <= NewFaces.Length(); ii++) |
2695 | { |
2696 | TopTools_SequenceOfShape facesForThisFace; |
2697 | TopTools_MapOfShape UsedFaces; |
2698 | TopExp_Explorer Explo(NewFaces(ii), TopAbs_EDGE); |
2699 | for (; Explo.More(); Explo.Next()) |
2700 | { |
2701 | const TopoDS_Edge& anEdge = TopoDS::Edge(Explo.Current()); |
2702 | if (BRep_Tool::Degenerated(anEdge) || |
2703 | BRep_Tool::IsClosed(anEdge, RefFace)) |
2704 | continue; |
2705 | Standard_Integer jj; |
2706 | for (jj = 1; jj <= Emaps.Length(); jj++) |
2707 | if (Emaps(jj).Contains(anEdge)) |
2708 | break; |
2709 | if (UsedFaces.Add(faces(jj))) |
2710 | facesForThisFace.Append(faces(jj)); |
2711 | } |
2712 | myContext->Merge(facesForThisFace, NewFaces(ii)); |
2713 | } |
2714 | } |
2715 | } //if (faces.Length() > 1) |
56091b56 |
2716 | } // end processing each face |
2277323d |
2717 | } |
2718 | |
2719 | //======================================================================= |
2720 | //function : UnifyEdges |
2721 | //purpose : |
2722 | //======================================================================= |
2277323d |
2723 | void ShapeUpgrade_UnifySameDomain::UnifyEdges() |
2724 | { |
632175c3 |
2725 | TopoDS_Shape aRes = myContext->Apply(myShape); |
ce41efde |
2726 | // creating map of edge faces |
2727 | TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces; |
632175c3 |
2728 | TopExp::MapShapesAndAncestors(aRes, TopAbs_EDGE, TopAbs_FACE, aMapEdgeFaces); |
ce41efde |
2729 | // creating map of vertex edges |
2730 | TopTools_IndexedDataMapOfShapeListOfShape aMapEdgesVertex; |
632175c3 |
2731 | TopExp::MapShapesAndUniqueAncestors(aRes, TopAbs_VERTEX, TopAbs_EDGE, aMapEdgesVertex); |
389b9d5c |
2732 | // creating map of vertex faces |
2733 | TopTools_IndexedDataMapOfShapeListOfShape aVFmap; |
2734 | TopExp::MapShapesAndUniqueAncestors(aRes, TopAbs_VERTEX, TopAbs_FACE, aVFmap); |
ce41efde |
2735 | |
632175c3 |
2736 | if (mySafeInputMode) |
2737 | UpdateMapOfShapes(myKeepShapes, myContext); |
2738 | |
12d71ad6 |
2739 | // Sequence of the edges of the shape |
2740 | TopTools_SequenceOfShape aSeqEdges; |
2741 | const Standard_Integer aNbE = aMapEdgeFaces.Extent(); |
2742 | for (Standard_Integer i = 1; i <= aNbE; ++i) |
2743 | aSeqEdges.Append(aMapEdgeFaces.FindKey(i)); |
2744 | |
2745 | // Prepare map of shared vertices (with the number of connected edges greater then 2) |
2746 | TopTools_MapOfShape aSharedVert; |
2747 | CheckSharedVertices(aSeqEdges, aMapEdgesVertex, myKeepShapes, aSharedVert); |
2748 | // Merge the edges avoiding removal of the shared vertices |
389b9d5c |
2749 | Standard_Boolean isMerged = MergeSeq(aSeqEdges, aVFmap, myAngTol, myLinTol, myConcatBSplines, |
12d71ad6 |
2750 | mySafeInputMode, myContext, aSharedVert); |
2751 | // Collect faces to rebuild |
2752 | TopTools_IndexedMapOfShape aChangedFaces; |
2753 | if (isMerged) |
f7d70540 |
2754 | { |
12d71ad6 |
2755 | for (Standard_Integer i = 1; i <= aNbE; ++i) |
f7d70540 |
2756 | { |
12d71ad6 |
2757 | const TopoDS_Shape& aE = aMapEdgeFaces.FindKey(i); |
2758 | if (myContext->IsRecorded(aE)) |
2277323d |
2759 | { |
12d71ad6 |
2760 | TopTools_ListIteratorOfListOfShape it(aMapEdgeFaces(i)); |
2761 | for (; it.More(); it.Next()) |
2762 | aChangedFaces.Add(it.Value()); |
2277323d |
2763 | } |
ce41efde |
2764 | } |
12d71ad6 |
2765 | } |
ce41efde |
2766 | |
2767 | // fix changed faces and replace them in the local context |
632175c3 |
2768 | Standard_Real aPrec = Precision::Confusion(); |
12d71ad6 |
2769 | for (Standard_Integer i = 1; i <= aChangedFaces.Extent(); i++) { |
2770 | TopoDS_Face aFace = TopoDS::Face(myContext->Apply(aChangedFaces.FindKey(i))); |
f7d70540 |
2771 | if (aFace.IsNull()) |
2772 | continue; |
f16a6cc5 |
2773 | |
2774 | // for a planar face create and store pcurve of edge on face |
2775 | // to speed up all operations; but this is allowed only when non-safe mode in force |
2776 | if (!mySafeInputMode) |
2777 | { |
2778 | TopLoc_Location aLoc; |
2779 | Handle(Geom_Surface) aSurface = BRep_Tool::Surface(aFace, aLoc); |
2780 | aSurface = ClearRts(aSurface); |
2781 | if (aSurface->IsKind(STANDARD_TYPE(Geom_Plane))) |
2782 | { |
2783 | TopTools_ListOfShape aLE; |
2784 | for (TopExp_Explorer anEx(aFace, TopAbs_EDGE); anEx.More(); anEx.Next()) |
2785 | aLE.Append(anEx.Current()); |
2786 | BRepLib::BuildPCurveForEdgesOnPlane(aLE, aFace); |
2787 | } |
2788 | } |
2789 | |
2790 | ShapeFix_Face sff(aFace); |
2791 | if (mySafeInputMode) |
2792 | sff.SetContext(myContext); |
2793 | sff.SetPrecision(aPrec); |
2794 | sff.SetMinTolerance(aPrec); |
2795 | sff.SetMaxTolerance(Max(1., aPrec*1000.)); |
2796 | sff.FixOrientationMode() = 0; |
2797 | sff.FixAddNaturalBoundMode() = 0; |
2798 | sff.FixIntersectingWiresMode() = 0; |
2799 | sff.FixLoopWiresMode() = 0; |
2800 | sff.FixSplitFaceMode() = 0; |
2801 | sff.FixPeriodicDegeneratedMode() = 0; |
2802 | SetFixWireModes(sff); |
2803 | sff.Perform(); |
2804 | TopoDS_Shape aNewFace = sff.Face(); |
ce41efde |
2805 | myContext->Replace(aFace,aNewFace); |
ce41efde |
2806 | } |
2807 | |
12d71ad6 |
2808 | if (aChangedFaces.Extent() > 0) { |
ce41efde |
2809 | // fix changed shell and replace it in the local context |
ce41efde |
2810 | TopoDS_Shape aRes1 = myContext->Apply(aRes); |
632175c3 |
2811 | Standard_Boolean isChanged = Standard_False; |
ce41efde |
2812 | TopExp_Explorer expsh; |
2813 | for (expsh.Init(aRes1, TopAbs_SHELL); expsh.More(); expsh.Next()) { |
2814 | TopoDS_Shell aShell = TopoDS::Shell(expsh.Current()); |
2815 | Handle(ShapeFix_Shell) sfsh = new ShapeFix_Shell; |
2816 | sfsh->FixFaceOrientation(aShell); |
2817 | TopoDS_Shape aNewShell = sfsh->Shell(); |
632175c3 |
2818 | if (!aNewShell.IsSame(aShell)) { |
2819 | myContext->Replace(aShell, aNewShell); |
2820 | isChanged = Standard_True; |
2277323d |
2821 | } |
ce41efde |
2822 | } |
632175c3 |
2823 | if (isChanged) |
2824 | aRes1 = myContext->Apply(aRes1); |
2825 | myContext->Replace(myShape, aRes1); |
ce41efde |
2826 | } |
2277323d |
2827 | |
2828 | myShape = myContext->Apply(myShape); |
2829 | } |
2830 | |
2277323d |
2831 | //======================================================================= |
2832 | //function : Build |
2833 | //purpose : builds the resulting shape |
f523acf0 |
2834 | //======================================================================= |
2277323d |
2835 | void ShapeUpgrade_UnifySameDomain::Build() |
2836 | { |
f16a6cc5 |
2837 | if (myUnifyFaces) |
2277323d |
2838 | UnifyFaces(); |
f16a6cc5 |
2839 | if (myUnifyEdges) |
2840 | UnifyEdges(); |
2277323d |
2841 | |
f523acf0 |
2842 | // Fill the history of modifications during the operation |
2843 | FillHistory(); |
2844 | } |
2845 | |
2846 | //======================================================================= |
2847 | //function : FillHistory |
2848 | //purpose : Fill the history of modifications during the operation |
2849 | //======================================================================= |
2850 | void ShapeUpgrade_UnifySameDomain::FillHistory() |
2851 | { |
2852 | if (myHistory.IsNull()) |
2853 | // History is not requested |
2854 | return; |
2855 | |
2856 | // Only Vertices, Edges and Faces can be modified during unification. |
2857 | // Thus, only these kind of shapes should be checked. |
2858 | |
2859 | // Get history from the context. |
2860 | // It contains all modifications of the operation. Some of these |
2861 | // modifications become not relevant and should be filtered. |
2862 | Handle(BRepTools_History) aCtxHistory = myContext->History(); |
2863 | |
2864 | // Explore the history of the context and fill |
2865 | // the history of UnifySameDomain algorithm |
2866 | Handle(BRepTools_History) aUSDHistory = new BRepTools_History(); |
2867 | |
d9ca2e0c |
2868 | // Map all Vertices, Edges, Faces and Solids in the input shape |
f523acf0 |
2869 | TopTools_IndexedMapOfShape aMapInputShape; |
2870 | TopExp::MapShapes(myInitShape, TopAbs_VERTEX, aMapInputShape); |
2871 | TopExp::MapShapes(myInitShape, TopAbs_EDGE , aMapInputShape); |
2872 | TopExp::MapShapes(myInitShape, TopAbs_FACE , aMapInputShape); |
d9ca2e0c |
2873 | TopExp::MapShapes(myInitShape, TopAbs_SOLID , aMapInputShape); |
f523acf0 |
2874 | |
d9ca2e0c |
2875 | // Map all Vertices, Edges, Faces and Solids in the result shape |
f523acf0 |
2876 | TopTools_IndexedMapOfShape aMapResultShapes; |
2877 | TopExp::MapShapes(myShape, TopAbs_VERTEX, aMapResultShapes); |
2878 | TopExp::MapShapes(myShape, TopAbs_EDGE , aMapResultShapes); |
2879 | TopExp::MapShapes(myShape, TopAbs_FACE , aMapResultShapes); |
d9ca2e0c |
2880 | TopExp::MapShapes(myShape, TopAbs_SOLID , aMapResultShapes); |
f523acf0 |
2881 | |
2882 | // Iterate on all input shapes and get their modifications |
2883 | Standard_Integer i, aNb = aMapInputShape.Extent(); |
2884 | for (i = 1; i <= aNb; ++i) |
654c48b2 |
2885 | { |
f523acf0 |
2886 | const TopoDS_Shape& aS = aMapInputShape(i); |
2887 | |
2888 | // Check the shape itself to be present in the result |
2889 | if (aMapResultShapes.Contains(aS)) |
2890 | { |
2891 | // The shape is present in the result as is, thus has not been modified |
2892 | continue; |
2893 | } |
2894 | |
2895 | // Check if the shape has been modified during the operation |
2896 | const TopTools_ListOfShape& aLSImages = aCtxHistory->Modified(aS); |
2897 | if (aLSImages.IsEmpty()) |
2898 | { |
2899 | // The shape has not been modified and not present in the result, |
2900 | // thus it has been removed |
2901 | aUSDHistory->Remove(aS); |
2902 | continue; |
2903 | } |
2904 | |
2905 | // Check the images of the shape to be present in the result |
2906 | Standard_Boolean bRemoved = Standard_True; |
2907 | TopTools_ListIteratorOfListOfShape aItLSIm(aLSImages); |
2908 | for (; aItLSIm.More(); aItLSIm.Next()) |
2909 | { |
d9ca2e0c |
2910 | const TopoDS_Shape& aSIm = aItLSIm.Value(); |
2911 | if (aMapResultShapes.Contains(aSIm)) |
f523acf0 |
2912 | { |
d9ca2e0c |
2913 | if (!aSIm.IsSame(aS)) |
2914 | // Image is found in the result, thus the shape has been modified |
2915 | aUSDHistory->AddModified(aS, aSIm); |
f523acf0 |
2916 | bRemoved = Standard_False; |
2917 | } |
2918 | } |
2919 | |
2920 | if (bRemoved) |
654c48b2 |
2921 | { |
f523acf0 |
2922 | // No images are found in the result, thus the shape has been removed |
2923 | aUSDHistory->Remove(aS); |
654c48b2 |
2924 | } |
20aa0d3f |
2925 | } |
f7d70540 |
2926 | |
f523acf0 |
2927 | // Merge the history of the operation into global history |
2928 | myHistory->Merge(aUSDHistory); |
2277323d |
2929 | } |