b311480e |
1 | // Created on: 1995-07-07 |
2 | // Created by: Joelle CHAUVET |
3 | // Copyright (c) 1995-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. |
b311480e |
16 | |
7fd59977 |
17 | // Modified : 08/07/97 : JPI : traitement des edges degeneres comme pour les fillets 2D |
18 | // Modified: Fri Sep 25 09:38:04 1998 |
7fd59977 |
19 | // status = ChFi2d_NotAuthorized si les aretes ne sont pas |
20 | // des droites ou des cercles; fonction IsLineOrCircle |
21 | // (BUC60288) |
22 | |
42cf5bc1 |
23 | #include <BRep_Builder.hxx> |
24 | #include <BRep_Tool.hxx> |
7fd59977 |
25 | #include <BRepAdaptor_Curve.hxx> |
26 | #include <BRepAdaptor_Surface.hxx> |
27 | #include <BRepLib_MakeEdge.hxx> |
28 | #include <BRepLib_MakeFace.hxx> |
42cf5bc1 |
29 | #include <ChFi2d.hxx> |
30 | #include <ChFi2d_Builder.hxx> |
7fd59977 |
31 | #include <ElCLib.hxx> |
42cf5bc1 |
32 | #include <GCPnts_AbscissaPoint.hxx> |
33 | #include <Geom2d_Circle.hxx> |
34 | #include <Geom2d_Curve.hxx> |
35 | #include <Geom2d_Line.hxx> |
36 | #include <Geom2d_TrimmedCurve.hxx> |
37 | #include <Geom2dAdaptor_Curve.hxx> |
38 | #include <Geom2dInt_GInter.hxx> |
7fd59977 |
39 | #include <Geom_Curve.hxx> |
40 | #include <Geom_Line.hxx> |
41 | #include <Geom_Plane.hxx> |
42 | #include <Geom_Surface.hxx> |
7fd59977 |
43 | #include <GeomAdaptor_Curve.hxx> |
44 | #include <GeomAPI.hxx> |
7fd59977 |
45 | #include <gp_Pln.hxx> |
46 | #include <gp_Pnt.hxx> |
47 | #include <gp_Pnt2d.hxx> |
42cf5bc1 |
48 | #include <IntRes2d_IntersectionPoint.hxx> |
7fd59977 |
49 | #include <Precision.hxx> |
7fd59977 |
50 | #include <TopAbs_Orientation.hxx> |
51 | #include <TopExp.hxx> |
52 | #include <TopExp_Explorer.hxx> |
53 | #include <TopLoc_Location.hxx> |
7fd59977 |
54 | #include <TopoDS.hxx> |
55 | #include <TopoDS_Edge.hxx> |
42cf5bc1 |
56 | #include <TopoDS_Face.hxx> |
7fd59977 |
57 | #include <TopoDS_Shape.hxx> |
42cf5bc1 |
58 | #include <TopoDS_Vertex.hxx> |
59 | #include <TopoDS_Wire.hxx> |
7fd59977 |
60 | |
61 | gp_Pnt ComputePoint(const TopoDS_Vertex& V,const TopoDS_Edge& E, |
62 | const Standard_Real D1, Standard_Real& Param1); |
63 | gp_Pnt ComputePoint(const TopoDS_Face& F, const Handle(Geom_Line)& L, |
64 | const TopoDS_Edge& E, Standard_Real& Param); |
65 | void OrientChamfer(TopoDS_Edge& chamfer, |
66 | const TopoDS_Edge& E, |
67 | const TopoDS_Vertex& V); |
68 | |
69 | static Standard_Boolean IsLineOrCircle(const TopoDS_Edge& E, |
70 | const TopoDS_Face& F); |
71 | |
72 | |
73 | //======================================================================= |
74 | //function : AddChamfer |
75 | //purpose : |
76 | //======================================================================= |
77 | |
78 | TopoDS_Edge ChFi2d_Builder::AddChamfer(const TopoDS_Edge& E1, |
79 | const TopoDS_Edge& E2, |
80 | const Standard_Real D1, |
81 | const Standard_Real D2) |
82 | { |
83 | TopoDS_Vertex commonVertex; |
84 | TopoDS_Edge basisEdge1, basisEdge2; |
85 | TopoDS_Edge E1Mod, E2Mod, chamfer; |
86 | |
87 | Standard_Boolean hasConnection = ChFi2d::CommonVertex(E1, E2, commonVertex); |
88 | if (!hasConnection) return chamfer; |
89 | |
90 | if (IsAFillet(E1) || IsAChamfer(E1) || |
91 | IsAFillet(E2) || IsAChamfer(E2)) { |
92 | status = ChFi2d_NotAuthorized; |
93 | return chamfer; |
94 | } // if (IsAChamfer ... |
95 | |
96 | if (!IsLineOrCircle(E1,newFace) |
97 | || !IsLineOrCircle(E2,newFace) ) { |
98 | status = ChFi2d_NotAuthorized; |
99 | return chamfer; |
100 | } // if (!IsLineOrCircle ... |
101 | |
102 | // EE1 and EE2 are copies of E1 and E2 with the good orientation |
103 | // on <newFace> |
104 | TopoDS_Edge EE1, EE2; |
105 | status = ChFi2d::FindConnectedEdges(newFace, commonVertex, EE1, EE2); |
106 | if (EE1.IsSame(E2)) { |
107 | TopAbs_Orientation orient = EE1.Orientation(); |
108 | EE1 = EE2; |
109 | EE2 = E2; |
110 | EE2.Orientation(orient); |
111 | } |
112 | |
113 | ComputeChamfer(commonVertex, EE1, EE2, D1, D2, |
114 | E1Mod, E2Mod, chamfer); |
115 | if (status == ChFi2d_IsDone |
116 | || status == ChFi2d_FirstEdgeDegenerated |
117 | || status == ChFi2d_LastEdgeDegenerated |
118 | || status == ChFi2d_BothEdgesDegenerated) { |
119 | // if (status == ChFi2d_IsDone) { |
120 | BuildNewWire(EE1, EE2, E1Mod, chamfer, E2Mod); |
121 | basisEdge1 = BasisEdge(EE1); |
122 | basisEdge2 = BasisEdge(EE2); |
123 | UpDateHistory(basisEdge1, basisEdge2, |
124 | E1Mod, E2Mod, chamfer, 2); |
125 | status = ChFi2d_IsDone; |
126 | return TopoDS::Edge(chamfers.Value(chamfers.Length())); |
127 | } |
128 | return chamfer; |
129 | } // AddChamfer |
130 | |
131 | |
132 | //======================================================================= |
133 | //function : AddChamfer |
134 | //purpose : |
135 | //======================================================================= |
136 | |
137 | TopoDS_Edge ChFi2d_Builder::AddChamfer(const TopoDS_Edge& E, |
138 | const TopoDS_Vertex& V, |
139 | const Standard_Real D, |
140 | const Standard_Real Ang) |
141 | { |
142 | TopoDS_Edge aChamfer, adjEdge1, adjEdge2; |
143 | status = ChFi2d::FindConnectedEdges(newFace, V, adjEdge1, adjEdge2); |
144 | if (status == ChFi2d_ConnexionError) return aChamfer; |
145 | |
146 | // adjEdge1 is a copy of E with the good orientation |
147 | // on <newFace> |
148 | if (adjEdge2.IsSame(E)) { |
149 | TopAbs_Orientation orient = adjEdge2.Orientation(); |
150 | adjEdge2 = adjEdge1; |
151 | adjEdge1 = E; |
152 | adjEdge1.Orientation(orient); |
153 | } |
154 | |
155 | if (IsAFillet(adjEdge1) || IsAChamfer(adjEdge1) || |
156 | IsAFillet(adjEdge2) || IsAChamfer(adjEdge2)) { |
157 | status = ChFi2d_NotAuthorized; |
158 | return aChamfer; |
159 | } // if (IsAChamfer ... |
160 | |
161 | if (!IsLineOrCircle(adjEdge1,newFace) |
606a112a |
162 | || !IsLineOrCircle(adjEdge2,newFace) ) { |
7fd59977 |
163 | status = ChFi2d_NotAuthorized; |
164 | return aChamfer; |
165 | } // if (!IsLineOrCircle ... |
166 | |
167 | TopoDS_Edge E1, E2; |
168 | ComputeChamfer(V, adjEdge1, D, Ang, |
169 | adjEdge2, E1, E2, aChamfer); |
170 | TopoDS_Edge basisEdge1, basisEdge2; |
171 | if (status == ChFi2d_IsDone |
172 | || status == ChFi2d_FirstEdgeDegenerated |
173 | || status == ChFi2d_LastEdgeDegenerated |
174 | || status == ChFi2d_BothEdgesDegenerated) { |
175 | // if (status == ChFi2d_IsDone) { |
176 | BuildNewWire(adjEdge1, adjEdge2, E1, aChamfer, E2); |
177 | basisEdge1 = BasisEdge(adjEdge1); |
178 | basisEdge2 = BasisEdge(adjEdge2); |
179 | UpDateHistory(basisEdge1, basisEdge2, |
180 | E1, E2, aChamfer, 2); |
181 | status = ChFi2d_IsDone; |
182 | return TopoDS::Edge(chamfers.Value(chamfers.Length())); |
183 | } |
184 | return aChamfer; |
185 | |
186 | } |
187 | |
188 | |
189 | //======================================================================= |
190 | //function : ComputeChamfer |
191 | //purpose : |
192 | //======================================================================= |
193 | |
194 | void ChFi2d_Builder::ComputeChamfer(const TopoDS_Vertex& V, |
195 | const TopoDS_Edge& E1, |
196 | const TopoDS_Edge& E2, |
197 | const Standard_Real D1, |
198 | const Standard_Real D2, |
199 | TopoDS_Edge& TrimE1, |
200 | TopoDS_Edge& TrimE2, |
201 | TopoDS_Edge& Chamfer) |
202 | { |
203 | TopoDS_Vertex newExtr1, newExtr2; |
204 | Standard_Boolean Degen1, Degen2; |
205 | Chamfer = BuildChamferEdge(V, E1, E2, D1, D2, newExtr1, newExtr2); |
206 | if ( status != ChFi2d_IsDone) return; |
207 | TrimE1 = BuildNewEdge(E1, V, newExtr1, Degen1); |
208 | TrimE2 = BuildNewEdge(E2, V, newExtr2, Degen2); |
209 | if (Degen1 && Degen2 ) status = ChFi2d_BothEdgesDegenerated; |
210 | if (Degen1 && !Degen2 ) status = ChFi2d_FirstEdgeDegenerated; |
211 | if (!Degen1 && Degen2 ) status = ChFi2d_LastEdgeDegenerated; |
212 | // TrimE1 = BuildNewEdge(E1, V, newExtr1); |
213 | // TrimE2 = BuildNewEdge(E2, V, newExtr2); |
214 | } // ComputeChamfer |
215 | |
216 | |
217 | //======================================================================= |
218 | //function : ComputeChamfer |
219 | //purpose : |
220 | //======================================================================= |
221 | |
222 | void ChFi2d_Builder::ComputeChamfer(const TopoDS_Vertex& V, |
223 | const TopoDS_Edge& E1, |
224 | const Standard_Real D, |
225 | const Standard_Real Ang, |
226 | const TopoDS_Edge& E2, |
227 | TopoDS_Edge& TrimE1, |
228 | TopoDS_Edge& TrimE2, |
229 | TopoDS_Edge& Chamfer) |
230 | { |
231 | TopoDS_Vertex newExtr1, newExtr2; |
232 | Standard_Boolean Degen1, Degen2; |
233 | Chamfer = BuildChamferEdge(V, E1, D, Ang, E2, newExtr1, newExtr2); |
234 | if ( status != ChFi2d_IsDone) return; |
235 | TrimE1 = BuildNewEdge(E1, V, newExtr1, Degen1); |
236 | TrimE2 = BuildNewEdge(E2, V, newExtr2, Degen2); |
237 | if (Degen1 && Degen2 ) status = ChFi2d_BothEdgesDegenerated; |
238 | if (Degen1 && !Degen2 ) status = ChFi2d_FirstEdgeDegenerated; |
239 | if (!Degen1 && Degen2 ) status = ChFi2d_LastEdgeDegenerated; |
240 | // TrimE1 = BuildNewEdge(E1, V, newExtr1); |
241 | // TrimE2 = BuildNewEdge(E2, V, newExtr2); |
242 | } // ComputeChamfer |
243 | |
244 | |
245 | //======================================================================= |
246 | //function : ModifyFillet |
247 | //purpose : |
248 | //======================================================================= |
249 | |
250 | TopoDS_Edge ChFi2d_Builder::ModifyChamfer(const TopoDS_Edge& Chamfer, |
35e08fe8 |
251 | const TopoDS_Edge& /*E1*/, |
7fd59977 |
252 | const TopoDS_Edge& E2, |
253 | const Standard_Real D1, |
254 | const Standard_Real D2) |
255 | { |
256 | TopoDS_Vertex aVertex = RemoveChamfer(Chamfer); |
257 | TopoDS_Edge adjEdge1, adjEdge2; |
258 | status = ChFi2d::FindConnectedEdges(newFace, aVertex, adjEdge1, adjEdge2); |
259 | TopoDS_Edge aChamfer; |
260 | if (status == ChFi2d_ConnexionError) return aChamfer; |
261 | |
262 | // adjEdge1 and adjEdge2 are copies of E1 and E2 with the good orientation |
263 | // on <newFace> |
264 | if (adjEdge1.IsSame(E2)) { |
265 | TopAbs_Orientation orient = adjEdge1.Orientation(); |
266 | adjEdge1 = adjEdge2; |
267 | adjEdge2 = E2; |
268 | adjEdge2.Orientation(orient); |
269 | } |
270 | |
271 | aChamfer = AddChamfer(adjEdge1, adjEdge2, D1, D2); |
272 | return aChamfer; |
273 | } // ModifyChamfer |
274 | |
275 | |
276 | //======================================================================= |
277 | //function : ModifyFillet |
278 | //purpose : |
279 | //======================================================================= |
280 | |
281 | TopoDS_Edge ChFi2d_Builder::ModifyChamfer(const TopoDS_Edge& Chamfer, |
282 | const TopoDS_Edge& E, |
283 | const Standard_Real D, |
284 | const Standard_Real Ang) |
285 | { |
286 | TopoDS_Vertex aVertex = RemoveChamfer(Chamfer); |
287 | TopoDS_Edge adjEdge1, adjEdge2; |
288 | status = ChFi2d::FindConnectedEdges(newFace, aVertex, adjEdge1, adjEdge2); |
289 | TopoDS_Edge aChamfer; |
290 | if (status == ChFi2d_ConnexionError) return aChamfer; |
291 | |
292 | if (adjEdge1.IsSame(E)) |
293 | aChamfer = AddChamfer(adjEdge1, aVertex, D, Ang); |
294 | else aChamfer = AddChamfer(adjEdge2, aVertex, D, Ang); |
295 | return aChamfer; |
296 | } // ModifyChamfer |
297 | |
298 | |
299 | //======================================================================= |
300 | //function : RemoveChamfer |
301 | //purpose : |
302 | //======================================================================= |
303 | |
304 | TopoDS_Vertex ChFi2d_Builder::RemoveChamfer(const TopoDS_Edge& Chamfer) |
305 | { |
306 | TopoDS_Vertex commonVertex; |
307 | |
308 | Standard_Integer i = 1; |
309 | Standard_Integer IsFind = Standard_False; |
310 | while (i <= chamfers.Length()) { |
311 | const TopoDS_Edge& aChamfer = TopoDS::Edge(chamfers.Value(i)); |
312 | if (aChamfer.IsSame(Chamfer)) { |
313 | chamfers.Remove(i); |
314 | IsFind = Standard_True; |
315 | break; |
316 | } |
317 | i++; |
318 | } |
319 | if (!IsFind) return commonVertex; |
320 | |
321 | TopoDS_Vertex firstVertex, lastVertex; |
322 | TopExp::Vertices(Chamfer, firstVertex, lastVertex); |
323 | |
324 | |
325 | TopoDS_Edge adjEdge1, adjEdge2; |
326 | status = ChFi2d::FindConnectedEdges(newFace, firstVertex, |
327 | adjEdge1, adjEdge2); |
328 | if (status == ChFi2d_ConnexionError) return commonVertex; |
329 | |
330 | TopoDS_Edge basisEdge1, basisEdge2, E1, E2; |
331 | // E1 and E2 are the adjacentes edges to Chamfer |
332 | |
333 | if (adjEdge1.IsSame(Chamfer)) E1 = adjEdge2; |
334 | else E1 = adjEdge1; |
335 | basisEdge1 = BasisEdge(E1); |
336 | status = ChFi2d::FindConnectedEdges(newFace, lastVertex,adjEdge1, adjEdge2); |
337 | if (status == ChFi2d_ConnexionError) return commonVertex; |
338 | if (adjEdge1.IsSame(Chamfer)) E2 = adjEdge2; |
339 | else E2 = adjEdge1; |
340 | basisEdge2 = BasisEdge(E2); |
341 | TopoDS_Vertex connectionE1Chamfer, connectionE2Chamfer; |
342 | Standard_Boolean hasConnection = |
343 | ChFi2d::CommonVertex(basisEdge1, basisEdge2, commonVertex); |
344 | if (!hasConnection) { |
345 | status = ChFi2d_ConnexionError; |
346 | return commonVertex; |
347 | } |
348 | hasConnection = ChFi2d::CommonVertex(E1, Chamfer, connectionE1Chamfer); |
349 | if (!hasConnection) { |
350 | status = ChFi2d_ConnexionError; |
351 | return commonVertex; |
352 | } |
353 | hasConnection = ChFi2d::CommonVertex(E2, Chamfer, connectionE2Chamfer); |
354 | if (!hasConnection) { |
355 | status = ChFi2d_ConnexionError; |
356 | return commonVertex; |
357 | } |
358 | |
359 | // rebuild edges on wire |
360 | TopoDS_Edge newEdge1, newEdge2; |
361 | TopoDS_Vertex v, v1, v2; |
362 | BRepLib_MakeEdge makeEdge; |
363 | TopLoc_Location loc; |
364 | Standard_Real first, last; |
365 | |
366 | TopExp::Vertices(E1, firstVertex, lastVertex); |
367 | TopExp::Vertices(basisEdge1, v1, v2); |
368 | if (v1.IsSame(commonVertex)) v = v2; |
369 | else v = v1; |
370 | |
371 | if ( firstVertex.IsSame(v) || lastVertex.IsSame(v)) |
372 | // It means the edge support only one fillet. In this case |
373 | // the new edge must be the basis edge. |
374 | newEdge1 = basisEdge1; |
375 | else { |
376 | // It means the edge support one fillet on each end. |
377 | if (firstVertex.IsSame(connectionE1Chamfer)) { |
378 | // syntaxe invalide sur NT |
379 | // const Handle(Geom_Curve)& curve = |
380 | // BRep_Tool::Curve(E1, loc, first, last); |
381 | Handle(Geom_Curve) curve = BRep_Tool::Curve(E1, loc, first, last); |
382 | makeEdge.Init(curve, commonVertex, lastVertex); |
383 | newEdge1 = makeEdge.Edge(); |
384 | newEdge1.Orientation(basisEdge1.Orientation()); |
385 | newEdge1.Location(basisEdge1.Location()); |
386 | } // if (firstVertex ... |
387 | else if (lastVertex.IsSame(connectionE1Chamfer)) { |
388 | // syntaxe invalide sur NT |
389 | // const Handle(Geom_Curve)& curve = |
390 | // BRep_Tool::Curve(E1, loc, first, last); |
391 | Handle(Geom_Curve) curve = BRep_Tool::Curve(E1, loc, first, last); |
392 | makeEdge.Init(curve, firstVertex, commonVertex); |
393 | newEdge1 = makeEdge.Edge(); |
394 | newEdge1.Orientation(basisEdge1.Orientation()); |
395 | newEdge1.Location(basisEdge1.Location()); |
396 | } // else if (lastVertex ... |
397 | } // else ... |
398 | |
399 | TopExp::Vertices(basisEdge2, v1, v2); |
400 | if (v1.IsSame(commonVertex)) v = v2; |
401 | else v = v1; |
402 | |
403 | TopExp::Vertices(E2, firstVertex, lastVertex); |
404 | if ( firstVertex.IsSame(v) || lastVertex.IsSame(v)) |
405 | // It means the edge support only one fillet. In this case |
406 | // the new edge must be the basis edge. |
407 | newEdge2 = basisEdge2; |
408 | else { |
409 | // It means the edge support one fillet on each end. |
410 | if (firstVertex.IsSame(connectionE2Chamfer)) { |
411 | // syntaxe invalide sur NT |
412 | // const Handle(Geom_Curve)& curve = |
413 | // BRep_Tool::Curve(E2, loc, first, last); |
414 | Handle(Geom_Curve) curve = BRep_Tool::Curve(E2, loc, first, last); |
415 | makeEdge.Init(curve, commonVertex, lastVertex); |
416 | newEdge2 = makeEdge.Edge(); |
417 | newEdge2.Orientation(basisEdge2.Orientation()); |
418 | newEdge2.Location(basisEdge2.Location()); |
419 | } // if (firstVertex ... |
420 | else if (lastVertex.IsSame(connectionE2Chamfer)) { |
421 | // syntaxe invalide sur NT |
422 | // const Handle(Geom_Curve)& curve = |
423 | // BRep_Tool::Curve(E2, loc, first, last); |
424 | Handle(Geom_Curve) curve = BRep_Tool::Curve(E2, loc, first, last); |
425 | makeEdge.Init(curve, firstVertex, commonVertex); |
426 | newEdge2 = makeEdge.Edge(); |
427 | newEdge2.Orientation(basisEdge2.Orientation()); |
428 | newEdge2.Location(basisEdge2.Location()); |
429 | } // else if (lastVertex ... |
430 | } // else ... |
431 | |
432 | // rebuild the newFace |
433 | TopExp_Explorer Ex(newFace, TopAbs_EDGE); |
434 | TopoDS_Wire newWire; |
435 | |
436 | BRep_Builder B; |
437 | B.MakeWire(newWire); |
438 | |
439 | while (Ex.More()) { |
440 | const TopoDS_Edge& theEdge = TopoDS::Edge(Ex.Current()); |
441 | if (!theEdge.IsSame(E1) && |
442 | !theEdge.IsSame(E2) && |
443 | !theEdge.IsSame(Chamfer) ) |
444 | B.Add(newWire, theEdge); |
445 | else { |
446 | if (theEdge == E1) |
447 | B.Add(newWire, newEdge1); |
448 | else if (theEdge == E2) |
449 | B.Add(newWire, newEdge2); |
450 | } // else |
451 | Ex.Next(); |
452 | } // while ... |
453 | |
454 | BRepAdaptor_Surface Adaptor3dSurface(refFace); |
455 | BRepLib_MakeFace mFace(Adaptor3dSurface.Plane(), newWire); |
456 | newFace.Nullify(); |
457 | newFace = mFace; |
458 | |
459 | UpDateHistory(basisEdge1, basisEdge2, newEdge1, newEdge2); |
460 | |
461 | return commonVertex; |
462 | } // RemoveChamfer |
463 | |
464 | |
465 | //======================================================================= |
466 | //function : BuildChamferEdge |
467 | //purpose : |
468 | //======================================================================= |
469 | TopoDS_Edge ChFi2d_Builder::BuildChamferEdge(const TopoDS_Vertex& V, |
470 | const TopoDS_Edge& AdjEdge1, |
471 | const TopoDS_Edge& AdjEdge2, |
472 | const Standard_Real D1, |
473 | const Standard_Real D2, |
474 | TopoDS_Vertex& NewExtr1, |
475 | TopoDS_Vertex& NewExtr2) |
476 | { |
477 | TopoDS_Edge chamfer; |
478 | if ( D1 <= 0 || D2 <= 0) { |
479 | status = ChFi2d_ParametersError; |
480 | return chamfer; |
481 | } // if ( D1 <=0 ... |
482 | |
483 | Standard_Real param1, param2; |
484 | gp_Pnt p1 = ComputePoint(V, AdjEdge1, D1, param1); |
485 | gp_Pnt p2 = ComputePoint(V, AdjEdge2, D2, param2); |
486 | |
487 | Standard_Real tol = Precision::Confusion(); |
488 | BRep_Builder B; |
489 | B.MakeVertex(NewExtr1, p1, tol); |
490 | B.MakeVertex(NewExtr2, p2, tol); |
491 | NewExtr1.Orientation(TopAbs_FORWARD); |
492 | NewExtr2.Orientation(TopAbs_REVERSED); |
493 | |
494 | // chamfer edge construction |
495 | TopLoc_Location loc; |
496 | const Handle(Geom_Surface) refSurf = BRep_Tool::Surface(refFace, loc); |
497 | gp_Vec myVec( p1, p2); |
498 | gp_Dir myDir(myVec); |
499 | Handle(Geom_Line) newLine = new Geom_Line( p1, myDir); |
500 | Standard_Real param = ElCLib::Parameter(newLine->Lin(), p2); |
501 | B.MakeEdge(chamfer, newLine, tol); |
502 | B.Range(chamfer,0., param); |
503 | B.Add(chamfer, NewExtr1); |
504 | B.UpdateVertex(NewExtr1,0., chamfer, tol); |
505 | B.Add(chamfer, NewExtr2); |
506 | B.UpdateVertex(NewExtr2,param, chamfer, tol); |
507 | OrientChamfer(chamfer, AdjEdge1, V); |
508 | |
509 | // set the orientation of NewExtr1 and NewExtr2 for the adjacent edges |
510 | TopoDS_Vertex V1 = TopExp::FirstVertex(AdjEdge1); |
511 | TopoDS_Vertex V2 = TopExp::LastVertex(AdjEdge1); |
512 | if (V1.IsSame(V)) NewExtr1.Orientation(V1.Orientation()); |
513 | else NewExtr1.Orientation(V2.Orientation()); |
514 | |
515 | V1 = TopExp::FirstVertex(AdjEdge2); |
516 | V2 = TopExp::LastVertex(AdjEdge2); |
517 | if (V1.IsSame(V)) NewExtr2.Orientation(V1.Orientation()); |
518 | else NewExtr2.Orientation(V2.Orientation()); |
519 | B.UpdateVertex(NewExtr1, param1, AdjEdge1, tol); |
520 | B.UpdateVertex(NewExtr2, param2, AdjEdge2, tol); |
521 | |
522 | status = ChFi2d_IsDone; |
523 | return chamfer; |
524 | } // BuildChamferEdge |
525 | |
526 | |
527 | //======================================================================= |
528 | //function : BuildFilletEdge |
529 | //purpose : |
530 | //======================================================================= |
531 | TopoDS_Edge ChFi2d_Builder::BuildChamferEdge(const TopoDS_Vertex& V, |
532 | const TopoDS_Edge& AdjEdge1, |
533 | const Standard_Real D, |
534 | const Standard_Real Ang, |
535 | const TopoDS_Edge& AdjEdge2, |
536 | TopoDS_Vertex& NewExtr1, |
537 | TopoDS_Vertex& NewExtr2) |
538 | { |
539 | TopoDS_Edge chamfer; |
540 | if ( D <= 0 || Ang <= 0) { |
541 | status = ChFi2d_ParametersError; |
542 | return chamfer; |
543 | } // if ( D <= 0 ... |
544 | |
545 | Standard_Real param1, param2; |
546 | gp_Pnt p1 = ComputePoint(V, AdjEdge1, D, param1); |
547 | gp_Pnt p = BRep_Tool::Pnt(V); |
548 | gp_Vec myVec( p1, p); |
549 | |
550 | // compute the tangent vector on AdjEdge2 at the vertex V. |
551 | BRepAdaptor_Curve c(AdjEdge2, refFace); |
552 | Standard_Real first, last; |
553 | first = c.FirstParameter(); |
554 | last = c.LastParameter(); |
555 | |
556 | gp_Pnt aPoint; |
557 | gp_Vec tan; |
558 | c.D1(first, aPoint, tan); |
559 | if (aPoint.Distance(p) > Precision::Confusion()) { |
560 | c.D1(last, aPoint, tan); |
561 | } |
562 | // tangent orientation |
563 | TopoDS_Vertex v1, v2; |
564 | TopExp::Vertices(AdjEdge2, v1, v2); |
565 | TopAbs_Orientation orient; |
566 | if (v1.IsSame(V)) orient = v1.Orientation(); |
567 | else orient = v2.Orientation(); |
568 | if (orient == TopAbs_REVERSED) tan *= -1; |
569 | |
570 | // compute the chamfer geometric support |
571 | gp_Ax1 RotAxe(p1, tan^myVec); |
572 | gp_Vec vecLin = myVec.Rotated(RotAxe, -Ang); |
573 | gp_Dir myDir(vecLin); |
574 | Handle(Geom_Line) newLine = new Geom_Line( p1, myDir); |
575 | BRep_Builder B1; |
576 | B1.MakeEdge(chamfer, newLine, Precision::Confusion()); |
577 | gp_Pnt p2 = ComputePoint(refFace, newLine, AdjEdge2, param2); |
578 | |
579 | |
580 | Standard_Real tol = Precision::Confusion(); |
581 | BRep_Builder B; |
582 | B.MakeVertex(NewExtr1, p1, tol); |
583 | B.MakeVertex(NewExtr2, p2, tol); |
584 | NewExtr1.Orientation(TopAbs_FORWARD); |
585 | NewExtr2.Orientation(TopAbs_REVERSED); |
586 | |
587 | // chamfer edge construction |
588 | Standard_Real param = ElCLib::Parameter(newLine->Lin(), p2); |
589 | B.MakeEdge(chamfer, newLine, tol); |
590 | B.Range(chamfer,0., param); |
591 | B.Add(chamfer, NewExtr1); |
592 | B.UpdateVertex(NewExtr1,0., chamfer, tol); |
593 | B.Add(chamfer, NewExtr2); |
594 | B.UpdateVertex(NewExtr2,param, chamfer, tol); |
595 | OrientChamfer(chamfer, AdjEdge1, V); |
596 | |
597 | // set the orientation of NewExtr1 and NewExtr2 for the adjacent edges |
598 | TopoDS_Vertex V1 = TopExp::FirstVertex(AdjEdge1); |
599 | TopoDS_Vertex V2 = TopExp::LastVertex(AdjEdge1); |
600 | if (V1.IsSame(V)) NewExtr1.Orientation(V1.Orientation()); |
601 | else NewExtr1.Orientation(V2.Orientation()); |
602 | |
603 | V1 = TopExp::FirstVertex(AdjEdge2); |
604 | V2 = TopExp::LastVertex(AdjEdge2); |
605 | if (V1.IsSame(V)) NewExtr2.Orientation(V1.Orientation()); |
606 | else NewExtr2.Orientation(V2.Orientation()); |
607 | B.UpdateVertex(NewExtr1, param1, AdjEdge1, tol); |
608 | B.UpdateVertex(NewExtr2, param2, AdjEdge2, tol); |
609 | |
610 | status = ChFi2d_IsDone; |
611 | return chamfer; |
612 | } |
613 | |
614 | |
615 | //======================================================================= |
616 | //function : ComputePoint |
617 | //purpose : |
618 | //======================================================================= |
619 | |
620 | gp_Pnt ComputePoint(const TopoDS_Vertex& V,const TopoDS_Edge& E, |
621 | const Standard_Real D, Standard_Real& Param) |
622 | { |
623 | // geometric support |
624 | BRepAdaptor_Curve c(E); |
625 | Standard_Real first, last; |
626 | first = c.FirstParameter(); |
627 | last = c.LastParameter(); |
628 | |
629 | gp_Pnt thePoint; |
630 | if (c.GetType() == GeomAbs_Line) { |
631 | gp_Pnt p1, p2; |
632 | TopoDS_Vertex v1, v2; |
633 | TopExp::Vertices(E, v1, v2); |
634 | p1 = BRep_Tool::Pnt(v1); |
635 | p2 = BRep_Tool::Pnt(v2); |
636 | gp_Vec myVec( p1, p2); |
637 | myVec.Normalize(); |
638 | myVec *= D; |
639 | if (v2.IsSame(V)) { |
640 | myVec *= -1; // change the sense of myVec |
641 | thePoint = p2.Translated(myVec); |
642 | } // if (v2 ... |
643 | else thePoint = p1.Translated(myVec); |
644 | |
645 | Param = ElCLib::Parameter(c.Line(), thePoint); |
646 | //szv:OCC20823-begin |
647 | c.D0(Param, thePoint); |
648 | //szv:OCC20823-end |
649 | return thePoint; |
650 | } // if (C->IsKind(TYPE ... |
651 | |
652 | if (c.GetType() == GeomAbs_Circle) { |
653 | gp_Circ cir = c.Circle(); |
654 | Standard_Real radius = cir.Radius(); |
655 | TopoDS_Vertex v1, v2; |
656 | TopExp::Vertices(E, v1, v2); |
657 | Standard_Real param1,param2; |
658 | if (V.IsSame(v1)) { |
659 | param1 = BRep_Tool::Parameter(v1,E); |
660 | param2 = BRep_Tool::Parameter(v2,E); |
661 | } |
662 | else { |
663 | param1 = BRep_Tool::Parameter(v2,E); |
664 | param2 = BRep_Tool::Parameter(v1,E); |
665 | } |
666 | Standard_Real deltaAlpha = D/radius; |
667 | if (param1 > param2) Param = param1 - deltaAlpha; |
668 | else Param = param1 + deltaAlpha; |
669 | c.D0(Param, thePoint); |
670 | return thePoint; |
671 | } // if (C->IsKind(TYPE ... |
672 | |
673 | else { |
674 | // in all other case than lines and circles. |
675 | gp_Pnt p; |
676 | TopoDS_Vertex v1, v2; |
677 | TopExp::Vertices(E, v1, v2); |
678 | if (V.IsSame(v1)) { |
679 | p = BRep_Tool::Pnt(v1); |
680 | } |
681 | else { |
682 | p = BRep_Tool::Pnt(v2); |
683 | } |
684 | |
685 | GeomAdaptor_Curve cc = c.Curve(); |
686 | if (p.Distance(c.Value(first)) <= Precision::Confusion()) { |
687 | GCPnts_AbscissaPoint computePoint(cc, D, first); |
688 | Param = computePoint.Parameter(); |
689 | } |
690 | else { |
691 | GCPnts_AbscissaPoint computePoint(cc, D, last); |
692 | Param = computePoint.Parameter(); |
693 | } |
694 | thePoint = cc.Value(Param); |
695 | return thePoint; |
696 | } // else ... |
7fd59977 |
697 | } // ComputePoint |
698 | |
699 | |
700 | |
701 | //======================================================================= |
702 | //function : ComputePoint |
703 | //purpose : |
704 | //======================================================================= |
705 | |
706 | gp_Pnt ComputePoint(const TopoDS_Face& F, |
707 | const Handle(Geom_Line)& L, |
708 | const TopoDS_Edge& E, |
709 | Standard_Real& Param) |
710 | { |
711 | BRepAdaptor_Surface Adaptor3dSurface(F); |
712 | Handle(Geom_Plane) refSurf = new Geom_Plane(Adaptor3dSurface.Plane()); |
713 | Handle(Geom2d_Curve) lin2d = GeomAPI::To2d(L, refSurf->Pln()); |
714 | Handle(Geom2d_Curve) c2d; |
715 | Standard_Real first, last; |
716 | c2d = BRep_Tool::CurveOnSurface(E, F, first, last); |
717 | Geom2dAdaptor_Curve adaptorL(lin2d); |
718 | Geom2dAdaptor_Curve adaptorC(c2d); |
719 | Geom2dInt_GInter Intersection(adaptorL, adaptorC, |
720 | Precision::PIntersection(), |
721 | Precision::PIntersection()); |
722 | Standard_Real paramOnLine = 1E300; |
723 | gp_Pnt2d p2d; |
724 | if (Intersection.IsDone()) { |
725 | Standard_Integer i = 1; |
726 | while ( i <= Intersection.NbPoints()) { |
727 | IntRes2d_IntersectionPoint iP = Intersection.Point(i); |
728 | if (iP.ParamOnFirst() < paramOnLine) { |
729 | p2d = iP.Value(); |
730 | paramOnLine = iP.ParamOnFirst(); |
731 | Param = iP.ParamOnSecond(); |
732 | } // if (iP.ParamOnFirst ... |
733 | i++; |
734 | } // while ( i <= ... |
735 | } // if (Intersection.IsDone ... |
736 | |
737 | gp_Pnt thePoint = Adaptor3dSurface.Value(p2d.X(), p2d.Y()); |
738 | return thePoint; |
739 | } // ComputePoint |
740 | |
741 | //======================================================================= |
742 | //function : OrientChamfer |
743 | //purpose : |
744 | //======================================================================= |
745 | |
746 | void OrientChamfer(TopoDS_Edge& chamfer, |
747 | const TopoDS_Edge& E, |
748 | const TopoDS_Vertex& V) |
749 | { |
750 | TopAbs_Orientation vOrient, orient = E.Orientation(); |
751 | TopoDS_Vertex v1, v2; |
752 | TopExp::Vertices(E, v1, v2); |
753 | if (v1.IsSame(V)) vOrient = v2.Orientation(); |
754 | else vOrient = v1.Orientation(); |
755 | |
756 | if ((orient == TopAbs_FORWARD && vOrient == TopAbs_FORWARD) || |
757 | (orient == TopAbs_REVERSED && vOrient == TopAbs_REVERSED)) |
758 | chamfer.Orientation(TopAbs_FORWARD); |
759 | else chamfer.Orientation(TopAbs_REVERSED); |
760 | } // OrientChamfer |
761 | |
762 | |
763 | //======================================================================= |
764 | //function : IsLineOrCircle |
765 | //purpose : |
766 | //======================================================================= |
767 | |
768 | Standard_Boolean IsLineOrCircle(const TopoDS_Edge& E, |
769 | const TopoDS_Face& F) |
770 | { |
771 | Standard_Real first, last; |
772 | TopLoc_Location loc; |
773 | // syntaxe invalide sur NT |
774 | // const Handle(Geom2d_Curve)& C = |
775 | // BRep_Tool::CurveOnSurface(E,F,first,last); |
776 | Handle(Geom2d_Curve) C = BRep_Tool::CurveOnSurface(E,F,first,last); |
777 | Handle(Geom2d_Curve) basisC; |
778 | Handle(Geom2d_TrimmedCurve) TC = Handle(Geom2d_TrimmedCurve)::DownCast(C); |
779 | if (!TC.IsNull()) |
a9dde4a3 |
780 | basisC = TC->BasisCurve(); |
7fd59977 |
781 | else |
a9dde4a3 |
782 | basisC = C; |
7fd59977 |
783 | |
784 | if ( basisC->DynamicType() == STANDARD_TYPE(Geom2d_Circle) |
785 | || basisC->DynamicType() == STANDARD_TYPE(Geom2d_Line) ) { |
786 | return Standard_True; |
787 | } |
788 | else { |
789 | return Standard_False; |
790 | } // else ... |
791 | } // IsLineOrCircle |