4e57c75e |
1 | // Created by: Peter KURNEV |
973c2be1 |
2 | // Copyright (c) 1999-2014 OPEN CASCADE SAS |
4e57c75e |
3 | // |
973c2be1 |
4 | // This file is part of Open CASCADE Technology software library. |
4e57c75e |
5 | // |
d5f74e42 |
6 | // This library is free software; you can redistribute it and/or modify it under |
7 | // the terms of the GNU Lesser General Public License version 2.1 as published |
973c2be1 |
8 | // by the Free Software Foundation, with special exception defined in the file |
9 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
10 | // distribution for complete text of the license and disclaimer of any warranty. |
4e57c75e |
11 | // |
973c2be1 |
12 | // Alternatively, this file may be used under the terms of Open CASCADE |
13 | // commercial license or contractual agreement. |
4e57c75e |
14 | |
4e57c75e |
15 | |
6303cb12 |
16 | #include <Bnd_Box.hxx> |
42cf5bc1 |
17 | #include <BOPTools_AlgoTools2D.hxx> |
18 | #include <BOPTools_AlgoTools3D.hxx> |
19 | #include <BRep_Builder.hxx> |
42cf5bc1 |
20 | #include <BRep_TEdge.hxx> |
21 | #include <BRep_TFace.hxx> |
22 | #include <BRep_Tool.hxx> |
42cf5bc1 |
23 | #include <BRepTools.hxx> |
4e57c75e |
24 | #include <Geom2d_Curve.hxx> |
4e57c75e |
25 | #include <Geom2d_Line.hxx> |
42cf5bc1 |
26 | #include <Geom2d_TrimmedCurve.hxx> |
42cf5bc1 |
27 | #include <Geom2dHatch_Hatcher.hxx> |
4e57c75e |
28 | #include <Geom_BezierSurface.hxx> |
42cf5bc1 |
29 | #include <Geom_BSplineSurface.hxx> |
6303cb12 |
30 | #include <Geom_RectangularTrimmedSurface.hxx> |
42cf5bc1 |
31 | #include <Geom_Surface.hxx> |
d476fc37 |
32 | #include <Geom2dAPI_ProjectPointOnCurve.hxx> |
42cf5bc1 |
33 | #include <gp_Dir.hxx> |
34 | #include <gp_Dir2d.hxx> |
42cf5bc1 |
35 | #include <gp_Pnt.hxx> |
36 | #include <gp_Pnt2d.hxx> |
37 | #include <gp_Vec.hxx> |
38 | #include <gp_Vec2d.hxx> |
6303cb12 |
39 | #include <HatchGen_Domain.hxx> |
42cf5bc1 |
40 | #include <IntTools_Context.hxx> |
41 | #include <IntTools_Tools.hxx> |
42 | #include <Poly_Triangulation.hxx> |
43 | #include <TopExp.hxx> |
44 | #include <TopExp_Explorer.hxx> |
6303cb12 |
45 | #include <TopoDS.hxx> |
6303cb12 |
46 | #include <TopoDS_Edge.hxx> |
47 | #include <TopoDS_Face.hxx> |
42cf5bc1 |
48 | #include <TopoDS_Shape.hxx> |
1155d05a |
49 | #include <TopTools_IndexedMapOfShape.hxx> |
4e57c75e |
50 | |
4e57c75e |
51 | static void Add(const TopoDS_Shape& aS, |
1155d05a |
52 | TopTools_IndexedMapOfShape& myShapes, |
4e57c75e |
53 | Standard_Boolean& bHasGeometry); |
54 | static |
55 | Standard_Boolean HasGeometry(const TopoDS_Shape& aS); |
56 | |
57 | //======================================================================= |
58 | //function : DoSplitSEAMOnFace |
59 | //purpose : |
60 | //======================================================================= |
d476fc37 |
61 | Standard_Boolean BOPTools_AlgoTools3D::DoSplitSEAMOnFace (const TopoDS_Edge& aSplit, |
62 | const TopoDS_Face& aF) |
4e57c75e |
63 | { |
362dec17 |
64 | Standard_Boolean bIsUPeriodic, bIsVPeriodic, bIsLeft; |
d1b591e5 |
65 | Standard_Real anUPeriod = 0., anVPeriod = 0.; |
66 | Standard_Real aTol, a, b, aT, anU, dU, anU1; |
362dec17 |
67 | Standard_Real aScPr, anV, dV, anV1; |
6303cb12 |
68 | Standard_Real aUmin, aUmax, aVmin, aVmax; |
4e57c75e |
69 | gp_Pnt2d aP2D; |
70 | gp_Vec2d aVec2D; |
71 | Handle(Geom2d_Curve) aTmpC1, aTmpC2; |
72 | Handle(Geom2d_Curve) C2D1; |
73 | Handle(Geom2d_Line) aLD1; |
74 | Handle(Geom_Surface) aS; |
75 | BRep_Builder BB; |
76 | TopoDS_Edge aSp; |
77 | // |
362dec17 |
78 | bIsLeft = Standard_False; |
4e57c75e |
79 | aSp=aSplit; |
80 | aSp.Orientation(TopAbs_FORWARD); |
4e57c75e |
81 | aTol=BRep_Tool::Tolerance(aSp); |
fe343049 |
82 | // |
4e57c75e |
83 | aS=BRep_Tool::Surface(aF); |
6303cb12 |
84 | // |
85 | aS->Bounds(aUmin, aUmax, aVmin, aVmax); |
86 | // |
d1b591e5 |
87 | |
88 | bIsUPeriodic = aS->IsUClosed(); |
89 | bIsVPeriodic = aS->IsVClosed(); |
90 | |
91 | if (bIsUPeriodic) |
92 | anUPeriod = aUmax - aUmin; |
93 | if (bIsVPeriodic) |
94 | anVPeriod = aVmax - aVmin; |
95 | |
fe343049 |
96 | // |
97 | if (!bIsUPeriodic && !bIsVPeriodic) { |
d1b591e5 |
98 | |
6303cb12 |
99 | Handle(Geom_RectangularTrimmedSurface) aRTS; |
d1b591e5 |
100 | aRTS = Handle(Geom_RectangularTrimmedSurface)::DownCast(aS); |
4e57c75e |
101 | // |
d1b591e5 |
102 | if (aRTS.IsNull()) |
103 | return Standard_False; |
104 | |
105 | else { |
6303cb12 |
106 | Handle(Geom_Surface) aSB; |
107 | // |
d1b591e5 |
108 | aSB = aRTS->BasisSurface(); |
109 | bIsUPeriodic = aSB->IsUPeriodic(); |
110 | bIsVPeriodic = aSB->IsVPeriodic(); |
6303cb12 |
111 | // |
d1b591e5 |
112 | |
113 | if (bIsUPeriodic || bIsVPeriodic) |
114 | { |
115 | anUPeriod = bIsUPeriodic ? aSB->UPeriod() : 0.; |
116 | anVPeriod = bIsVPeriodic ? aSB->VPeriod() : 0.; |
6303cb12 |
117 | } |
d1b591e5 |
118 | else |
119 | { |
120 | Standard_Boolean bIsUClosed = aSB->IsUClosed(); |
121 | Standard_Boolean bIsVClosed = aSB->IsVClosed(); |
122 | Standard_Real aGlobalUmin, aGlobalUmax, aGlobalVmin, aGlobalVmax; |
123 | aSB->Bounds(aGlobalUmin, aGlobalUmax, aGlobalVmin, aGlobalVmax); |
124 | |
125 | if (bIsUClosed && |
126 | Abs(aUmin - aGlobalUmin) < aTol && |
127 | Abs(aUmax - aGlobalUmax) < aTol) |
128 | { |
129 | bIsUPeriodic = Standard_True; |
130 | anUPeriod = aUmax - aUmin; |
131 | } |
132 | if (bIsVClosed && |
133 | Abs(aVmin - aGlobalVmin) < aTol && |
134 | Abs(aVmax - aGlobalVmax) < aTol) |
135 | { |
136 | bIsVPeriodic = Standard_True; |
137 | anVPeriod = aVmax - aVmin; |
138 | } |
6303cb12 |
139 | } |
d1b591e5 |
140 | |
141 | if (!(bIsUPeriodic || bIsVPeriodic)) { |
142 | return Standard_False; |
6303cb12 |
143 | } |
d1b591e5 |
144 | } //if !RTS.IsNull |
4e57c75e |
145 | } |
146 | // |
6303cb12 |
147 | //--------------------------------------------------- |
4e57c75e |
148 | C2D1=BRep_Tool::CurveOnSurface(aSp, aF, a, b); |
149 | // |
150 | aT=BOPTools_AlgoTools2D::IntermediatePoint(a, b); |
151 | C2D1->D1(aT, aP2D, aVec2D); |
fe343049 |
152 | gp_Dir2d aDir2D1(aVec2D), aDOX(-1.,0.), aDOY(0.,1.); |
4e57c75e |
153 | // |
fe343049 |
154 | anU=aP2D.X(); |
155 | anV=aP2D.Y(); |
4e57c75e |
156 | // |
fe343049 |
157 | anU1=anU; |
158 | anV1=anV; |
4e57c75e |
159 | // |
0929d0ef |
160 | GeomAdaptor_Surface aGAS(aS); |
161 | dU = aGAS.UResolution(aTol); |
162 | dV = aGAS.VResolution(aTol); |
163 | // |
fe343049 |
164 | if (anUPeriod > 0.){ |
6303cb12 |
165 | if (fabs (anU-aUmin) < dU) { |
fe343049 |
166 | bIsLeft=Standard_True; |
167 | anU1=anU+anUPeriod; |
168 | } |
6303cb12 |
169 | else if (fabs (anU-aUmax) < dU) { |
fe343049 |
170 | bIsLeft=Standard_False; |
171 | anU1=anU-anUPeriod; |
172 | } |
4e57c75e |
173 | } |
fe343049 |
174 | // |
175 | if (anVPeriod > 0.) { |
6303cb12 |
176 | if (fabs (anV-aVmin) < dV) { |
fe343049 |
177 | bIsLeft=Standard_True; |
178 | anV1=anV+anVPeriod; |
179 | } |
6303cb12 |
180 | else if (fabs (anV-aVmax) < dV) { |
fe343049 |
181 | bIsLeft=Standard_False; |
182 | anV1=anV-anVPeriod; |
183 | } |
4e57c75e |
184 | } |
fe343049 |
185 | // |
186 | if (anU1==anU && anV1==anV) { |
d476fc37 |
187 | return Standard_False; |
4e57c75e |
188 | } |
189 | // |
fe343049 |
190 | aScPr = (anU1==anU) ? aDir2D1*aDOX : aDir2D1*aDOY; |
191 | // |
4e57c75e |
192 | aTmpC1=Handle(Geom2d_Curve)::DownCast(C2D1->Copy()); |
362dec17 |
193 | Handle(Geom2d_TrimmedCurve) aC1 = |
194 | new Geom2d_TrimmedCurve(aTmpC1, a, b); |
fe343049 |
195 | // |
4e57c75e |
196 | aTmpC2=Handle(Geom2d_Curve)::DownCast(C2D1->Copy()); |
362dec17 |
197 | Handle(Geom2d_TrimmedCurve) aC2 = |
198 | new Geom2d_TrimmedCurve(aTmpC2, a, b); |
fe343049 |
199 | gp_Vec2d aTrV(anU1-anU, anV1-anV); |
4e57c75e |
200 | aC2->Translate(aTrV); |
201 | // |
202 | if (!bIsLeft) { |
203 | if (aScPr<0.) { |
204 | BB.UpdateEdge(aSp, aC2, aC1, aF, aTol); |
205 | } |
206 | else { |
207 | BB.UpdateEdge(aSp, aC1, aC2, aF, aTol); |
208 | } |
209 | } |
210 | else { |
211 | if (aScPr<0.) { |
212 | BB.UpdateEdge(aSp, aC1, aC2, aF, aTol); |
213 | } |
214 | else { |
215 | BB.UpdateEdge(aSp, aC2, aC1, aF, aTol); |
216 | } |
217 | } |
d476fc37 |
218 | return Standard_True; |
4e57c75e |
219 | } |
d476fc37 |
220 | |
221 | //======================================================================= |
222 | //function : DoSplitSEAMOnFace |
223 | //purpose : |
224 | //======================================================================= |
225 | Standard_Boolean BOPTools_AlgoTools3D::DoSplitSEAMOnFace (const TopoDS_Edge& theEOrigin, |
226 | const TopoDS_Edge& theESplit, |
227 | const TopoDS_Face& theFace) |
228 | { |
229 | if (!BRep_Tool::IsClosed (theEOrigin, theFace)) |
230 | return Standard_False; |
231 | |
232 | if (BRep_Tool::IsClosed (theESplit, theFace)) |
233 | return Standard_True; |
234 | |
235 | TopoDS_Edge aESplit = theESplit; |
236 | aESplit.Orientation (TopAbs_FORWARD); |
237 | |
238 | TopoDS_Face aFace = theFace; |
239 | aFace.Orientation (TopAbs_FORWARD); |
240 | |
241 | Standard_Real aTS1, aTS2; |
242 | Handle(Geom2d_Curve) aC2DSplit = BRep_Tool::CurveOnSurface (aESplit, aFace, aTS1, aTS2); |
243 | if (aC2DSplit.IsNull()) |
244 | return Standard_False; |
245 | |
246 | Standard_Real aT1, aT2; |
247 | Handle(Geom2d_Curve) aC2D1 = BRep_Tool::CurveOnSurface ( |
248 | TopoDS::Edge (theEOrigin.Oriented (TopAbs_FORWARD)), aFace, aT1, aT2); |
249 | Handle(Geom2d_Curve) aC2D2 = BRep_Tool::CurveOnSurface ( |
250 | TopoDS::Edge (theEOrigin.Oriented (TopAbs_REVERSED)), aFace, aT1, aT2); |
251 | |
252 | Standard_Real aT = BOPTools_AlgoTools2D::IntermediatePoint (aTS1, aTS2); |
253 | gp_Pnt2d aPMid; |
254 | gp_Vec2d aVTgt; |
255 | aC2DSplit->D1 (aT, aPMid, aVTgt); |
256 | |
257 | // project on original 2d curves |
258 | Geom2dAPI_ProjectPointOnCurve aProjPC1, aProjPC2; |
259 | aProjPC1.Init (aPMid, aC2D1, aT1, aT2); |
260 | aProjPC2.Init (aPMid, aC2D2, aT1, aT2); |
261 | |
262 | if (!aProjPC1.NbPoints() && !aProjPC2.NbPoints()) |
263 | return Standard_False; |
264 | |
265 | Standard_Real aDist1 = aProjPC1.NbPoints() ? aProjPC1.LowerDistance() : RealLast(); |
266 | Standard_Real aDist2 = aProjPC2.NbPoints() ? aProjPC2.LowerDistance() : RealLast(); |
267 | |
268 | if (aDist1 > Precision::PConfusion() && aDist2 > Precision::PConfusion()) |
269 | return Standard_False; |
270 | |
271 | // choose the closest and take corresponding point from the opposite |
272 | gp_Pnt2d aNewPnt = aDist1 < aDist2 ? aC2D2->Value (aProjPC1.LowerDistanceParameter()) : |
273 | aC2D1->Value (aProjPC2.LowerDistanceParameter()); |
274 | |
275 | Handle (Geom2d_Curve) aTmpC1 = Handle (Geom2d_Curve)::DownCast (aC2DSplit->Copy()); |
276 | Handle (Geom2d_Curve) aTmpC2 = Handle (Geom2d_Curve)::DownCast (aC2DSplit->Copy()); |
277 | |
278 | Handle (Geom2d_TrimmedCurve) aC1 = new Geom2d_TrimmedCurve (aTmpC1, aTS1, aTS2); |
279 | Handle (Geom2d_TrimmedCurve) aC2 = new Geom2d_TrimmedCurve (aTmpC2, aTS1, aTS2); |
280 | |
281 | gp_Vec2d aTrVec (aPMid, aNewPnt); |
282 | aC2->Translate (aTrVec); |
283 | |
284 | gp_Pnt2d aPProj; |
285 | gp_Vec2d aVTgtOrigin; |
286 | if (aDist1 < aDist2) |
287 | { |
288 | aC2D1->D1 (aProjPC1.LowerDistanceParameter(), aPProj, aVTgtOrigin); |
289 | } |
290 | else |
291 | { |
292 | aC2D2->D1 (aProjPC2.LowerDistanceParameter(), aPProj, aVTgtOrigin); |
293 | } |
294 | |
295 | Standard_Real aDot = aVTgt.Dot (aVTgtOrigin); |
296 | |
297 | if ((aDist1 < aDist2) == (aDot > 0)) |
298 | { |
299 | BRep_Builder().UpdateEdge (aESplit, aC1, aC2, aFace, BRep_Tool::Tolerance (aESplit)); |
300 | } |
301 | else |
302 | { |
303 | BRep_Builder().UpdateEdge (aESplit, aC2, aC1, aFace, BRep_Tool::Tolerance (aESplit)); |
304 | } |
305 | return Standard_True; |
306 | } |
307 | |
4e57c75e |
308 | //======================================================================= |
309 | //function : GetNormalToFaceOnEdge |
310 | //purpose : |
311 | //======================================================================= |
362dec17 |
312 | void BOPTools_AlgoTools3D::GetNormalToFaceOnEdge (const TopoDS_Edge& aE, |
313 | const TopoDS_Face& aF, |
51db0179 |
314 | gp_Dir& aDNF, |
315 | const Handle(IntTools_Context)& theContext) |
4e57c75e |
316 | { |
317 | Standard_Real aT, aT1, aT2; |
318 | |
319 | BRep_Tool::CurveOnSurface(aE, aF, aT1, aT2); |
320 | aT=BOPTools_AlgoTools2D::IntermediatePoint(aT1, aT2); |
321 | |
51db0179 |
322 | BOPTools_AlgoTools3D::GetNormalToFaceOnEdge (aE, aF, aT, aDNF, theContext); |
4e57c75e |
323 | |
324 | if (aF.Orientation()==TopAbs_REVERSED){ |
325 | aDNF.Reverse(); |
326 | } |
327 | } |
4e57c75e |
328 | //======================================================================= |
329 | //function : GetNormalToFaceOnEdge |
330 | //purpose : |
331 | //======================================================================= |
362dec17 |
332 | void BOPTools_AlgoTools3D::GetNormalToFaceOnEdge (const TopoDS_Edge& aE, |
333 | const TopoDS_Face& aF1, |
334 | const Standard_Real aT, |
51db0179 |
335 | gp_Dir& aDNF1, |
336 | const Handle(IntTools_Context)& theContext) |
4e57c75e |
337 | { |
338 | Standard_Real U, V, aTolPC; |
339 | gp_Pnt2d aP2D; |
340 | gp_Pnt aP; |
341 | gp_Vec aD1U, aD1V; |
342 | |
343 | Handle(Geom_Surface) aS1=BRep_Tool::Surface(aF1); |
344 | |
345 | Handle(Geom2d_Curve)aC2D1; |
51db0179 |
346 | BOPTools_AlgoTools2D::CurveOnSurface(aE, aF1, aC2D1, aTolPC, theContext); |
4e57c75e |
347 | |
348 | aC2D1->D0(aT, aP2D); |
349 | U=aP2D.X(); |
350 | V=aP2D.Y(); |
351 | |
352 | aS1->D1(U, V, aP, aD1U, aD1V); |
353 | gp_Dir aDD1U(aD1U); |
354 | gp_Dir aDD1V(aD1V); |
355 | |
356 | aDNF1=aDD1U^aDD1V; |
357 | } |
4e57c75e |
358 | //======================================================================= |
359 | //function : SenseFlag |
360 | //purpose : |
361 | //======================================================================= |
362dec17 |
362 | Standard_Integer BOPTools_AlgoTools3D::SenseFlag (const gp_Dir& aDNF1, |
363 | const gp_Dir& aDNF2) |
4e57c75e |
364 | { |
365 | Standard_Boolean bIsDirsCoinside; |
362dec17 |
366 | // |
4e57c75e |
367 | bIsDirsCoinside=IntTools_Tools::IsDirsCoinside(aDNF1, aDNF2); |
368 | if (!bIsDirsCoinside) { |
369 | return 0; |
370 | } |
371 | |
372 | Standard_Real aScPr; |
373 | |
374 | aScPr=aDNF1*aDNF2; |
375 | if (aScPr<0.) { |
376 | return -1; |
377 | } |
378 | else if (aScPr>0.) { |
379 | return 1; |
380 | } |
381 | return -1; |
382 | } |
4e57c75e |
383 | //======================================================================= |
384 | //function : GetNormalToSurface |
385 | //purpose : |
386 | //======================================================================= |
362dec17 |
387 | Standard_Boolean BOPTools_AlgoTools3D::GetNormalToSurface |
388 | (const Handle(Geom_Surface)& aS, |
389 | const Standard_Real U, |
390 | const Standard_Real V, |
391 | gp_Dir& aDNS) |
4e57c75e |
392 | { |
4e57c75e |
393 | gp_Pnt aP; |
394 | gp_Vec aD1U, aD1V; |
395 | |
396 | aS->D1(U, V, aP, aD1U, aD1V); |
b7cd7c2b |
397 | |
398 | Standard_Real aLenU = aD1U.SquareMagnitude(); |
399 | if (aLenU < gp::Resolution()) |
400 | return Standard_False; |
401 | |
402 | Standard_Real aLenV = aD1V.SquareMagnitude(); |
403 | if (aLenV < gp::Resolution()) |
404 | return Standard_False; |
405 | |
406 | gp_Dir aDD1U(aD1U); |
407 | gp_Dir aDD1V(aD1V); |
408 | |
409 | Standard_Boolean bFlag = IntTools_Tools::IsDirsCoinside(aDD1U, aDD1U); |
410 | if (!bFlag) |
4e57c75e |
411 | return bFlag; |
b7cd7c2b |
412 | |
413 | aDNS = aDD1U^aDD1V; |
4e57c75e |
414 | return bFlag; |
415 | } |
4e57c75e |
416 | //======================================================================= |
417 | //function : GetApproxNormalToFaceOnEdge |
418 | //purpose : |
419 | //======================================================================= |
18c06690 |
420 | Standard_Boolean BOPTools_AlgoTools3D::GetApproxNormalToFaceOnEdge |
362dec17 |
421 | (const TopoDS_Edge& aE, |
422 | const TopoDS_Face& aF, |
423 | const Standard_Real aT, |
424 | gp_Pnt& aPNear, |
425 | gp_Dir& aDNF, |
426 | Standard_Real aDt2D) |
4e57c75e |
427 | { |
4e57c75e |
428 | gp_Pnt2d aPx2DNear; |
18c06690 |
429 | Standard_Integer iErr = BOPTools_AlgoTools3D::PointNearEdge |
430 | (aE, aF, aT, aDt2D, aPx2DNear, aPNear); |
431 | if (iErr != 1) { |
432 | Handle(Geom_Surface) aS=BRep_Tool::Surface(aF); |
4e57c75e |
433 | |
18c06690 |
434 | BOPTools_AlgoTools3D::GetNormalToSurface |
435 | (aS, aPx2DNear.X(), aPx2DNear.Y(), aDNF); |
4e57c75e |
436 | |
18c06690 |
437 | if (aF.Orientation()==TopAbs_REVERSED){ |
438 | aDNF.Reverse(); |
439 | } |
4e57c75e |
440 | } |
18c06690 |
441 | // |
442 | return (iErr == 0); |
4e57c75e |
443 | } |
4e57c75e |
444 | //======================================================================= |
445 | //function : GetApproxNormalToFaceOnEdge |
446 | //purpose : |
447 | //======================================================================= |
18c06690 |
448 | Standard_Boolean BOPTools_AlgoTools3D::GetApproxNormalToFaceOnEdge |
362dec17 |
449 | (const TopoDS_Edge& aE, |
450 | const TopoDS_Face& aF, |
451 | const Standard_Real aT, |
452 | gp_Pnt& aPNear, |
453 | gp_Dir& aDNF, |
80d55adf |
454 | const Handle(IntTools_Context)& theContext) |
4e57c75e |
455 | { |
4e57c75e |
456 | gp_Pnt2d aPx2DNear; |
18c06690 |
457 | Standard_Integer iErr = BOPTools_AlgoTools3D::PointNearEdge |
362dec17 |
458 | (aE, aF, aT, aPx2DNear, aPNear, theContext); |
18c06690 |
459 | if (iErr != 1) { |
460 | Handle(Geom_Surface) aS=BRep_Tool::Surface(aF); |
4e57c75e |
461 | |
18c06690 |
462 | BOPTools_AlgoTools3D::GetNormalToSurface |
463 | (aS, aPx2DNear.X(), aPx2DNear.Y(), aDNF); |
4e57c75e |
464 | |
18c06690 |
465 | if (aF.Orientation()==TopAbs_REVERSED){ |
466 | aDNF.Reverse(); |
467 | } |
468 | } |
469 | // |
470 | return (iErr == 0); |
471 | } |
472 | //======================================================================= |
473 | //function : GetApproxNormalToFaceOnEdge |
474 | //purpose : |
475 | //======================================================================= |
476 | Standard_Boolean BOPTools_AlgoTools3D::GetApproxNormalToFaceOnEdge |
477 | (const TopoDS_Edge& aE, |
478 | const TopoDS_Face& aF, |
479 | const Standard_Real aT, |
480 | const Standard_Real theStep, |
481 | gp_Pnt& aPNear, |
482 | gp_Dir& aDNF, |
80d55adf |
483 | const Handle(IntTools_Context)& theContext) |
18c06690 |
484 | { |
485 | gp_Pnt2d aPx2DNear; |
486 | Standard_Integer iErr = BOPTools_AlgoTools3D::PointNearEdge |
487 | (aE, aF, aT, theStep, aPx2DNear, aPNear, theContext); |
488 | if (iErr != 1) { |
489 | Handle(Geom_Surface) aS=BRep_Tool::Surface(aF); |
4e57c75e |
490 | |
18c06690 |
491 | BOPTools_AlgoTools3D::GetNormalToSurface |
492 | (aS, aPx2DNear.X(), aPx2DNear.Y(), aDNF); |
493 | |
494 | if (aF.Orientation()==TopAbs_REVERSED){ |
495 | aDNF.Reverse(); |
496 | } |
4e57c75e |
497 | } |
18c06690 |
498 | // |
499 | return (iErr == 0); |
4e57c75e |
500 | } |
4e57c75e |
501 | //======================================================================= |
502 | //function : PointNearEdge |
503 | //purpose : |
504 | //======================================================================= |
18c06690 |
505 | Standard_Integer BOPTools_AlgoTools3D::PointNearEdge |
506 | (const TopoDS_Edge& aE, |
507 | const TopoDS_Face& aF, |
508 | const Standard_Real aT, |
509 | const Standard_Real aDt2D, |
510 | gp_Pnt2d& aPx2DNear, |
511 | gp_Pnt& aPxNear) |
4e57c75e |
512 | { |
513 | Standard_Real aFirst, aLast, aETol, aFTol, transVal; |
514 | GeomAbs_SurfaceType aTS; |
515 | Handle(Geom2d_Curve) aC2D; |
516 | Handle(Geom_Surface) aS; |
517 | // |
518 | aC2D= BRep_Tool::CurveOnSurface (aE, aF, aFirst, aLast); |
18c06690 |
519 | Standard_Integer iErr = aC2D.IsNull() ? 1 : 0; |
520 | if (iErr) { |
521 | return iErr; |
4e57c75e |
522 | } |
523 | // |
524 | aS=BRep_Tool::Surface(aF); |
525 | // |
526 | gp_Pnt2d aPx2D; |
527 | gp_Vec2d aVx2D; |
528 | aC2D->D1 (aT, aPx2D, aVx2D); |
529 | gp_Dir2d aDx2D(aVx2D); |
530 | |
531 | gp_Dir2d aDP; |
532 | aDP.SetCoord (-aDx2D.Y(), aDx2D.X()); |
533 | |
534 | if (aE.Orientation()==TopAbs_REVERSED){ |
535 | aDP.Reverse(); |
536 | } |
537 | |
538 | if (aF.Orientation()==TopAbs_REVERSED) { |
539 | aDP.Reverse(); |
540 | } |
541 | // |
542 | aETol = BRep_Tool::Tolerance(aE); |
543 | aFTol = BRep_Tool::Tolerance(aF); |
f4ea2ca6 |
544 | // NPAL19220 |
4e57c75e |
545 | GeomAdaptor_Surface aGAS(aS); |
546 | aTS=aGAS.GetType(); |
547 | if (aTS==GeomAbs_BSplineSurface) { |
548 | if (aETol > 1.e-5) { |
549 | aFTol=aETol; |
550 | } |
551 | } |
552 | if( aETol > 1.e-5 || aFTol > 1.e-5 ) { |
6303cb12 |
553 | // |
4e57c75e |
554 | if(aTS!=GeomAbs_Sphere) { |
555 | gp_Vec2d transVec( aDP ); |
556 | transVal = aDt2D + aETol + aFTol; |
557 | if (aTS==GeomAbs_Cylinder) {// pkv/909/F8 |
558 | Standard_Real aR, dT; |
559 | // |
560 | gp_Cylinder aCyl=aGAS.Cylinder(); |
561 | aR=aCyl.Radius(); |
562 | dT=1.-transVal/aR; |
563 | if (dT>=-1 && dT<=1) { |
564 | dT=acos(dT); |
565 | transVal=dT; |
566 | } |
567 | } |
568 | // |
569 | transVec.Multiply(transVal); |
570 | aPx2DNear = aPx2D.Translated( transVec ); |
571 | } |
572 | else { |
362dec17 |
573 | aPx2DNear.SetCoord |
574 | (aPx2D.X()+aDt2D*aDP.X(), aPx2D.Y()+aDt2D*aDP.Y()); |
4e57c75e |
575 | } |
576 | } |
577 | else { |
362dec17 |
578 | aPx2DNear.SetCoord |
579 | (aPx2D.X()+aDt2D*aDP.X(), aPx2D.Y()+aDt2D*aDP.Y()); |
4e57c75e |
580 | } |
581 | // |
582 | aS->D0(aPx2DNear.X(), aPx2DNear.Y(), aPxNear); |
18c06690 |
583 | return iErr; |
4e57c75e |
584 | } |
4e57c75e |
585 | //======================================================================= |
586 | //function : PointNearEdge |
587 | //purpose : |
588 | //======================================================================= |
18c06690 |
589 | Standard_Integer BOPTools_AlgoTools3D::PointNearEdge |
362dec17 |
590 | (const TopoDS_Edge& aE, |
591 | const TopoDS_Face& aF, |
592 | const Standard_Real aT, |
593 | gp_Pnt2d& aPx2DNear, |
594 | gp_Pnt& aPxNear, |
80d55adf |
595 | const Handle(IntTools_Context)& theContext) |
4e57c75e |
596 | { |
f4ea2ca6 |
597 | Standard_Real aTolE, aTolF, dTx, dT2D; |
598 | Handle(Geom_Surface) aS; |
599 | GeomAdaptor_Surface aGAS; |
4e57c75e |
600 | // |
f4ea2ca6 |
601 | dT2D=10.*BOPTools_AlgoTools3D::MinStepIn2d();//~1.e-5; |
602 | // |
603 | aS = BRep_Tool::Surface(aF); |
604 | aGAS.Load(aS); |
4e57c75e |
605 | if (aGAS.GetType()==GeomAbs_Cylinder || |
606 | aGAS.GetType()==GeomAbs_Sphere) { |
f4ea2ca6 |
607 | dT2D=10.*dT2D; |
18c06690 |
608 | } |
f4ea2ca6 |
609 | // |
4e57c75e |
610 | aTolE = BRep_Tool::Tolerance(aE); |
611 | aTolF = BRep_Tool::Tolerance(aF); |
f4ea2ca6 |
612 | dTx = 2.*(aTolE + aTolF); |
613 | if (dTx > dT2D) { |
614 | dT2D=dTx; |
615 | } |
616 | // |
18c06690 |
617 | Standard_Integer iErr = BOPTools_AlgoTools3D::PointNearEdge |
362dec17 |
618 | (aE, aF, aT, dT2D, aPx2DNear, aPxNear); |
18c06690 |
619 | if ((iErr != 1) && !theContext->IsPointInOnFace(aF, aPx2DNear)) { |
4e57c75e |
620 | gp_Pnt aP; |
621 | gp_Pnt2d aP2d; |
4e57c75e |
622 | // |
18c06690 |
623 | iErr = BOPTools_AlgoTools3D::PointInFace |
624 | (aF, aE, aT, dT2D, aP, aP2d, theContext); |
625 | if (iErr == 0) { |
626 | aPxNear = aP; |
627 | aPx2DNear = aP2d; |
51db0179 |
628 | } |
629 | else { |
18c06690 |
630 | iErr = 2; // point is out of the face |
51db0179 |
631 | } |
18c06690 |
632 | } |
633 | // |
634 | return iErr; |
635 | } |
636 | |
637 | //======================================================================= |
638 | //function : PointNearEdge |
639 | //purpose : |
640 | //======================================================================= |
641 | Standard_Integer BOPTools_AlgoTools3D::PointNearEdge |
642 | (const TopoDS_Edge& aE, |
643 | const TopoDS_Face& aF, |
644 | const Standard_Real aT, |
645 | const Standard_Real theStep, |
646 | gp_Pnt2d& aPx2DNear, |
647 | gp_Pnt& aPxNear, |
80d55adf |
648 | const Handle(IntTools_Context)& theContext) |
18c06690 |
649 | { |
650 | Standard_Integer iErr = BOPTools_AlgoTools3D::PointNearEdge |
651 | (aE, aF, aT, theStep, aPx2DNear, aPxNear); |
652 | if ((iErr != 1) && !theContext->IsPointInOnFace(aF, aPx2DNear)) { |
653 | gp_Pnt aP; |
654 | gp_Pnt2d aP2d; |
f4ea2ca6 |
655 | // |
18c06690 |
656 | iErr = BOPTools_AlgoTools3D::PointInFace |
657 | (aF, aE, aT, theStep, aP, aP2d, theContext); |
658 | if (iErr == 0) { |
659 | aPxNear = aP; |
660 | aPx2DNear = aP2d; |
f4ea2ca6 |
661 | } |
18c06690 |
662 | else { |
663 | iErr = 2; // point is out of the face |
4e57c75e |
664 | } |
665 | } |
18c06690 |
666 | // |
667 | return iErr; |
4e57c75e |
668 | } |
4e57c75e |
669 | //======================================================================= |
670 | // function: PointNearEdge |
671 | // purpose: |
672 | //======================================================================= |
18c06690 |
673 | Standard_Integer BOPTools_AlgoTools3D::PointNearEdge |
362dec17 |
674 | (const TopoDS_Edge& aE, |
675 | const TopoDS_Face& aF, |
676 | gp_Pnt2d& aPInFace2D, |
677 | gp_Pnt& aPInFace, |
80d55adf |
678 | const Handle(IntTools_Context)& theContext) |
4e57c75e |
679 | { |
680 | Standard_Real aT, aT1, aT2; |
681 | // |
18c06690 |
682 | // 1. compute parameter on edge |
4e57c75e |
683 | BRep_Tool::Range(aE, aT1, aT2); |
684 | aT=BOPTools_AlgoTools2D::IntermediatePoint(aT1, aT2); |
685 | // |
18c06690 |
686 | // 2. compute point inside the face near the edge |
4e57c75e |
687 | TopoDS_Face aFF=aF; |
688 | TopoDS_Edge aERight; |
689 | aFF.Orientation(TopAbs_FORWARD); |
690 | BOPTools_AlgoTools3D::OrientEdgeOnFace (aE, aFF, aERight); |
18c06690 |
691 | // |
692 | Standard_Integer iErr = BOPTools_AlgoTools3D::PointNearEdge |
362dec17 |
693 | (aERight, aFF, aT, aPInFace2D, aPInFace, theContext); |
18c06690 |
694 | // |
695 | return iErr; |
4e57c75e |
696 | } |
4e57c75e |
697 | //======================================================================= |
698 | //function : MinStepIn2d |
699 | //purpose : |
700 | //======================================================================= |
362dec17 |
701 | Standard_Real BOPTools_AlgoTools3D::MinStepIn2d() |
4e57c75e |
702 | { |
703 | Standard_Real dt=1.e-5; |
704 | return dt; |
705 | } |
4e57c75e |
706 | //======================================================================= |
707 | //function : IsEmptyShape |
708 | //purpose : |
709 | //======================================================================= |
362dec17 |
710 | Standard_Boolean BOPTools_AlgoTools3D::IsEmptyShape |
711 | (const TopoDS_Shape& aS) |
4e57c75e |
712 | { |
713 | Standard_Boolean bHasGeometry=Standard_False; |
714 | // |
1155d05a |
715 | TopTools_IndexedMapOfShape myShapes; |
4e57c75e |
716 | // |
717 | Add(aS, myShapes, bHasGeometry); |
718 | |
719 | return !bHasGeometry; |
720 | } |
4e57c75e |
721 | //======================================================================= |
722 | //function : Add |
723 | //purpose : |
724 | //======================================================================= |
725 | void Add(const TopoDS_Shape& aS, |
1155d05a |
726 | TopTools_IndexedMapOfShape& myShapes, |
4e57c75e |
727 | Standard_Boolean& bHasGeometry) |
728 | { |
729 | Standard_Integer anIndex; |
730 | // |
731 | if (bHasGeometry) { |
732 | return; |
733 | } |
734 | // |
735 | if (aS.IsNull()) { |
736 | return; |
737 | } |
738 | // |
b2fedee6 |
739 | const TopoDS_Shape& aSx = aS; |
4e57c75e |
740 | // |
741 | anIndex=myShapes.FindIndex(aSx); |
742 | if (!anIndex) { |
743 | bHasGeometry=HasGeometry (aSx); |
744 | if (bHasGeometry) { |
745 | return; |
746 | } |
747 | // |
748 | TopoDS_Iterator anIt(aSx, Standard_False, Standard_False); |
749 | for(; anIt.More(); anIt.Next()) { |
750 | const TopoDS_Shape& aSy=anIt.Value(); |
751 | Add(aSy, myShapes, bHasGeometry); |
752 | // |
753 | if (bHasGeometry) { |
754 | return; |
755 | } |
756 | // |
757 | myShapes.Add(aSx); |
758 | } |
759 | } |
760 | } |
4e57c75e |
761 | //======================================================================= |
762 | //function : HasGeometry |
763 | //purpose : |
764 | //======================================================================= |
362dec17 |
765 | Standard_Boolean HasGeometry(const TopoDS_Shape& aS) |
4e57c75e |
766 | { |
767 | Standard_Boolean bHasGeometry=Standard_True; |
768 | TopAbs_ShapeEnum aType= aS.ShapeType(); |
769 | |
770 | if (aType == TopAbs_VERTEX) { |
362dec17 |
771 | return bHasGeometry; |
4e57c75e |
772 | } |
4e57c75e |
773 | // |
774 | else if (aType == TopAbs_EDGE) { |
775 | Handle(BRep_TEdge) TE = Handle(BRep_TEdge)::DownCast(aS.TShape()); |
776 | BRep_ListIteratorOfListOfCurveRepresentation itrc(TE->Curves()); |
777 | |
778 | while (itrc.More()) { |
779 | const Handle(BRep_CurveRepresentation)& CR = itrc.Value(); |
780 | if (CR->IsCurve3D()) { |
781 | if (!CR->Curve3D().IsNull()) { |
782 | return bHasGeometry; |
783 | } |
784 | } |
785 | else if (CR->IsCurveOnSurface()) { |
786 | return bHasGeometry; |
787 | } |
788 | else if (CR->IsRegularity()) { |
789 | return bHasGeometry; |
790 | } |
791 | else if (!CR->Polygon3D().IsNull()) { |
792 | return bHasGeometry; |
793 | } |
794 | else if (CR->IsPolygonOnTriangulation()) { |
795 | return bHasGeometry; |
796 | } |
797 | else if (CR->IsPolygonOnSurface()) { |
798 | return bHasGeometry; |
799 | } |
800 | itrc.Next(); |
801 | } |
802 | } |
803 | // |
804 | else if (aType == TopAbs_FACE) { |
805 | Handle(BRep_TFace) TF = Handle(BRep_TFace)::DownCast(aS.TShape()); |
806 | if (!TF->Surface().IsNull()) { |
807 | return bHasGeometry; |
808 | } |
809 | Handle(Poly_Triangulation) Tr = TF->Triangulation(); |
810 | if (!Tr.IsNull()) { |
811 | return bHasGeometry; |
812 | } |
813 | } |
814 | |
815 | return !bHasGeometry; |
816 | } |
4e57c75e |
817 | //======================================================================= |
818 | //function : OrientEdgeOnFace |
819 | //purpose : |
820 | //======================================================================= |
362dec17 |
821 | void BOPTools_AlgoTools3D::OrientEdgeOnFace (const TopoDS_Edge& aE, |
822 | const TopoDS_Face& aF, |
823 | TopoDS_Edge& aERight) |
4e57c75e |
824 | { |
825 | if (BRep_Tool::IsClosed(aE, aF)) { |
826 | aERight=aE; |
827 | aERight.Orientation(aE.Orientation()); |
828 | |
829 | Standard_Integer iFoundCount = 0; |
830 | TopoDS_Edge anEdge = aE; |
831 | TopExp_Explorer anExp(aF, TopAbs_EDGE); |
832 | |
833 | for (; anExp.More(); anExp.Next()) { |
834 | const TopoDS_Shape& aSS=anExp.Current(); |
835 | |
836 | if (aSS.IsSame(aE)) { |
837 | anEdge = TopoDS::Edge(aSS); |
838 | iFoundCount++; |
839 | } |
840 | } |
841 | |
842 | if(iFoundCount == 1) { |
843 | aERight = anEdge; |
844 | } |
845 | return; |
846 | } |
847 | |
848 | TopExp_Explorer anExp(aF, TopAbs_EDGE); |
849 | for (; anExp.More(); anExp.Next()) { |
850 | const TopoDS_Shape& aSS=anExp.Current(); |
851 | if (aSS.IsSame(aE)) { |
852 | aERight=aE; |
853 | aERight.Orientation(aSS.Orientation()); |
854 | return; |
855 | } |
856 | } |
857 | aERight=aE; |
858 | aERight.Orientation(aE.Orientation()); |
859 | } |
4e57c75e |
860 | //======================================================================= |
861 | //function : PointInFace |
862 | //purpose : |
863 | //======================================================================= |
362dec17 |
864 | Standard_Integer BOPTools_AlgoTools3D::PointInFace |
18c06690 |
865 | (const TopoDS_Face& theF, |
362dec17 |
866 | gp_Pnt& theP, |
867 | gp_Pnt2d& theP2D, |
80d55adf |
868 | const Handle(IntTools_Context)& theContext) |
4e57c75e |
869 | { |
18c06690 |
870 | Standard_Integer i, iErr = 1; |
871 | Standard_Real aUMin, aUMax, aVMin, aVMax, aUx; |
872 | // |
873 | theContext->UVBounds(theF, aUMin, aUMax, aVMin, aVMax); |
874 | // |
875 | gp_Dir2d aD2D(0. , 1.); |
876 | aUx = IntTools_Tools::IntermediatePoint(aUMin, aUMax); |
877 | // |
878 | for (i = 0; i < 2; ++i) { |
879 | gp_Pnt2d aP2D(aUx, 0.); |
880 | Handle(Geom2d_Line) aL2D = new Geom2d_Line (aP2D, aD2D); |
881 | iErr = BOPTools_AlgoTools3D::PointInFace |
882 | (theF, aL2D, theP, theP2D, theContext); |
883 | if (iErr == 0) { |
884 | // done |
885 | break; |
886 | } |
887 | else { |
888 | // possible reason - incorrect computation of the 2d box of the face. |
889 | // try to compute the point with the translated line. |
890 | aUx = aUMax - (aUx - aUMin); |
891 | } |
892 | } |
893 | // |
894 | return iErr; |
895 | } |
896 | //======================================================================= |
897 | //function : PointInFace |
898 | //purpose : |
899 | //======================================================================= |
900 | Standard_Integer BOPTools_AlgoTools3D::PointInFace |
901 | (const TopoDS_Face& theF, |
902 | const TopoDS_Edge& theE, |
903 | const Standard_Real theT, |
904 | const Standard_Real theDt2D, |
905 | gp_Pnt& theP, |
906 | gp_Pnt2d& theP2D, |
80d55adf |
907 | const Handle(IntTools_Context)& theContext) |
18c06690 |
908 | { |
909 | Standard_Integer iErr; |
910 | Standard_Real f, l; |
4e57c75e |
911 | Handle(Geom2d_Curve) aC2D; |
4e57c75e |
912 | // |
18c06690 |
913 | iErr = 0; |
914 | aC2D = BRep_Tool::CurveOnSurface (theE, theF, f, l); |
915 | if (aC2D.IsNull()) { |
916 | iErr = 5; |
917 | return iErr; |
918 | } |
4e57c75e |
919 | // |
18c06690 |
920 | gp_Pnt2d aP2D; |
921 | gp_Vec2d aV2D; |
4e57c75e |
922 | // |
18c06690 |
923 | aC2D->D1(theT, aP2D, aV2D); |
924 | gp_Dir2d aD2Dx(aV2D); |
4e57c75e |
925 | // |
18c06690 |
926 | gp_Dir2d aD2D; |
927 | aD2D.SetCoord (-aD2Dx.Y(), aD2Dx.X()); |
928 | // |
929 | if (theE.Orientation()==TopAbs_REVERSED){ |
930 | aD2D.Reverse(); |
51db0179 |
931 | } |
18c06690 |
932 | // |
933 | if (theF.Orientation()==TopAbs_REVERSED) { |
934 | aD2D.Reverse(); |
51db0179 |
935 | } |
4e57c75e |
936 | // |
18c06690 |
937 | Handle(Geom2d_Line) aL2D = new Geom2d_Line(aP2D, aD2D); |
938 | Handle(Geom2d_TrimmedCurve) aL2DTrim = |
939 | new Geom2d_TrimmedCurve(aL2D, 0., Precision::Infinite()); |
940 | // |
941 | iErr = BOPTools_AlgoTools3D::PointInFace |
942 | (theF, aL2DTrim, theP, theP2D, theContext, theDt2D); |
943 | // |
944 | return iErr; |
945 | } |
946 | //======================================================================= |
947 | //function : PointInFace |
948 | //purpose : |
949 | //======================================================================= |
950 | Standard_Integer BOPTools_AlgoTools3D::PointInFace |
951 | (const TopoDS_Face& theF, |
952 | const Handle(Geom2d_Curve)& theL2D, |
953 | gp_Pnt& theP, |
954 | gp_Pnt2d& theP2D, |
80d55adf |
955 | const Handle(IntTools_Context)& theContext, |
18c06690 |
956 | const Standard_Real theDt2D) |
957 | { |
958 | Standard_Boolean bIsDone, bHasFirstPoint, bHasSecondPoint; |
959 | Standard_Integer iErr, aIH, aNbDomains; |
960 | Standard_Real aVx, aV1, aV2; |
961 | // |
962 | Geom2dHatch_Hatcher& aHatcher = theContext->Hatcher(theF); |
963 | // |
964 | Geom2dAdaptor_Curve aHCur(theL2D); |
965 | // |
966 | aHatcher.ClrHatchings(); |
967 | aIH = aHatcher.AddHatching(aHCur); |
968 | // |
969 | iErr = 0; |
970 | for (;;) { |
971 | aHatcher.Trim(); |
972 | bIsDone = aHatcher.TrimDone(aIH); |
873c119f |
973 | if (!bIsDone) { |
18c06690 |
974 | iErr = 1; |
975 | break; |
873c119f |
976 | } |
977 | // |
18c06690 |
978 | aHatcher.ComputeDomains(aIH); |
979 | bIsDone = aHatcher.IsDone(aIH); |
980 | if (!bIsDone) { |
981 | iErr = 2; |
873c119f |
982 | break; |
983 | } |
18c06690 |
984 | // |
985 | aNbDomains = aHatcher.NbDomains(aIH); |
986 | if (aNbDomains == 0) { |
987 | iErr = 2; |
988 | break; |
873c119f |
989 | } |
18c06690 |
990 | // |
991 | const HatchGen_Domain& aDomain = aHatcher.Domain (aIH, 1); |
992 | bHasFirstPoint = aDomain.HasFirstPoint(); |
4e57c75e |
993 | if (!bHasFirstPoint) { |
18c06690 |
994 | iErr = 3; |
995 | break; |
4e57c75e |
996 | } |
997 | // |
18c06690 |
998 | bHasSecondPoint = aDomain.HasSecondPoint(); |
4e57c75e |
999 | if (!bHasSecondPoint) { |
18c06690 |
1000 | iErr = 4; |
1001 | break; |
4e57c75e |
1002 | } |
1003 | // |
18c06690 |
1004 | aV1 = aDomain.FirstPoint().Parameter(); |
1005 | aV2 = aDomain.SecondPoint().Parameter(); |
4e57c75e |
1006 | // |
18c06690 |
1007 | aVx = (theDt2D > 0. && (aV2 - aV1) > theDt2D) ? (aV1 + theDt2D) : |
1008 | IntTools_Tools::IntermediatePoint(aV1, aV2); |
4e57c75e |
1009 | // |
18c06690 |
1010 | Handle(Geom_Surface) aS = BRep_Tool::Surface(theF); |
1011 | // |
1012 | theL2D->D0(aVx, theP2D); |
1013 | aS->D0(theP2D.X(), theP2D.Y(), theP); |
1014 | break; |
3ed30348 |
1015 | } |
4e57c75e |
1016 | // |
18c06690 |
1017 | aHatcher.RemHatching(aIH); |
4e57c75e |
1018 | return iErr; |
1019 | } |