コード例 #1
0
void DXFOutput::printGeneric(const BRepAdaptor_Curve& c, int id, std::ostream& out)
{
    double uStart = c.FirstParameter();
    gp_Pnt PS;
    gp_Vec VS;
    c.D1(uStart, PS, VS);

    double uEnd = c.LastParameter();
    gp_Pnt PE;
    gp_Vec VE;
    c.D1(uEnd, PE, VE);

    out << "0"			<< endl;
    out << "LINE"		<< endl;
    out << "8"			<< endl;	// Group code for layer name
    out << "sheet_layer" << endl; // Layer name 
    out << "10"			<< endl;	// Start point of line
    out << PS.X()		<< endl;	// X in WCS coordinates
    out << "20"			<< endl;
    out << PS.Y()		<< endl;	// Y in WCS coordinates
    out << "30"			<< endl;
    out << "0"		<< endl;	// Z in WCS coordinates
    out << "11"			<< endl;	// End point of line
    out << PE.X()		<< endl;	// X in WCS coordinates
    out << "21"			<< endl;
    out << PE.Y()		<< endl;	// Y in WCS coordinates
    out << "31"			<< endl;
    out << "0"		<< endl;	// Z in WCS coordinates
}
コード例 #2
0
void ImpExpDxfWrite::exportLine(BRepAdaptor_Curve& c)
{
    double f = c.FirstParameter();
    double l = c.LastParameter();
    gp_Pnt s = c.Value(f);
    double start[3] = {0,0,0};
    gPntToTuple(start, s);
    gp_Pnt e = c.Value(l);
    double end[3] = {0,0,0};
    gPntToTuple(end, e);
    writeLine(start, end);
}
コード例 #3
0
void ImpExpDxfWrite::exportCircle(BRepAdaptor_Curve& c)
{
    gp_Circ circ = c.Circle();
    gp_Pnt p = circ.Location();
    double center[3] = {0,0,0};
    gPntToTuple(center, p);

    double  radius = circ.Radius();

    writeCircle(center, radius);
}
コード例 #4
0
void SVGOutput::printCircle(const BRepAdaptor_Curve& c, std::ostream& out)
{
    gp_Circ circ = c.Circle();
    const gp_Pnt& p= circ.Location();
    double r = circ.Radius();
    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 circle
    if (fabs(l-f) > 1.0 && s.SquareDistance(e) < 0.001) {
        out << "<circle cx =\"" << p.X() << "\" cy =\"" 
            << p.Y() << "\" r =\"" << r << "\" />";
    }
    // arc of circle
    else {
        // See also https://developer.mozilla.org/en/SVG/Tutorial/Paths
        char xar = '0'; // x-axis-rotation
        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" << r << " " << r << " "
            << xar << " " << las << " " << swp << " "
            << e.X() << " " << e.Y() << "\" />";
    }
}
コード例 #5
0
void ImpExpDxfWrite::exportArc(BRepAdaptor_Curve& c)
{
    gp_Circ circ = c.Circle();
    gp_Pnt p = circ.Location();
    double center[3] = {0,0,0};
    gPntToTuple(center, p);

    double f = c.FirstParameter();
    double l = c.LastParameter();
    gp_Pnt s = c.Value(f);
    double start[3];
    gPntToTuple(start, s);
    gp_Pnt m = c.Value((l+f)/2.0);
    gp_Pnt e = c.Value(l);
    double end[3] = {0,0,0};
    gPntToTuple(end, e);

    gp_Vec v1(m,s);
    gp_Vec v2(m,e);
    gp_Vec v3(0,0,1);
    double a = v3.DotCross(v1,v2);

    bool dir = (a < 0) ? true: false;
    writeArc(start, end, center, dir );
}
コード例 #6
0
void SVGOutput::printGeneric(const BRepAdaptor_Curve& c, int id, std::ostream& out)
{
    TopLoc_Location location;
    Handle(Poly_Polygon3D) polygon = BRep_Tool::Polygon3D(c.Edge(), location);
    if (!polygon.IsNull()) {
        const TColgp_Array1OfPnt& nodes = polygon->Nodes();
        char c = 'M';
        out << "<path id= \"" /*<< ViewName*/ << id << "\" d=\" "; 
        for (int i = nodes.Lower(); i <= nodes.Upper(); i++){
            out << c << " " << nodes(i).X() << " " << nodes(i).Y()<< " " ; 
            c = 'L';
        }
        out << "\" />" << endl;
    }
}
コード例 #7
0
void ImpExpDxfWrite::exportPolyline(BRepAdaptor_Curve& c)
{
    LWPolyDataOut pd;
    pd.Flag = c.IsClosed();
    pd.Elev = 0.0;
    pd.Thick = 0.0;
    pd.Extr.x = 0.0;
    pd.Extr.y = 0.0;
    pd.Extr.z = 1.0;
    pd.nVert = 0;

    GCPnts_UniformAbscissa discretizer;
    discretizer.Initialize (c, optionMaxLength);
    std::vector<point3D> points;
    if (discretizer.IsDone () && discretizer.NbPoints () > 0) {
        int nbPoints = discretizer.NbPoints ();
        for (int i=1; i<=nbPoints; i++) {
            gp_Pnt p = c.Value (discretizer.Parameter (i));
            pd.Verts.push_back(gPntTopoint3D(p));
        }
        pd.nVert = discretizer.NbPoints ();
        writePolyline(pd);
    }
}
コード例 #8
0
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 );
}
コード例 #9
0
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);
}
コード例 #10
0
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;
    }
}
コード例 #11
0
void DXFOutput::printBSpline(const BRepAdaptor_Curve& c, int id, std::ostream& out) //Not even close yet- DF 
{
    try {
        std::stringstream str;
        Handle_Geom_BSplineCurve spline = c.BSpline();
        if (spline->Degree() > 3) {
            Standard_Real tol3D = 0.001;
            Standard_Integer maxDegree = 3, maxSegment = 10;
            Handle_BRepAdaptor_HCurve hCurve = new BRepAdaptor_HCurve(c);
            // approximate the curve using a tolerance
            Approx_Curve3d approx(hCurve,tol3D,GeomAbs_C2,maxSegment,maxDegree);
            if (approx.IsDone() && approx.HasResult()) {
                // have the result
                spline = approx.Curve();
            }
        }
		
        GeomConvert_BSplineCurveToBezierCurve crt(spline);
		//GeomConvert_BSplineCurveKnotSplitting crt(spline,0);
        Standard_Integer arcs = crt.NbArcs();
		//Standard_Integer arcs = crt.NbSplits()-1;
        	str << 0 << endl
				<< "SECTION" << endl
				<< 2 << endl
				<< "ENTITIES" << endl
				<< 0 << endl
				<< "SPLINE" << endl;
				//<< 8 << endl
				//<< 0 << endl
				//<< 66 << endl
				//<< 1 << endl
				//<< 0 << endl;

        for (Standard_Integer i=1; i<=arcs; i++) {
            Handle_Geom_BezierCurve bezier = crt.Arc(i);
            Standard_Integer poles = bezier->NbPoles();
			//Standard_Integer poles = bspline->NbPoles();
			//gp_Pnt p1 = bspline->Pole(1);

            if (bezier->Degree() == 3) {
                if (poles != 4)
                    Standard_Failure::Raise("do it the generic way");
                gp_Pnt p1 = bezier->Pole(1);
                gp_Pnt p2 = bezier->Pole(2);
                gp_Pnt p3 = bezier->Pole(3);
                gp_Pnt p4 = bezier->Pole(4);
                if (i == 1) {
                    str 
						<< 10 << endl
						<< p1.X() << endl
						<< 20 << endl
						<< p1.Y() << endl
						<< 30 << endl
						<< 0 << endl
						
						<< 10 << endl
                        << p2.X() << endl
						<< 20 << endl
						<< p2.Y() << endl
						<< 30 << endl
						<< 0 << endl
						
						<< 10 << endl
                        << p3.X() << endl
						<< 20 << endl
						<< p3.Y() << endl
						<< 30 << endl
						<< 0 << endl
						
						<< 10 << endl
                        << p4.X() << endl
						<< 20 << endl
						<< p4.Y() << endl
						<< 30 << endl
						<< 0 << endl

						<< 12 << endl
						<< p1.X() << endl
						<< 22 << endl
						<< p1.Y() << endl
						<< 32 << endl
						<< 0 << endl

						<< 13 << endl
						<< p4.X() << endl
						<< 23 << endl
						<< p4.Y() << endl
						<< 33 << endl
						<< 0 << endl;
                }
                else {
                    str 
						<< 10 << endl
                        << p3.X() << endl
						<< 20 << endl
						<< p3.Y() << endl
						<< 30 << endl
						<< 0 << endl
						
						<< 10 << endl
                        << p4.X() << endl
						<< 20 << endl
						<< p4.Y() << endl
						<< 30 << endl
						<< 0 << endl

						<< 12 << endl
						<< p3.X() << endl
						<< 22 << endl
						<< p3.Y() << endl
						<< 32 << endl
						<< 0 << endl

						<< 13 << endl
						<< p4.X() << endl
						<< 23 << endl
						<< p4.Y() << endl
						<< 33 << endl
						<< 0 << endl;

                }
            }
            else if (bezier->Degree() == 2) {
                if (poles != 3)
                    Standard_Failure::Raise("do it the generic way");
                gp_Pnt p1 = bezier->Pole(1);
                gp_Pnt p2 = bezier->Pole(2);
                gp_Pnt p3 = bezier->Pole(3);
                if (i == 1) {
                    str 
						<< 10 << endl
						<< p1.X() << endl
						<< 20 << endl
						<< p1.Y() << endl
						<< 30 << endl
						<< 0 << endl
						
						<< 10 << endl
                        << p2.X() << endl
						<< 20 << endl
						<< p2.Y() << endl
						<< 30 << endl
						<< 0 << endl
						
						<< 10 << endl
                        << p3.X() << endl
						<< 20 << endl
						<< p3.Y() << endl
						<< 30 << endl
						<< 0 << endl

						<< 12 << endl
						<< p1.X() << endl
						<< 22 << endl
						<< p1.Y() << endl
						<< 32 << endl
						<< 0 << endl

						<< 13 << endl
						<< p3.X() << endl
						<< 23 << endl
						<< p3.Y() << endl
						<< 33 << endl
						<< 0 << endl;
                }
                else {
                    str 
						<< 10 << endl
                        << p3.X() << endl
						<< 20 << endl
						<< p3.Y() << endl
						<< 30 << endl
						<< 0 << endl;
                }
            }
            else {
                Standard_Failure::Raise("do it the generic way");
            }
        }

        //str << "\" />";
        out << str.str();
    }
    catch (Standard_Failure) {
        printGeneric(c, id, out);
    }
}
コード例 #12
0
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
}
コード例 #13
0
void DXFOutput::printCircle(const BRepAdaptor_Curve& c, std::ostream& out)
{
    gp_Circ circ = c.Circle();
	//const gp_Ax1& axis = c->Axis();
    const gp_Pnt& p= circ.Location();
    double r = circ.Radius();
    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 circle
    if (s.SquareDistance(e) < 0.001) {
        //out << "<circle cx =\"" << p.X() << "\" cy =\"" 
            //<< p.Y() << "\" r =\"" << r << "\" />";
	    out << 0			<< endl;
	    out << "CIRCLE"		<< 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-leaving flat
	    out << 40			<< endl;	//
	    out << r		<< endl;	// Radius
                                }



    // arc of circle
    else {
        // See also https://developer.mozilla.org/en/SVG/Tutorial/Paths
        /*char xar = '0'; // x-axis-rotation
        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" << r << " " << r << " "
            << xar << " " << las << " " << swp << " "
            << e.X() << " " << e.Y() << "\" />";*/
	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;


	if(a > 0){
		double temp = start_angle;
		start_angle = end_angle;
		end_angle = temp;}
	out << 0			<< endl;
	out << "ARC"		<< 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 << 40			<< endl;	//
	out << r		<< endl;	// Radius
	out << 50			<< endl;
	out << start_angle	<< endl;	// Start angle
	out << 51			<< endl;
	out << end_angle	<< endl;	// End angle



    }
}
コード例 #14
0
void SVGOutput::printBSpline(const BRepAdaptor_Curve& c, int id, std::ostream& out)
{
    try {
        std::stringstream str;
        Handle_Geom_BSplineCurve spline = c.BSpline();
        if (spline->Degree() > 3) {
            Standard_Real tol3D = 0.001;
            Standard_Integer maxDegree = 3, maxSegment = 10;
            Handle_BRepAdaptor_HCurve hCurve = new BRepAdaptor_HCurve(c);
            // approximate the curve using a tolerance
            Approx_Curve3d approx(hCurve,tol3D,GeomAbs_C2,maxSegment,maxDegree);
            if (approx.IsDone() && approx.HasResult()) {
                // have the result
                spline = approx.Curve();
            }
        }

        GeomConvert_BSplineCurveToBezierCurve crt(spline);
        Standard_Integer arcs = crt.NbArcs();
        str << "<path d=\"M";
        for (Standard_Integer i=1; i<=arcs; i++) {
            Handle_Geom_BezierCurve bezier = crt.Arc(i);
            Standard_Integer poles = bezier->NbPoles();
            if (bezier->Degree() == 3) {
                if (poles != 4)
                    Standard_Failure::Raise("do it the generic way");
                gp_Pnt p1 = bezier->Pole(1);
                gp_Pnt p2 = bezier->Pole(2);
                gp_Pnt p3 = bezier->Pole(3);
                gp_Pnt p4 = bezier->Pole(4);
                if (i == 1) {
                    str << p1.X() << "," << p1.Y() << " C"
                        << p2.X() << "," << p2.Y() << " "
                        << p3.X() << "," << p3.Y() << " "
                        << p4.X() << "," << p4.Y() << " ";
                }
                else {
                    str << "S"
                        << p3.X() << "," << p3.Y() << " "
                        << p4.X() << "," << p4.Y() << " ";
                }
            }
            else if (bezier->Degree() == 2) {
                if (poles != 3)
                    Standard_Failure::Raise("do it the generic way");
                gp_Pnt p1 = bezier->Pole(1);
                gp_Pnt p2 = bezier->Pole(2);
                gp_Pnt p3 = bezier->Pole(3);
                if (i == 1) {
                    str << p1.X() << "," << p1.Y() << " Q"
                        << p2.X() << "," << p2.Y() << " "
                        << p3.X() << "," << p3.Y() << " ";
                }
                else {
                    str << "T"
                        << p3.X() << "," << p3.Y() << " ";
                }
            }
            else {
                Standard_Failure::Raise("do it the generic way");
            }
        }

        str << "\" />";
        out << str.str();
    }
    catch (Standard_Failure) {
        printGeneric(c, id, out);
    }
}
コード例 #15
0
void ImpExpDxfWrite::exportBSpline(BRepAdaptor_Curve& c)
{
    SplineDataOut sd;
    Handle(Geom_BSplineCurve) spline;
    double f,l;
    gp_Pnt s,ePt;

    Standard_Real tol3D = 0.001;
    Standard_Integer maxDegree = 3, maxSegment = 100;
    Handle(BRepAdaptor_HCurve) hCurve = new BRepAdaptor_HCurve(c);
    Approx_Curve3d approx(hCurve, tol3D, GeomAbs_C0, maxSegment, maxDegree);
    if (approx.IsDone() && approx.HasResult()) {
        spline = approx.Curve();
    } else {
        if (approx.HasResult()) {                   //result, but not within tolerance
            spline = approx.Curve();
            Base::Console().Message("DxfWrite::exportBSpline - result not within tolerance\n");
        } else {
            f = c.FirstParameter();
            l = c.LastParameter();
            s = c.Value(f);
            ePt = c.Value(l);
            Base::Console().Message("DxfWrite::exportBSpline - no result- from:(%.3f,%.3f) to:(%.3f,%.3f) poles: %d\n",
                                 s.X(),s.Y(),ePt.X(),ePt.Y(),spline->NbPoles());
            TColgp_Array1OfPnt controlPoints(0,1);
            controlPoints.SetValue(0,s);
            controlPoints.SetValue(1,ePt);
            spline = GeomAPI_PointsToBSpline(controlPoints,1).Curve();
        }
    }
    //WF? norm of surface containing curve??
    sd.norm.x = 0.0;
    sd.norm.y = 0.0;
    sd.norm.z = 1.0;

    sd.flag = spline->IsClosed();
    sd.flag += spline->IsPeriodic()*2;
    sd.flag += spline->IsRational()*4;
    sd.flag += 8;   //planar spline

    sd.degree = spline->Degree();
    sd.control_points = spline->NbPoles();
    sd.knots  = spline->NbKnots();
    gp_Pnt p;
    spline->D0(spline->FirstParameter(),p);
    sd.starttan = gPntTopoint3D(p);
    spline->D0(spline->LastParameter(),p);
    sd.endtan = gPntTopoint3D(p);

    //next bit is from DrawingExport.cpp (Dan Falk?).  
    Standard_Integer m = 0;
    if (spline->IsPeriodic()) {
        m = spline->NbPoles() + 2*spline->Degree() - spline->Multiplicity(1) + 2;
    }
    else {
        for (int i=1; i<= spline->NbKnots(); i++)
            m += spline->Multiplicity(i);
    }
    TColStd_Array1OfReal knotsequence(1,m);
    spline->KnotSequence(knotsequence);
    for (int i = knotsequence.Lower() ; i <= knotsequence.Upper(); i++) {
            sd.knot.push_back(knotsequence(i));
    }
    sd.knots = knotsequence.Length();

    TColgp_Array1OfPnt poles(1,spline->NbPoles());
    spline->Poles(poles);
    for (int i = poles.Lower(); i <= poles.Upper(); i++) {
        sd.control.push_back(gPntTopoint3D(poles(i)));
    }
    //OCC doesn't have separate lists for control points and fit points. 
    
    writeSpline(sd);
}