1 // Created by: Joelle CHAUVET
2 // Copyright (c) 1996-1999 Matra Datavision
3 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 // Modified: Tue Oct 15 10:12:02 1996
17 // Add ChFi2d_TangencyError (PRO3529)
18 // Modified: Fri Sep 25 09:38:04 1998
19 // status = ChFi2d_NotAuthorized if edges are not
20 // lines or circles (BUC60288) + partial_result
23 #include <TColgp_Array1OfPnt2d.hxx>
24 #include <BRepTest.hxx>
26 #include <Draw_Interpretor.hxx>
27 #include <Draw_Appli.hxx>
28 #include <BRepFilletAPI_MakeFillet2d.hxx>
29 #include <TopAbs_ShapeEnum.hxx>
30 #include <TopoDS_Shape.hxx>
31 #include <TopoDS_Edge.hxx>
32 #include <TopoDS_Vertex.hxx>
33 #include <TopExp_Explorer.hxx>
36 #include <TopTools_MapOfShape.hxx>
38 #include <ChFi2d_FilletAPI.hxx>
39 #include <ChFi2d_ChamferAPI.hxx>
41 #include <BRepBuilderAPI_MakeWire.hxx>
42 #include <BRepBuilderAPI_FindPlane.hxx>
43 #include <BRep_Builder.hxx>
45 //=======================================================================
47 //purpose : 2d fillets and chamfers
48 //=======================================================================
50 static Standard_Integer chfi2d(Draw_Interpretor& di, Standard_Integer n, const char** a)
53 di << "chfi2d : not enough args";
57 // set up the algorithm
58 TopoDS_Shape F = DBRep::Get(a[2],TopAbs_FACE);
60 di << "chfi2d : "<< a[2] << " not a face";
64 BRepFilletAPI_MakeFillet2d MF(TopoDS::Face(F));
65 if (MF.Status() == ChFi2d_NotPlanar) {
66 di << "chfi2d : not a planar face";
71 Standard_Boolean partial_result = Standard_False;
72 Standard_Integer i = 3;
75 TopoDS_Shape aLocalEdge(DBRep::Get(a[i],TopAbs_EDGE));
76 TopoDS_Edge E1 = TopoDS::Edge(aLocalEdge);
77 aLocalEdge = DBRep::Get(a[i+1],TopAbs_EDGE);
78 TopoDS_Edge E2 = TopoDS::Edge(aLocalEdge);
79 // TopoDS_Edge E1 = TopoDS::Edge(DBRep::Get(a[i],TopAbs_EDGE));
80 // TopoDS_Edge E2 = TopoDS::Edge(DBRep::Get(a[i+1],TopAbs_EDGE));
82 if (E1.IsNull() || E2.IsNull()) {
83 di << "chfi2d : " << a[i] << " or " << a[i+1] << " not an edge";
85 di <<" WARNING : this is a partial result ";
92 if (!TopExp::CommonVertex(E1,E2,V)) {
93 di << "chfi2d " << a[i] << " and " << a[i+1] << " does not share a vertex";
95 di <<" WARNING : this is a partial result ";
103 di << "chfi2d : not enough args";
104 if (partial_result) {
105 di <<" WARNING : this is a partial result ";
106 DBRep::Set(a[1],res);
111 Standard_Real p1 = Draw::Atof(a[i+1]);
117 di << "chfi2d : not enough args";
118 if (partial_result) {
119 di <<" WARNING : this is a partial result ";
120 DBRep::Set(a[1],res);
124 Standard_Real p2 = Draw::Atof(a[i+2]);
125 if (a[i][2] == 'D') {
126 MF.AddChamfer(E1,E2,p1,p2);
129 MF.AddChamfer(E1,V,p1,p2 * (M_PI / 180.0));
133 if (MF.Status() == ChFi2d_TangencyError) {
134 di << "chfi2d : " << a[i-2] << " and " << a[i-1] << " are tangent ";
135 if (partial_result) {
136 di <<" WARNING : this is a partial result ";
137 DBRep::Set(a[1],res);
142 if (MF.Status() == ChFi2d_NotAuthorized) {
143 di << "chfi2d : " << a[i-2] << " or " << a[i-1] << " is not a line or a circle ";
144 if (partial_result) {
145 di <<" WARNING : this is a partial result ";
146 DBRep::Set(a[1],res);
151 if (MF.Status() != ChFi2d_IsDone) {
152 di << "chfi2d : operation failed on " << a[i-2];
153 if (partial_result) {
154 di <<" WARNING : this is a partial result ";
155 DBRep::Set(a[1],res);
160 partial_result = Standard_True;
179 //=======================================================================
180 //function : fillet2d
181 //purpose : A method to find a plane for 2 edges.
182 // : It may return a NULL object of the plane is not found
183 // : (the edge are located not in a plane).
184 //=======================================================================
186 static Handle(Geom_Plane) findPlane(const TopoDS_Shape& S)
188 Handle(Geom_Plane) plane;
189 BRepBuilderAPI_FindPlane planeFinder(S);
190 if (planeFinder.Found())
191 plane = planeFinder.Plane();
195 static Handle(Geom_Plane) findPlane(const TopoDS_Shape& E1, const TopoDS_Shape& E2)
205 //=======================================================================
206 //function : findCommonPoint
207 //purpose : Find a common (or the most close) point of two edges.
208 //=======================================================================
210 static gp_Pnt findCommonPoint(const TopoDS_Shape& E1, const TopoDS_Shape& E2)
212 TopoDS_Vertex v11, v12, v21, v22;
213 TopExp::Vertices(TopoDS::Edge(E1), v11, v12);
214 TopExp::Vertices(TopoDS::Edge(E2), v21, v22);
216 gp_Pnt p11 = BRep_Tool::Pnt(v11);
217 gp_Pnt p12 = BRep_Tool::Pnt(v12);
218 gp_Pnt p21 = BRep_Tool::Pnt(v21);
219 gp_Pnt p22 = BRep_Tool::Pnt(v22);
222 const double d1121 = p11.SquareDistance(p21);
223 const double d1122 = p11.SquareDistance(p22);
224 const double d1221 = p12.SquareDistance(p21);
225 const double d1222 = p12.SquareDistance(p22);
226 if (d1121 < d1122 && d1121 < d1221 && d1121 < d1222)
228 else if (d1122 < d1121 && d1122 < d1221 && d1122 < d1222)
230 else if (d1221 < d1121 && d1221 < d1122 && d1221 < d1222)
232 else if (d1222 < d1121 && d1222 < d1122 && d1222 < d1221)
238 static gp_Pnt findCommonPoint(const TopoDS_Shape& W)
240 // The common point for two edges inside a wire
241 // is a sharing vertex of two edges.
242 TopTools_MapOfShape vertices;
243 TopExp_Explorer expl(W, TopAbs_VERTEX);
244 for (; expl.More(); expl.Next())
246 if (!vertices.Add(expl.Current()))
248 return BRep_Tool::Pnt(TopoDS::Vertex(expl.Current()));
251 return gp::Origin(); // not found
254 //=======================================================================
255 //function : fillet2d
256 //purpose : Fillet 2d based on Newton method (recursive, iteration)
257 //usage : fillet2d result wire (or edge1 edge2) radius
258 //=======================================================================
260 static Standard_Integer fillet2d(Draw_Interpretor& di, Standard_Integer n, const char** a)
262 if (n != 4 && n != 5)
264 di << "Usage : fillet2d result wire (or edge1 edge2) radius";
268 TopoDS_Shape E1, E2, W;
272 E1 = DBRep::Get(a[2], TopAbs_EDGE, Standard_True);
273 E2 = DBRep::Get(a[3], TopAbs_EDGE, Standard_True);
278 W = DBRep::Get(a[2], TopAbs_WIRE, Standard_True);
281 // Get the radius value.
282 const Standard_Real radius = Atof(n == 5 ? a[4] : a[3]);
284 // Find plane of the edges.
285 Handle(Geom_Plane) hPlane = n == 5 ? findPlane(E1, E2) : findPlane(W);
288 di << "Error: the edges are located not in a plane.";
293 ChFi2d_FilletAPI algo;
294 gp_Pln plane = hPlane->Pln();
297 const TopoDS_Edge& e1 = TopoDS::Edge(E1);
298 const TopoDS_Edge& e2 = TopoDS::Edge(E2);
299 algo.Init(e1, e2, plane);
303 const TopoDS_Wire& w = TopoDS::Wire(W);
306 Standard_Boolean status = algo.Perform(radius);
309 di << "Error: the algrithm failed.";
313 // Find a common point of the edges.
314 gp_Pnt common = n == 5 ? findCommonPoint(E1, E2) : findCommonPoint(W);
316 // Get the number of solutions (usually it is equal to 1).
317 Standard_Integer nbSolutions = algo.NbResults(common);
320 di << "Error: no solutions.";
324 // Get the result for the "nearest" solution (near the common point).
325 TopoDS_Edge M1, M2; // modified E1 and E2
326 TopoDS_Edge fillet = algo.Result(common, M1, M2);
329 di << "Error: the algrithm produced no result.";
333 // Set result for DRAW.
334 DBRep::Set(a[1], fillet);
336 // Update neighbour edges in DRAW.
339 DBRep::Set(a[2], M1);
340 DBRep::Set(a[3], M2);
342 else // recreate the wire using the fillet
344 BRepBuilderAPI_MakeWire mkWire(M1, fillet, M2);
346 DBRep::Set(a[1], mkWire.Wire());
348 DBRep::Set(a[1], fillet);
353 //=======================================================================
354 //function : chamfer2d
355 //purpose : Chamfer 2d.
356 //usage : chamfer2d result wire (or edge1 edge2) length1 length2
357 //=======================================================================
359 static Standard_Integer chamfer2d(Draw_Interpretor& di, Standard_Integer n, const char** a)
361 if (n != 5 && n != 6)
363 di << "Usage : chamfer2d result wire (or edge1 edge2) length1 length2";
372 E1 = DBRep::Get(a[2], TopAbs_EDGE, Standard_True);
373 E2 = DBRep::Get(a[3], TopAbs_EDGE, Standard_True);
377 W = DBRep::Get(a[2], TopAbs_WIRE, Standard_True);
381 const Standard_Real length1 = (n == 6) ? Atof(a[4]) : Atof(a[3]);
382 const Standard_Real length2 = (n == 6) ? Atof(a[5]) : Atof(a[4]);
385 ChFi2d_ChamferAPI algo;
388 const TopoDS_Edge& e1 = TopoDS::Edge(E1);
389 const TopoDS_Edge& e2 = TopoDS::Edge(E2);
394 const TopoDS_Wire& w = TopoDS::Wire(W);
398 // Prepare the chamfer.
402 TopoDS_Edge M1, M2; // modified E1 and E2
403 TopoDS_Edge chamfer = algo.Result(M1, M2, length1, length2);
404 if (chamfer.IsNull())
406 di << "Error: the algrithm produced no result.";
412 // Set result for DRAW.
413 DBRep::Set(a[1], chamfer);
415 // Update neighbour edges in DRAW.
416 DBRep::Set(a[2], M1);
417 DBRep::Set(a[3], M2);
419 else // recreate the wire using the chamfer
421 BRepBuilderAPI_MakeWire mkWire(M1, chamfer, M2);
423 DBRep::Set(a[1], mkWire.Wire());
425 DBRep::Set(a[1], chamfer);
431 //=======================================================================
432 //function : Fillet2DCommands
434 //=======================================================================
436 void BRepTest::Fillet2DCommands(Draw_Interpretor& theCommands)
438 static Standard_Boolean done = Standard_False;
440 done = Standard_True;
442 DBRep::BasicCommands(theCommands);
444 const char* g = "TOPOLOGY Fillet2D construction commands";
446 theCommands.Add("chfi2d","chfi2d result face [edge1 edge2 (F radius/CDD d1 d2/CDA d ang) ....]",__FILE__,chfi2d,g);
447 theCommands.Add("fillet2d","fillet2d result wire (or edge1 edge2) radius",__FILE__,fillet2d,g);
448 theCommands.Add("chamfer2d","chamfer2d result wire (or edge1 edge2) length1 length2",__FILE__,chamfer2d,g);