Commit | Line | Data |
---|---|---|
b311480e | 1 | // Created on: 1994-03-25 |
2 | // Created by: Jean Marc LACHAUME | |
3 | // Copyright (c) 1994-1999 Matra Datavision | |
973c2be1 | 4 | // Copyright (c) 1999-2014 OPEN CASCADE SAS |
b311480e | 5 | // |
973c2be1 | 6 | // This file is part of Open CASCADE Technology software library. |
b311480e | 7 | // |
d5f74e42 | 8 | // This library is free software; you can redistribute it and/or modify it under |
9 | // the terms of the GNU Lesser General Public License version 2.1 as published | |
973c2be1 | 10 | // by the Free Software Foundation, with special exception defined in the file |
11 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT | |
12 | // distribution for complete text of the license and disclaimer of any warranty. | |
b311480e | 13 | // |
973c2be1 | 14 | // Alternatively, this file may be used under the terms of Open CASCADE |
15 | // commercial license or contractual agreement. | |
7fd59977 | 16 | |
7fd59977 | 17 | |
7fd59977 | 18 | #include <BRep_Tool.hxx> |
b6cf8ffa | 19 | #include <BRepAdaptor_Surface.hxx> |
42cf5bc1 | 20 | #include <BRepTools.hxx> |
b6cf8ffa | 21 | #include <BRepTools_WireExplorer.hxx> |
42cf5bc1 | 22 | #include <DBRep_Face.hxx> |
23 | #include <DBRep_IsoBuilder.hxx> | |
7fd59977 | 24 | #include <Geom2d_Curve.hxx> |
25 | #include <Geom2d_Line.hxx> | |
26 | #include <Geom2d_TrimmedCurve.hxx> | |
42cf5bc1 | 27 | #include <Geom2dAdaptor_Curve.hxx> |
28 | #include <Geom2dHatch_Intersector.hxx> | |
29 | #include <gp_Dir2d.hxx> | |
30 | #include <gp_Pnt2d.hxx> | |
7fd59977 | 31 | #include <HatchGen_Domain.hxx> |
32 | #include <Precision.hxx> | |
33 | #include <TopAbs_ShapeEnum.hxx> | |
b6cf8ffa | 34 | #include <TopExp.hxx> |
7fd59977 | 35 | #include <TopExp_Explorer.hxx> |
36 | #include <TopoDS.hxx> | |
37 | #include <TopoDS_Edge.hxx> | |
42cf5bc1 | 38 | #include <TopoDS_Face.hxx> |
b6cf8ffa | 39 | #include <TopoDS_Wire.hxx> |
7fd59977 | 40 | |
b6cf8ffa | 41 | #include <NCollection_IndexedDataMap.hxx> |
42 | #include <TopTools_OrientedShapeMapHasher.hxx> | |
43 | ||
44 | // Providing consistency with intersection tolerance for the linear curves | |
45 | static Standard_Real IntersectorConfusion = Precision::PConfusion(); | |
46 | static Standard_Real IntersectorTangency = Precision::PConfusion(); | |
7fd59977 | 47 | static Standard_Real HatcherConfusion2d = 1.e-8 ; |
48 | static Standard_Real HatcherConfusion3d = 1.e-8 ; | |
49 | ||
50 | //======================================================================= | |
51 | // Function : DBRep_IsoBuilder | |
52 | // Purpose : Constructeur. | |
53 | //======================================================================= | |
54 | ||
55 | DBRep_IsoBuilder::DBRep_IsoBuilder (const TopoDS_Face& TopologicalFace, | |
ecc4f148 | 56 | const Standard_Real Infinite, |
57 | const Standard_Integer NbIsos) : | |
58 | Geom2dHatch_Hatcher (Geom2dHatch_Intersector (IntersectorConfusion, | |
59 | IntersectorTangency), | |
60 | HatcherConfusion2d, | |
61 | HatcherConfusion3d, | |
62 | Standard_True, | |
63 | Standard_False) , | |
64 | myInfinite (Infinite) , | |
65 | myUMin (0.0) , | |
66 | myUMax (0.0) , | |
67 | myVMin (0.0) , | |
68 | myVMax (0.0) , | |
69 | myUPrm (1, NbIsos) , | |
70 | myUInd (1, NbIsos) , | |
71 | myVPrm (1, NbIsos) , | |
72 | myVInd (1, NbIsos) , | |
73 | myNbDom (0) | |
7fd59977 | 74 | { |
75 | myUInd.Init(0); | |
76 | myVInd.Init(0); | |
77 | ||
ecc4f148 | 78 | //----------------------------------------------------------------------- |
79 | // If the Min Max bounds are infinite, there are bounded to Infinite | |
80 | // value. | |
81 | //----------------------------------------------------------------------- | |
7fd59977 | 82 | |
83 | BRepTools::UVBounds (TopologicalFace, myUMin, myUMax, myVMin, myVMax) ; | |
84 | Standard_Boolean InfiniteUMin = Precision::IsNegativeInfinite (myUMin) ; | |
85 | Standard_Boolean InfiniteUMax = Precision::IsPositiveInfinite (myUMax) ; | |
86 | Standard_Boolean InfiniteVMin = Precision::IsNegativeInfinite (myVMin) ; | |
87 | Standard_Boolean InfiniteVMax = Precision::IsPositiveInfinite (myVMax) ; | |
88 | if (InfiniteUMin && InfiniteUMax) { | |
89 | myUMin = - Infinite ; | |
90 | myUMax = Infinite ; | |
91 | } else if (InfiniteUMin) { | |
92 | myUMin = myUMax - Infinite ; | |
93 | } else if (InfiniteUMax) { | |
94 | myUMax = myUMin + Infinite ; | |
95 | } | |
96 | if (InfiniteVMin && InfiniteVMax) { | |
97 | myVMin = - Infinite ; | |
98 | myVMax = Infinite ; | |
99 | } else if (InfiniteVMin) { | |
100 | myVMin = myVMax - Infinite ; | |
101 | } else if (InfiniteVMax) { | |
102 | myVMax = myVMin + Infinite ; | |
103 | } | |
104 | ||
ecc4f148 | 105 | //----------------------------------------------------------------------- |
b6cf8ffa | 106 | // Retrieving the edges and its p-curves for further trimming |
107 | // and loading them into the hatcher | |
ecc4f148 | 108 | //----------------------------------------------------------------------- |
b6cf8ffa | 109 | DataMapOfEdgePCurve anEdgePCurveMap; |
7fd59977 | 110 | |
ffe74e46 K |
111 | TopExp_Explorer ExpEdges; |
112 | for (ExpEdges.Init (TopologicalFace, TopAbs_EDGE); ExpEdges.More(); ExpEdges.Next()) | |
113 | { | |
114 | const TopoDS_Edge& TopologicalEdge = TopoDS::Edge (ExpEdges.Current()); | |
115 | Standard_Real U1, U2; | |
116 | const Handle(Geom2d_Curve) PCurve = BRep_Tool::CurveOnSurface (TopologicalEdge, TopologicalFace, U1, U2); | |
117 | ||
118 | if (PCurve.IsNull()) | |
119 | { | |
0797d9d3 | 120 | #ifdef OCCT_DEBUG |
04232180 | 121 | std::cout << "DBRep_IsoBuilder : PCurve is null\n"; |
ecc4f148 | 122 | #endif |
7fd59977 | 123 | return; |
124 | } | |
ffe74e46 K |
125 | else if (U1 == U2) |
126 | { | |
0797d9d3 | 127 | #ifdef OCCT_DEBUG |
04232180 | 128 | std::cout << "DBRep_IsoBuilder PCurve : U1==U2\n"; |
ecc4f148 | 129 | #endif |
7fd59977 | 130 | return; |
131 | } | |
132 | ||
133 | //-- Test if a TrimmedCurve is necessary | |
ffe74e46 | 134 | if (Abs(PCurve->FirstParameter()-U1)<= Precision::PConfusion() |
ecc4f148 | 135 | && Abs(PCurve->LastParameter()-U2)<= Precision::PConfusion()) |
ffe74e46 | 136 | { |
b6cf8ffa | 137 | anEdgePCurveMap.Add(TopologicalEdge, PCurve); |
7fd59977 | 138 | } |
ffe74e46 K |
139 | else |
140 | { | |
141 | if (!PCurve->IsPeriodic()) | |
142 | { | |
143 | Handle (Geom2d_TrimmedCurve) TrimPCurve = Handle(Geom2d_TrimmedCurve)::DownCast (PCurve); | |
144 | if (!TrimPCurve.IsNull()) | |
145 | { | |
146 | if (TrimPCurve->BasisCurve()->FirstParameter() - U1 > Precision::PConfusion() || | |
ecc4f148 | 147 | TrimPCurve->BasisCurve()->FirstParameter() - U2 > Precision::PConfusion() || |
148 | U1 - TrimPCurve->BasisCurve()->LastParameter() > Precision::PConfusion() || | |
149 | U2 - TrimPCurve->BasisCurve()->LastParameter() > Precision::PConfusion()) | |
ffe74e46 | 150 | { |
0797d9d3 | 151 | #ifdef OCCT_DEBUG |
04232180 | 152 | std::cout << "DBRep_IsoBuilder TrimPCurve : parameters out of range\n"; |
153 | std::cout << " U1(" << U1 << "), Umin(" << PCurve->FirstParameter() | |
ecc4f148 | 154 | << "), U2(" << U2 << "), Umax(" << PCurve->LastParameter() << ")\n"; |
155 | #endif | |
ffe74e46 K |
156 | return; |
157 | } | |
158 | } | |
159 | else | |
160 | { | |
161 | if (PCurve->FirstParameter() - U1 > Precision::PConfusion()) | |
162 | { | |
0797d9d3 | 163 | #ifdef OCCT_DEBUG |
04232180 | 164 | std::cout << "DBRep_IsoBuilder PCurve : parameters out of range\n"; |
165 | std::cout << " U1(" << U1 << "), Umin(" << PCurve->FirstParameter() << ")\n"; | |
ecc4f148 | 166 | #endif |
ffe74e46 K |
167 | U1 = PCurve->FirstParameter(); |
168 | } | |
169 | if (PCurve->FirstParameter() - U2 > Precision::PConfusion()) | |
170 | { | |
0797d9d3 | 171 | #ifdef OCCT_DEBUG |
04232180 | 172 | std::cout << "DBRep_IsoBuilder PCurve : parameters out of range\n"; |
173 | std::cout << " U2(" << U2 << "), Umin(" << PCurve->FirstParameter() << ")\n"; | |
ecc4f148 | 174 | #endif |
ffe74e46 K |
175 | U2 = PCurve->FirstParameter(); |
176 | } | |
177 | if (U1 - PCurve->LastParameter() > Precision::PConfusion()) | |
178 | { | |
0797d9d3 | 179 | #ifdef OCCT_DEBUG |
04232180 | 180 | std::cout << "DBRep_IsoBuilder PCurve : parameters out of range\n"; |
181 | std::cout << " U1(" << U1 << "), Umax(" << PCurve->LastParameter() << ")\n"; | |
ecc4f148 | 182 | #endif |
ffe74e46 K |
183 | U1 = PCurve->LastParameter(); |
184 | } | |
185 | if (U2 - PCurve->LastParameter() > Precision::PConfusion()) | |
186 | { | |
0797d9d3 | 187 | #ifdef OCCT_DEBUG |
04232180 | 188 | std::cout << "DBRep_IsoBuilder PCurve : parameters out of range\n"; |
189 | std::cout << " U2(" << U2 << "), Umax(" << PCurve->LastParameter() << ")\n"; | |
ecc4f148 | 190 | #endif |
ffe74e46 K |
191 | U2 = PCurve->LastParameter(); |
192 | } | |
193 | } | |
7fd59977 | 194 | } |
ffe74e46 K |
195 | |
196 | // if U1 and U2 coincide-->do nothing | |
197 | if (Abs (U1 - U2) <= Precision::PConfusion()) continue; | |
198 | Handle (Geom2d_TrimmedCurve) TrimPCurve = new Geom2d_TrimmedCurve (PCurve, U1, U2); | |
b6cf8ffa | 199 | anEdgePCurveMap.Add(TopologicalEdge, TrimPCurve); |
7fd59977 | 200 | } |
201 | } | |
202 | ||
b6cf8ffa | 203 | // Fill the gaps between 2D curves, and trim the intersecting ones. |
204 | FillGaps(TopologicalFace, anEdgePCurveMap); | |
205 | ||
206 | // Load trimmed curves to the hatcher | |
207 | Standard_Integer aNbE = anEdgePCurveMap.Extent(); | |
208 | for (Standard_Integer iE = 1; iE <= aNbE; ++iE) | |
209 | { | |
210 | AddElement(Geom2dAdaptor_Curve(anEdgePCurveMap(iE)), | |
211 | anEdgePCurveMap.FindKey(iE).Orientation()); | |
212 | } | |
ecc4f148 | 213 | //----------------------------------------------------------------------- |
214 | // Loading and trimming the hatchings. | |
215 | //----------------------------------------------------------------------- | |
7fd59977 | 216 | |
217 | Standard_Integer IIso ; | |
218 | Standard_Real DeltaU = Abs (myUMax - myUMin) ; | |
219 | Standard_Real DeltaV = Abs (myVMax - myVMin) ; | |
220 | Standard_Real confusion = Min (DeltaU, DeltaV) * HatcherConfusion3d ; | |
221 | Confusion3d (confusion) ; | |
222 | ||
223 | Standard_Real StepU = DeltaU / (Standard_Real) NbIsos ; | |
224 | if (StepU > confusion) { | |
225 | Standard_Real UPrm = myUMin + StepU / 2. ; | |
226 | gp_Dir2d Dir (0., 1.) ; | |
227 | for (IIso = 1 ; IIso <= NbIsos ; IIso++) { | |
228 | myUPrm(IIso) = UPrm ; | |
229 | gp_Pnt2d Ori (UPrm, 0.) ; | |
230 | Geom2dAdaptor_Curve HCur (new Geom2d_Line (Ori, Dir)) ; | |
231 | myUInd(IIso) = AddHatching (HCur) ; | |
232 | UPrm += StepU ; | |
233 | } | |
234 | } | |
235 | ||
236 | Standard_Real StepV = DeltaV / (Standard_Real) NbIsos ; | |
237 | if (StepV > confusion) { | |
238 | Standard_Real VPrm = myVMin + StepV / 2. ; | |
239 | gp_Dir2d Dir (1., 0.) ; | |
240 | for (IIso = 1 ; IIso <= NbIsos ; IIso++) { | |
241 | myVPrm(IIso) = VPrm ; | |
242 | gp_Pnt2d Ori (0., VPrm) ; | |
243 | Geom2dAdaptor_Curve HCur (new Geom2d_Line (Ori, Dir)) ; | |
244 | myVInd(IIso) = AddHatching (HCur) ; | |
245 | VPrm += StepV ; | |
246 | } | |
247 | } | |
248 | ||
ecc4f148 | 249 | //----------------------------------------------------------------------- |
250 | // Computation. | |
251 | //----------------------------------------------------------------------- | |
7fd59977 | 252 | |
253 | Trim() ; | |
254 | ||
255 | myNbDom = 0 ; | |
ecc4f148 | 256 | for (IIso = 1 ; IIso <= NbIsos ; IIso++) |
257 | { | |
7fd59977 | 258 | Standard_Integer Index ; |
259 | ||
260 | Index = myUInd(IIso) ; | |
ecc4f148 | 261 | if (Index != 0) |
262 | { | |
263 | if (TrimDone (Index) && !TrimFailed (Index)) | |
264 | { | |
265 | ComputeDomains (Index); | |
266 | if (IsDone (Index)) | |
267 | myNbDom = myNbDom + Geom2dHatch_Hatcher::NbDomains (Index) ; | |
7fd59977 | 268 | } |
269 | } | |
270 | ||
271 | Index = myVInd(IIso) ; | |
ecc4f148 | 272 | if (Index != 0) |
273 | { | |
274 | if (TrimDone (Index) && !TrimFailed (Index)) | |
275 | { | |
276 | ComputeDomains (Index); | |
277 | if (IsDone (Index)) | |
278 | myNbDom = myNbDom + Geom2dHatch_Hatcher::NbDomains (Index) ; | |
7fd59977 | 279 | } |
280 | } | |
281 | } | |
282 | } | |
283 | ||
284 | //======================================================================= | |
285 | // Function : LoadIsos | |
286 | // Purpose : Loading of the isoparametric curves in the Data Structure | |
287 | // of a drawable face. | |
288 | //======================================================================= | |
289 | ||
290 | void DBRep_IsoBuilder::LoadIsos (const Handle(DBRep_Face)& Face) const | |
291 | { | |
292 | Standard_Integer NumIso = 0 ; | |
293 | ||
294 | for (Standard_Integer UIso = myUPrm.Lower() ; UIso <= myUPrm.Upper() ; UIso++) { | |
295 | Standard_Integer UInd = myUInd.Value (UIso) ; | |
296 | if (UInd != 0) { | |
297 | Standard_Real UPrm = myUPrm.Value (UIso) ; | |
298 | if (!IsDone (UInd)) { | |
04232180 | 299 | std::cout << "DBRep_IsoBuilder:: U iso of parameter: " << UPrm ; |
7fd59977 | 300 | switch (Status (UInd)) { |
04232180 | 301 | case HatchGen_NoProblem : std::cout << " No Problem" << std::endl ; break ; |
302 | case HatchGen_TrimFailure : std::cout << " Trim Failure" << std::endl ; break ; | |
303 | case HatchGen_TransitionFailure : std::cout << " Transition Failure" << std::endl ; break ; | |
304 | case HatchGen_IncoherentParity : std::cout << " Incoherent Parity" << std::endl ; break ; | |
305 | case HatchGen_IncompatibleStates : std::cout << " Incompatible States" << std::endl ; break ; | |
7fd59977 | 306 | } |
307 | } else { | |
308 | Standard_Integer NbDom = Geom2dHatch_Hatcher::NbDomains (UInd) ; | |
309 | for (Standard_Integer IDom = 1 ; IDom <= NbDom ; IDom++) { | |
310 | const HatchGen_Domain& Dom = Domain (UInd, IDom) ; | |
311 | Standard_Real V1 = Dom.HasFirstPoint() ? Dom.FirstPoint().Parameter() : myVMin - myInfinite ; | |
312 | Standard_Real V2 = Dom.HasSecondPoint() ? Dom.SecondPoint().Parameter() : myVMax + myInfinite ; | |
313 | NumIso++ ; | |
314 | Face->Iso (NumIso, GeomAbs_IsoU, UPrm, V1, V2) ; | |
315 | } | |
316 | } | |
317 | } | |
318 | } | |
319 | ||
320 | for (Standard_Integer VIso = myVPrm.Lower() ; VIso <= myVPrm.Upper() ; VIso++) { | |
321 | Standard_Integer VInd = myVInd.Value (VIso) ; | |
322 | if (VInd != 0) { | |
323 | Standard_Real VPrm = myVPrm.Value (VIso) ; | |
324 | if (!IsDone (VInd)) { | |
04232180 | 325 | std::cout << "DBRep_IsoBuilder:: V iso of parameter: " << VPrm ; |
7fd59977 | 326 | switch (Status (VInd)) { |
04232180 | 327 | case HatchGen_NoProblem : std::cout << " No Problem" << std::endl ; break ; |
328 | case HatchGen_TrimFailure : std::cout << " Trim Failure" << std::endl ; break ; | |
329 | case HatchGen_TransitionFailure : std::cout << " Transition Failure" << std::endl ; break ; | |
330 | case HatchGen_IncoherentParity : std::cout << " Incoherent Parity" << std::endl ; break ; | |
331 | case HatchGen_IncompatibleStates : std::cout << " Incompatible States" << std::endl ; break ; | |
7fd59977 | 332 | } |
333 | } else { | |
334 | Standard_Integer NbDom = Geom2dHatch_Hatcher::NbDomains (VInd) ; | |
335 | for (Standard_Integer IDom = 1 ; IDom <= NbDom ; IDom++) { | |
336 | const HatchGen_Domain& Dom = Domain (VInd, IDom) ; | |
337 | Standard_Real U1 = Dom.HasFirstPoint() ? Dom.FirstPoint().Parameter() : myVMin - myInfinite ; | |
338 | Standard_Real U2 = Dom.HasSecondPoint() ? Dom.SecondPoint().Parameter() : myVMax + myInfinite ; | |
339 | NumIso++ ; | |
340 | Face->Iso (NumIso, GeomAbs_IsoV, VPrm, U1, U2) ; | |
341 | } | |
342 | } | |
343 | } | |
344 | } | |
345 | } | |
b6cf8ffa | 346 | |
347 | //======================================================================= | |
348 | // Function : FillGaps | |
349 | // Purpose : | |
350 | //======================================================================= | |
351 | void DBRep_IsoBuilder::FillGaps(const TopoDS_Face& theFace, | |
352 | DataMapOfEdgePCurve& theEdgePCurveMap) | |
353 | { | |
354 | ||
355 | // Get surface of the face for getting the 3D points from 2D coordinates | |
356 | // of the p-curves bounds | |
357 | BRepAdaptor_Surface aBASurf(theFace, Standard_False); | |
358 | ||
359 | // Analyze each wire of the face separately | |
360 | TopoDS_Iterator aItW(theFace); | |
361 | for (; aItW.More(); aItW.Next()) | |
362 | { | |
363 | const TopoDS_Shape& aW = aItW.Value(); | |
364 | if (aW.ShapeType() != TopAbs_WIRE) | |
365 | continue; | |
366 | ||
367 | // Use WireExplorer to iterate on edges of the wire | |
368 | // to get the pairs of connected edges. | |
369 | // Using WireExplorer will also allow avoiding treatment | |
370 | // of the internal wires. | |
371 | BRepTools_WireExplorer aWExp; | |
372 | aWExp.Init(TopoDS::Wire(aW), theFace, myUMin, myUMax, myVMin, myVMax); | |
373 | if (!aWExp.More()) | |
374 | continue; | |
375 | ||
376 | // Check the number of edges in the wire, not to | |
377 | // miss the wires containing one edge only | |
b2d1851c | 378 | if (aW.NbChildren() == 0) |
b6cf8ffa | 379 | { |
b2d1851c | 380 | continue; |
b6cf8ffa | 381 | } |
b2d1851c | 382 | Standard_Boolean SingleEdge = (aW.NbChildren() == 1); |
b6cf8ffa | 383 | |
384 | TopoDS_Edge aPrevEdge, aCurrEdge; | |
385 | ||
386 | // Get first edge and its p-curve | |
387 | aCurrEdge = aWExp.Current(); | |
388 | ||
389 | // Ensure analysis of the pair of first and last edges | |
390 | TopoDS_Edge aFirstEdge = aCurrEdge; | |
391 | Standard_Real bStop = Standard_False; | |
392 | ||
393 | // Iterate on all other edges | |
394 | while (!bStop) | |
395 | { | |
396 | // Iteration to the next edge | |
397 | aPrevEdge = aCurrEdge; | |
398 | aWExp.Next(); | |
399 | // Get the current edge for analysis | |
400 | if (aWExp.More()) | |
401 | { | |
402 | aCurrEdge = aWExp.Current(); | |
403 | } | |
404 | else | |
405 | { | |
406 | aCurrEdge = aFirstEdge; | |
407 | bStop = Standard_True; | |
408 | } | |
409 | ||
410 | if (aPrevEdge.IsEqual(aCurrEdge) && !SingleEdge) | |
411 | continue; | |
412 | ||
413 | // Get p-curves | |
414 | Handle(Geom2d_Curve)* pPC1 = theEdgePCurveMap.ChangeSeek(aPrevEdge); | |
415 | Handle(Geom2d_Curve)* pPC2 = theEdgePCurveMap.ChangeSeek(aCurrEdge); | |
416 | if (!pPC1 || !pPC2) | |
417 | continue; | |
418 | ||
419 | Handle(Geom2d_Curve)& aPrevC2d = *pPC1; | |
420 | Handle(Geom2d_Curve)& aCurrC2d = *pPC2; | |
421 | ||
422 | // Get p-curves parameters | |
423 | Standard_Real fp, lp, fc, lc; | |
424 | fp = aPrevC2d->FirstParameter(); | |
425 | lp = aPrevC2d->LastParameter(); | |
426 | fc = aCurrC2d->FirstParameter(); | |
427 | lc = aCurrC2d->LastParameter(); | |
428 | ||
429 | // Get common vertex to check if the gap between two edges is closed | |
430 | // by the tolerance value of this vertex. | |
431 | // Take into account the orientation of the edges to obtain the correct | |
432 | // parameter of the vertex on edges. | |
433 | ||
434 | // Get vertex on the previous edge | |
435 | TopoDS_Vertex aCVOnPrev = TopExp::LastVertex(aPrevEdge, Standard_True); | |
436 | if (aCVOnPrev.IsNull()) | |
437 | continue; | |
438 | ||
439 | // Get parameter of the vertex on the previous edge | |
440 | Standard_Real aTPrev = BRep_Tool::Parameter(aCVOnPrev, aPrevEdge); | |
441 | if (aTPrev < fp) | |
442 | aTPrev = fp; | |
443 | else if (aTPrev > lp) | |
444 | aTPrev = lp; | |
445 | ||
446 | // Get vertex on the current edge | |
447 | TopoDS_Vertex aCVOnCurr = TopExp::FirstVertex(aCurrEdge, Standard_True); | |
448 | if (aCVOnCurr.IsNull() || !aCVOnPrev.IsSame(aCVOnCurr)) | |
449 | continue; | |
450 | ||
451 | // Get parameter of the vertex on the current edge | |
452 | Standard_Real aTCurr = BRep_Tool::Parameter(aCVOnCurr, aCurrEdge); | |
453 | if (aTCurr < fc) | |
454 | aTCurr = fc; | |
455 | else if (aTCurr > lc) | |
456 | aTCurr = lc; | |
457 | ||
458 | // Get bounding points on the edges corresponding to the current vertex | |
459 | gp_Pnt2d aPrevP2d = aPrevC2d->Value(aTPrev), | |
460 | aCurrP2d = aCurrC2d->Value(aTCurr); | |
461 | ||
462 | // Check if the vertex covers these bounding points by its tolerance | |
463 | Standard_Real aTolV2 = BRep_Tool::Tolerance(aCVOnPrev); | |
464 | gp_Pnt aPV = BRep_Tool::Pnt(aCVOnPrev); | |
465 | // There is no need to check the distance if the tolerance | |
466 | // of vertex is infinite (like in the test case sewing/tol_1/R2) | |
467 | if (aTolV2 < Precision::Infinite()) | |
468 | { | |
469 | aTolV2 *= aTolV2; | |
470 | ||
471 | // Convert bounding point on previous edge into 3D | |
472 | gp_Pnt aPrevPS = aBASurf.Value(aPrevP2d.X(), aPrevP2d.Y()); | |
473 | ||
474 | // Check if the vertex closes the gap | |
475 | if (aPV.SquareDistance(aPrevPS) > aTolV2) | |
476 | continue; | |
477 | ||
478 | // Convert bounding point on current edge into 3D | |
479 | gp_Pnt aCurrPS = aBASurf.Value(aCurrP2d.X(), aCurrP2d.Y()); | |
480 | ||
481 | // Check if the vertex closes the gap | |
482 | if (aPV.SquareDistance(aCurrPS) > aTolV2) | |
483 | continue; | |
484 | } | |
485 | ||
486 | // Create the segment | |
487 | gp_Vec2d aV2d(aPrevP2d, aCurrP2d); | |
488 | Standard_Real aSegmLen = aV2d.Magnitude(); | |
489 | // Do not add too small segments | |
490 | Standard_Boolean bAddSegment = (aSegmLen > Precision::PConfusion()); | |
491 | // Check for periodic surfaces | |
492 | if (bAddSegment) | |
493 | { | |
494 | if (aBASurf.IsUPeriodic()) | |
495 | bAddSegment = aSegmLen < aBASurf.UPeriod() / 4.; | |
496 | ||
497 | if (bAddSegment && aBASurf.IsVPeriodic()) | |
498 | bAddSegment = aSegmLen < aBASurf.VPeriod() / 4.; | |
499 | } | |
500 | ||
501 | // Check that p-curves do not interfere near the vertex. | |
502 | // And, if they do interfere, avoid creation of the segment. | |
503 | if (bAddSegment && !aPrevEdge.IsEqual(aCurrEdge)) | |
504 | { | |
505 | Geom2dAdaptor_Curve aPrevGC(aPrevC2d, fp, lp), aCurrGC(aCurrC2d, fc, lc); | |
506 | Geom2dInt_GInter anInter(aPrevGC, aCurrGC, Precision::PConfusion(), Precision::PConfusion()); | |
507 | if (anInter.IsDone() && !anInter.IsEmpty()) | |
508 | { | |
509 | // Collect intersection points | |
510 | NCollection_List<IntRes2d_IntersectionPoint> aLPInt; | |
511 | // Get bounding points from segments | |
512 | Standard_Integer iP, aNbInt = anInter.NbSegments(); | |
513 | for (iP = 1; iP <= aNbInt; ++iP) | |
514 | { | |
515 | aLPInt.Append(anInter.Segment(iP).FirstPoint()); | |
516 | aLPInt.Append(anInter.Segment(iP).LastPoint()); | |
517 | } | |
518 | // Get intersection points | |
519 | aNbInt = anInter.NbPoints(); | |
520 | for (iP = 1; iP <= aNbInt; ++iP) | |
521 | aLPInt.Append(anInter.Point(iP)); | |
522 | ||
523 | // Analyze the points and find the one closest to the current vertex | |
524 | Standard_Boolean bPointFound = Standard_False; | |
525 | Standard_Real aTPrevClosest = 0., aTCurrClosest = 0.; | |
526 | Standard_Real aDeltaPrev = ::RealLast(), aDeltaCurr = ::RealLast(); | |
527 | ||
528 | NCollection_List<IntRes2d_IntersectionPoint>::Iterator aItLPInt(aLPInt); | |
529 | for (; aItLPInt.More(); aItLPInt.Next()) | |
530 | { | |
531 | const IntRes2d_IntersectionPoint& aPnt = aItLPInt.Value(); | |
532 | const Standard_Real aTIntPrev = aPnt.ParamOnFirst(); | |
533 | const Standard_Real aTIntCurr = aPnt.ParamOnSecond(); | |
534 | // Check if the intersection point is in range | |
535 | if (aTIntPrev < fp || aTIntPrev > lp || | |
536 | aTIntCurr < fc || aTIntCurr > lc) | |
537 | { | |
538 | continue; | |
539 | } | |
540 | ||
541 | Standard_Real aDelta1 = Abs(aTIntPrev - aTPrev); | |
542 | Standard_Real aDelta2 = Abs(aTIntCurr - aTCurr); | |
543 | if (aDelta1 < aDeltaPrev || aDelta2 < aDeltaCurr) | |
544 | { | |
545 | aTPrevClosest = aTIntPrev; | |
546 | aTCurrClosest = aTIntCurr; | |
547 | aDeltaPrev = aDelta1; | |
548 | aDeltaCurr = aDelta2; | |
549 | bPointFound = Standard_True; | |
550 | } | |
551 | } | |
552 | ||
553 | if (bPointFound) | |
554 | { | |
555 | // Check the number of common vertices between edges. | |
556 | // If on the other end, there is also a common vertex, | |
557 | // check where the intersection point is located. It might | |
558 | // be closer to the other vertex than to the current one. | |
559 | // And here we just need to close the gap, avoiding the trimming. | |
560 | // If the common vertex is only one, do not create the segment, | |
561 | // as we have the intersection of the edges and trimmed the 2d curves. | |
562 | Standard_Integer aNbCV = 0; | |
563 | for (TopoDS_Iterator it1(aPrevEdge); it1.More(); it1.Next()) | |
564 | { | |
565 | for (TopoDS_Iterator it2(aCurrEdge); it2.More(); it2.Next()) | |
566 | { | |
567 | if (it1.Value().IsSame(it2.Value())) | |
568 | ++aNbCV; | |
569 | } | |
570 | } | |
571 | ||
572 | // Trim PCurves only if the intersection belongs to current parameter | |
573 | Standard_Boolean bTrim = (aNbCV == 1 || | |
574 | (Abs(aTPrev - aTPrevClosest) < (lp - fp) / 2. || | |
575 | Abs(aTCurr - aTCurrClosest) < (lc - fc) / 2.)); | |
576 | ||
577 | if (bTrim) | |
578 | { | |
579 | // Check that the intersection point is covered by vertex tolerance | |
580 | gp_Pnt2d aPInt = aPrevC2d->Value(aTPrevClosest); | |
581 | const gp_Pnt aPOnS = aBASurf.Value(aPInt.X(), aPInt.Y()); | |
582 | if (aTolV2 > Precision::Infinite() || aPOnS.SquareDistance(aPV) < aTolV2) | |
583 | { | |
584 | Standard_Real f, l; | |
585 | ||
586 | // Trim the curves with found parameters | |
587 | ||
588 | // Prepare trimming parameters for previous curve | |
589 | if (Abs(fp - aTPrev) < Abs(lp - aTPrev)) | |
590 | { | |
591 | f = aTPrevClosest; | |
592 | l = lp; | |
593 | } | |
594 | else | |
595 | { | |
596 | f = fp; | |
597 | l = aTPrevClosest; | |
598 | } | |
599 | ||
600 | // Trim previous p-curve | |
601 | if (l - f > Precision::PConfusion()) | |
602 | aPrevC2d = new Geom2d_TrimmedCurve(aPrevC2d, f, l); | |
603 | ||
604 | // Prepare trimming parameters for current p-curve | |
605 | if (Abs(fc - aTCurr) < Abs(lc - aTCurr)) | |
606 | { | |
607 | f = aTCurrClosest; | |
608 | l = lc; | |
609 | } | |
610 | else | |
611 | { | |
612 | f = fc; | |
613 | l = aTCurrClosest; | |
614 | } | |
615 | ||
616 | // Trim current p-curve | |
617 | if (l - f > Precision::PConfusion()) | |
618 | aCurrC2d = new Geom2d_TrimmedCurve(aCurrC2d, f, l); | |
619 | ||
620 | // Do not create the segment, as we performed the trimming | |
621 | // to the intersection point. | |
622 | bAddSegment = Standard_False; | |
623 | } | |
624 | } | |
625 | } | |
626 | } | |
627 | } | |
628 | ||
629 | if (bAddSegment) | |
630 | { | |
631 | // Add segment to the hatcher to trim the iso-lines | |
632 | Handle(Geom2d_Line) aLine = new Geom2d_Line(aPrevP2d, aV2d); | |
633 | Handle(Geom2d_TrimmedCurve) aLineSegm = new Geom2d_TrimmedCurve(aLine, 0.0, aSegmLen); | |
634 | AddElement(Geom2dAdaptor_Curve(aLineSegm), TopAbs_FORWARD); | |
635 | } | |
636 | } | |
637 | } | |
638 | } |