1 // Copyright (C) 2007-2011 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // GEOM SKETCHER : basic sketcher
24 // File : Sketcher_Profile.cxx
25 // Author : Damien COQUERET
29 #include <Standard_Stream.hxx>
31 #include <Sketcher_Profile.hxx>
33 #include <TopoDS_Vertex.hxx>
34 #include <TopoDS_Face.hxx>
35 #include <BRepLib.hxx>
36 #include <BRepBuilderAPI_MakeVertex.hxx>
37 #include <BRepBuilderAPI_MakeEdge.hxx>
38 #include <BRepBuilderAPI_MakeWire.hxx>
39 #include <BRepBuilderAPI_MakeFace.hxx>
41 #include <GeomAPI.hxx>
42 #include <Geom2d_Line.hxx>
43 #include <Geom2d_Circle.hxx>
44 #include <Geom_Surface.hxx>
46 #include <Precision.hxx>
50 #include <TCollection_AsciiString.hxx>
51 #include <TColStd_Array1OfAsciiString.hxx>
53 #include "utilities.h"
55 //=======================================================================
57 // command to build a profile
58 //=======================================================================
59 Sketcher_Profile::Sketcher_Profile()
64 //=======================================================================
66 // command to build a profile
67 //=======================================================================
68 Sketcher_Profile::Sketcher_Profile(const char* aCmd)
70 enum {line, circle, point, none} move;
72 Standard_Integer i = 1;
73 Standard_Real x0, y0, x, y, dx, dy;
74 x0 = y0 = x = y = dy = 0;
77 Standard_Boolean first, stayfirst, face, close;
78 first = Standard_True;
79 stayfirst = face = close = Standard_False;
81 Standard_Integer reversed = 0;
82 Standard_Integer control_Tolerance = 0;
86 BRepBuilderAPI_MakeWire MW;
87 gp_Ax3 DummyHP(gp::XOY());
89 TopLoc_Location TheLocation;
90 Handle(Geom_Surface) Surface;
92 myOK = Standard_False;
95 //TCollection_AsciiString aCommand(CORBA::string_dup(aCmd));
96 TCollection_AsciiString aCommand ((char*)aCmd);
97 TCollection_AsciiString aToken = aCommand.Token(":", 1);
100 TColStd_Array1OfAsciiString aTab (0, aCommand.Length() - 1);
101 if ( aCommand.Length() )
103 while(aToken.Length() != 0) {
104 if(aCommand.Token(":", n + 1).Length() > 0)
105 aTab(n) = aCommand.Token(":", n + 1);
106 aToken = aCommand.Token(":", ++n);
110 if ( aTab.Length() && aTab(0).Length() )
112 Standard_Real length = 0, radius = 0, angle = 0;
116 TColStd_Array1OfAsciiString a (0, aTab(0).Length());
117 aToken = aTab(i).Token(" ", 1);
118 while (aToken.Length() != 0) {
119 if (aTab(i).Token(" ", n1 + 1).Length() > 0)
120 a(n1) = aTab(i).Token(" ", n1 + 1);
121 aToken = aTab(i).Token(" ", ++n1);
125 switch(a(0).Value(1))
129 if (n1 != 3) goto badargs;
131 MESSAGE("profile : The F instruction must precede all moves");
134 x0 = x = a(1).RealValue();
135 y0 = y = a(2).RealValue();
136 stayfirst = Standard_True;
141 if (n1 != 4) goto badargs;
142 P.SetLocation(gp_Pnt(a(1).RealValue(), a(2).RealValue(), a(3).RealValue()));
143 stayfirst = Standard_True;
148 if (n1 != 7) goto badargs;
149 gp_Vec vn(a(1).RealValue(), a(2).RealValue(), a(3).RealValue());
150 gp_Vec vx(a(4).RealValue(), a(5).RealValue(), a(6).RealValue());
151 if (vn.Magnitude() <= Precision::Confusion() || vx.Magnitude() <= Precision::Confusion()) {
152 MESSAGE("profile : null direction");
155 gp_Ax2 ax(P.Location(), vn, vx);
157 stayfirst = Standard_True;
162 if (n1 != 2) goto badargs;
163 length = a(1).RealValue();
172 if (n1 != 2) goto badargs;
173 length = a(1).RealValue();
182 if (n1 != 2) goto badargs;
183 length = a(1).RealValue();
184 if (Abs(length) > Precision::Confusion())
192 if (n1 != 3) goto badargs;
193 Standard_Real vx = a(1).RealValue();
194 Standard_Real vy = a(2).RealValue();
199 length = Sqrt(vx * vx + vy * vy);
200 if (length > Precision::Confusion()) {
211 if (n1 != 2) goto badargs;
212 angle = a(1).RealValue() * PI180;
218 Standard_Real c = Cos(angle);
219 Standard_Real s = Sin(angle);
220 Standard_Real t = c * dx - s * dy;
221 dy = s * dx + c * dy;
228 if (n1 != 3) goto badargs;
229 Standard_Real vx = a(1).RealValue();
230 Standard_Real vy = a(2).RealValue();
231 length = Sqrt(vx * vx + vy * vy);
232 if (length > Precision::Confusion()) {
242 if (n1 != 3) goto badargs;
243 radius = a(1).RealValue();
244 if (Abs(radius) > Precision::Confusion()) {
245 angle = a(2).RealValue() * PI180;
252 case 'A': // TAngential arc by end point
254 if (n1 != 3) goto badargs;
255 Standard_Real vx = a(1).RealValue();
256 Standard_Real vy = a(2).RealValue();
261 Standard_Real det = dx * vy - dy * vx;
262 if ( Abs(det) > Precision::Confusion()) {
263 Standard_Real c = (dx * vx + dy * vy)
264 / Sqrt((dx * dx + dy * dy) * (vx * vx + vy * vy)); // Cosine of alpha = arc of angle / 2 , alpha in [0,Pi]
265 radius = (vx * vx + vy * vy)* Sqrt(dx * dx + dy * dy) // radius = distance between start and end point / 2 * sin(alpha)
266 / (2.0 * det); // radius is > 0 or < 0
267 if (Abs(radius) > Precision::Confusion()) {
268 angle = 2.0 * acos(c); // angle in [0,2Pi]
279 case 'U': // Arc by end point and radiUs
281 if (n1 != 5) goto badargs;
282 Standard_Real vx = a(1).RealValue();
283 Standard_Real vy = a(2).RealValue();
284 radius = a(3).RealValue();
285 reversed = a(4).IntegerValue();
286 if (a(0) == "UU") { // Absolute
290 Standard_Real length = Sqrt(vx * vx + vy * vy);
291 if ( (4.0 - (vx * vx + vy * vy) / (radius * radius) >= 0.0 ) && (length > Precision::Confusion()) ) {
292 Standard_Real c = 0.5 * Sqrt(4.0 - (vx * vx + vy * vy) / (radius * radius)); // Cosine of alpha = arc angle / 2 , alpha in [0,Pi/2]
293 angle = 2.0 * acos(c); // angle in [0,Pi]
295 angle = angle - 2 * PI;
296 dx = 0.5 * ( vy * 1.0/radius
297 + vx * Sqrt(4.0 / (vx * vx + vy * vy) - 1.0 / (radius * radius)));
298 dy = - 0.5 * ( vx * 1.0/radius
299 - vy * Sqrt(4.0 / (vx * vx + vy * vy) - 1.0 / (radius * radius)));
307 case 'E': // Arc by end point and cEnter
309 if (n1 != 7) goto badargs;
310 Standard_Real vx = a(1).RealValue();
311 Standard_Real vy = a(2).RealValue();
312 Standard_Real vxc = a(3).RealValue();
313 Standard_Real vyc = a(4).RealValue();
314 reversed = a(5).IntegerValue();
315 control_Tolerance = a(6).IntegerValue();
317 if (a(0) == "EE") { // Absolute
323 radius = Sqrt( vxc * vxc + vyc * vyc );
324 Standard_Real det = vx * vyc - vy * vxc;
325 Standard_Real length = Sqrt(vx * vx + vy * vy);
326 Standard_Real length2 = Sqrt((vx-vxc) * (vx-vxc) + (vy-vyc) * (vy-vyc));
327 Standard_Real length3 = Sqrt(vxc * vxc + vyc * vyc);
328 Standard_Real error = Abs(length2 - radius);
330 if ( error > Precision::Confusion() ){
331 MESSAGE("Warning : The specified end point is not on the Arc, distance = "<<error);
333 if ( error > Precision::Confusion() && control_Tolerance == 1) // Don't create the arc if the end point
334 move = none; // is too far from it
335 else if ( (length > Precision::Confusion()) &&
336 (length2 > Precision::Confusion()) &&
337 (length3 > Precision::Confusion()) ) {
338 Standard_Real c = ( radius * radius - (vx * vxc + vy * vyc) )
339 / ( radius * Sqrt((vx-vxc) * (vx-vxc) + (vy-vyc) * (vy-vyc)) ) ; // Cosine of arc angle
340 angle = acos(c); // angle in [0,Pi]
342 angle = angle - 2 * PI;
356 if (n1 != 2) goto badargs;
357 length = a(1).RealValue();
359 if (Abs(dx) < Precision::Confusion()) {
360 MESSAGE("profile : cannot intersect, arg "<<i-1);
363 length = (length - x) / dx;
365 else if (a(0) == "IY") {
366 if (Abs(dy) < Precision::Confusion()) {
367 MESSAGE("profile : cannot intersect, arg "<<i-1);
370 length = (length - y) / dy;
372 if (Abs(length) > Precision::Confusion())
381 close = Standard_True;
382 else if(a(0) == "WF") {
383 close = Standard_True;
384 face = Standard_True;
391 MESSAGE("profile : unknown code " << a(i));
406 Handle(Geom2d_Line) l = new Geom2d_Line(gp_Pnt2d(x,y),gp_Dir2d(dx,dy));
407 BRepBuilderAPI_MakeEdge ME (GeomAPI::To3d(l,P),0,length);
417 Standard_Boolean sense = Standard_True;
424 gp_Ax2d ax(gp_Pnt2d(x-radius*dy,y+radius*dx),gp_Dir2d(dy,-dx));
429 Handle(Geom2d_Circle) c = new Geom2d_Circle(ax,radius,sense);
430 BRepBuilderAPI_MakeEdge ME (GeomAPI::To3d(c,P),0,angle);
445 MP = BRepBuilderAPI_MakeVertex(gp_Pnt(x, y, 0.0));
457 stayfirst = Standard_False;
459 if(!(dx == 0 && dy == 0))
460 myLastDir.SetCoord(dx, dy, 0.0);
468 if ((i == n) && close) {
469 // the closing segment
472 length = Sqrt(dx * dx + dy * dy);
474 if (length > Precision::Confusion()) {
482 // get the result, face or wire
485 } else if (move == point) {
491 BRepBuilderAPI_MakeFace MF (P, MW.Wire());
503 if(!TheLocation.IsIdentity())
511 MESSAGE("profile : bad number of arguments");