void ImpExpDxfWrite::exportEllipse(BRepAdaptor_Curve& c) { gp_Elips ellp = c.Ellipse(); gp_Pnt p = ellp.Location(); double center[3] = {0,0,0}; gPntToTuple(center, p); double major = ellp.MajorRadius(); double minor = ellp.MinorRadius(); gp_Dir xaxis = ellp.XAxis().Direction(); //direction of major axis //rotation appears to be the clockwise(?) angle between major & +Y?? double rotation = xaxis.AngleWithRef(gp_Dir(0, 1, 0), gp_Dir(0, 0, 1)); //2*M_PI = 6.28319 is invalid(doesn't display in LibreCAD), but 2PI = 6.28318 is valid! //writeEllipse(center, major, minor, rotation, 0.0, 2 * M_PI, true ); writeEllipse(center, major, minor, rotation, 0.0, 6.28318, true ); }
void ImpExpDxfWrite::exportEllipseArc(BRepAdaptor_Curve& c) { gp_Elips ellp = c.Ellipse(); gp_Pnt p = ellp.Location(); double center[3] = {0,0,0}; gPntToTuple(center, p); double major = ellp.MajorRadius(); double minor = ellp.MinorRadius(); gp_Dir xaxis = ellp.XAxis().Direction(); //direction of major axis //rotation appears to be the clockwise angle between major & +Y?? double rotation = xaxis.AngleWithRef(gp_Dir(0, 1, 0), gp_Dir(0, 0, 1)); double f = c.FirstParameter(); double l = c.LastParameter(); gp_Pnt s = c.Value(f); gp_Pnt m = c.Value((l+f)/2.0); gp_Pnt e = c.Value(l); gp_Vec v1(m,s); gp_Vec v2(m,e); gp_Vec v3(0,0,1); double a = v3.DotCross(v1,v2); // a = v3 dot (v1 cross v2) // relates to "handedness" of 3 vectors // a > 0 ==> v2 is CCW from v1 (righthanded)? // a < 0 ==> v2 is CW from v1 (lefthanded)? double startAngle = fmod(f,2.0*M_PI); //revolutions double endAngle = fmod(l,2.0*M_PI); bool endIsCW = (a < 0) ? true: false; //if !endIsCW swap(start,end) //not sure if this is a hack or not. seems to make valid arcs. if (!endIsCW) { startAngle = -startAngle; endAngle = -endAngle; } writeEllipse(center, major, minor, rotation, startAngle, endAngle, endIsCW); }
void SVGOutput::printEllipse(const BRepAdaptor_Curve& c, int id, std::ostream& out) { gp_Elips ellp = c.Ellipse(); const gp_Pnt& p= ellp.Location(); double r1 = ellp.MajorRadius(); double r2 = ellp.MinorRadius(); double f = c.FirstParameter(); double l = c.LastParameter(); gp_Pnt s = c.Value(f); gp_Pnt m = c.Value((l+f)/2.0); gp_Pnt e = c.Value(l); gp_Vec v1(m,s); gp_Vec v2(m,e); gp_Vec v3(0,0,1); double a = v3.DotCross(v1,v2); // a full ellipse // See also https://developer.mozilla.org/en/SVG/Tutorial/Paths gp_Dir xaxis = ellp.XAxis().Direction(); Standard_Real angle = xaxis.AngleWithRef(gp_Dir(1,0,0),gp_Dir(0,0,-1)); angle = Base::toDegrees<double>(angle); if (fabs(l-f) > 1.0 && s.SquareDistance(e) < 0.001) { out << "<g transform = \"rotate(" << angle << "," << p.X() << "," << p.Y() << ")\">" << std::endl; out << "<ellipse cx =\"" << p.X() << "\" cy =\"" << p.Y() << "\" rx =\"" << r1 << "\" ry =\"" << r2 << "\"/>" << std::endl; out << "</g>" << std::endl; } // arc of ellipse else { char las = (l-f > D_PI) ? '1' : '0'; // large-arc-flag char swp = (a < 0) ? '1' : '0'; // sweep-flag, i.e. clockwise (0) or counter-clockwise (1) out << "<path d=\"M" << s.X() << " " << s.Y() << " A" << r1 << " " << r2 << " " << angle << " " << las << " " << swp << " " << e.X() << " " << e.Y() << "\" />" << std::endl; } }
void DXFOutput::printEllipse(const BRepAdaptor_Curve& c, int id, std::ostream& out) { gp_Elips ellp = c.Ellipse(); const gp_Pnt& p= ellp.Location(); double r1 = ellp.MajorRadius(); double r2 = ellp.MinorRadius(); double f = c.FirstParameter(); double l = c.LastParameter(); gp_Pnt s = c.Value(f); gp_Pnt m = c.Value((l+f)/2.0); gp_Pnt e = c.Value(l); gp_Vec v1(m,s); gp_Vec v2(m,e); gp_Vec v3(0,0,1); double a = v3.DotCross(v1,v2); // a full ellipse /* if (s.SquareDistance(e) < 0.001) { out << "<ellipse cx =\"" << p.X() << "\" cy =\"" << p.Y() << "\" rx =\"" << r1 << "\" ry =\"" << r2 << "\"/>"; } // arc of ellipse else { // See also https://developer.mozilla.org/en/SVG/Tutorial/Paths gp_Dir xaxis = ellp.XAxis().Direction(); Standard_Real angle = xaxis.Angle(gp_Dir(1,0,0)); angle = Base::toDegrees<double>(angle); char las = (l-f > D_PI) ? '1' : '0'; // large-arc-flag char swp = (a < 0) ? '1' : '0'; // sweep-flag, i.e. clockwise (0) or counter-clockwise (1) out << "<path d=\"M" << s.X() << " " << s.Y() << " A" << r1 << " " << r2 << " " << angle << " " << las << " " << swp << " " << e.X() << " " << e.Y() << "\" />"; }*/ gp_Dir xaxis = ellp.XAxis().Direction(); double angle = xaxis.Angle(gp_Dir(1,0,0)); //double rotation = Base::toDegrees<double>(angle); double ax = s.X() - p.X(); double ay = s.Y() - p.Y(); double bx = e.X() - p.X(); double by = e.Y() - p.Y(); double start_angle = atan2(ay, ax) * 180/D_PI; double end_angle = atan2(by, bx) * 180/D_PI; double major_x;double major_y; major_x = r1 * sin(angle*90); major_y = r1 * cos(angle*90); double ratio = r2/r1; if(a > 0){ double temp = start_angle; start_angle = end_angle; end_angle = temp; } out << 0 << endl; out << "ELLIPSE" << endl; out << 8 << endl; // Group code for layer name out << "sheet_layer" << endl; // Layer number out << 10 << endl; // Centre X out << p.X() << endl; // X in WCS coordinates out << 20 << endl; out << p.Y() << endl; // Y in WCS coordinates out << 30 << endl; out << 0 << endl; // Z in WCS coordinates out << 11 << endl; // out << major_x << endl; // Major X out << 21 << endl; out << major_y << endl; // Major Y out << 31 << endl; out << 0 << endl; // Major Z out << 40 << endl; // out << ratio << endl; // Ratio out << 41 << endl; out << start_angle << endl; // Start angle out << 42 << endl; out << end_angle << endl; // End angle }