-- 作者:wenwu2008
-- 发布时间:12/11/2006 10:44:00 AM
--
我用过GDI+里面的GraphicsPath类,从那里面再转成SVG的path元素,会比较简单。只是我转弧形时,算的比较复杂。我把代码发上来吧。 public: //将一个SVG中的扇形转成一个Graphics中的扇形,x_axis_rotation代表长半短轴顺时针旋转的角度,large_arc_flag代表是在圆还是小圆,sweep_flag代表是顺时针还是逆时针转动。 //假设存在严格匹配的扇形,不需要移动长半轴和短半轴 static void SVGArcToGDI(Drawing::Drawing2D ::GraphicsPath ^tagPath,Drawing::PointF startPoint,Drawing::PointF overPoint,float rx,float ry,float x_axis_rotation,float large_arc_flag,float sweep_flag) { //第一次解会得到 double t=2*(overPoint.Y -startPoint.Y)/ry; double V=Math::Pow (((overPoint.Y-startPoint.Y )/ry),2)+(overPoint.X*overPoint.X-startPoint.X*startPoint.X ) /(rx*rx); //方程的三个系数 double A=4*Math::Pow ((startPoint.X-overPoint.X ),2)/Math::Pow (rx,4)+t*t/(rx*rx); double B=4*(startPoint.X -overPoint.X )*V/(rx*rx)-t*t*2*startPoint.X /(rx*rx); double C=V*V-t*t*(1-startPoint.X *startPoint.X /(rx*rx)); //得解为椭圆的中心点, double PX_1,PY_1,PX_2,PY_2; //当半径不够时,扩大半径,以达到拟合. while(B*B-4*A*C<0) { rx*=1.01F; ry*=1.01F; V=Math::Pow (((overPoint.Y-startPoint.Y )/ry),2)+(overPoint.X*overPoint.X-startPoint.X*startPoint.X ) /(rx*rx); A=4*Math::Pow ((startPoint.X-overPoint.X ),2)/Math::Pow (rx,4)+t*t/(rx*rx); B=4*(startPoint.X -overPoint.X )*V/(rx*rx)-t*t*2*startPoint.X /(rx*rx); C=V*V-t*t*(1-startPoint.X *startPoint.X /(rx*rx)); } if(B*B-4*A*C>0) { //第一组 PX_1=((0-B)+Math::Pow ((B*B-4*A*C),0.5))/(2*A); PY_1=startPoint.Y -ry*Math::Pow ((1- Math::Pow ((startPoint.X -PX_1),2)/(rx*rx) ),0.5); if(Math::Abs ((Math::Pow ((overPoint.X -PX_1)/rx,2)+Math::Pow ((overPoint.Y -PY_1)/ry,2))-1)>0.00001) PY_1=startPoint.Y +ry*Math::Pow ((1- Math::Pow ((startPoint.X -PX_1),2)/(rx*rx) ),0.5); //第二组 PX_2=((0-B)-Math::Pow ((B*B-4*A*C),0.5))/(2*A); PY_2=startPoint.Y -ry*Math::Pow ((1- Math::Pow ((startPoint.X -PX_2),2)/(rx*rx) ),0.5); if(Math::Abs ((Math::Pow ((overPoint.X -PX_2)/rx,2)+Math::Pow ((overPoint.Y -PY_2)/ry,2))-1)>0.00001) PY_2=startPoint.Y +ry*Math::Pow ((1- Math::Pow ((startPoint.X -PX_2),2)/(rx*rx) ),0.5); } else { if(B*B-4*A*C==0) { PX_1=((0-B)+Math::Pow ((B*B-4*A*C),0.5))/(2*A); PX_2=PX_1; PY_1=startPoint.Y -ry*Math::Pow ((1- Math::Pow ((startPoint.X -PX_1),2)/(rx*rx) ),0.5); PY_2=startPoint.Y +ry*Math::Pow ((1- Math::Pow ((startPoint.X -PX_1),2)/(rx*rx) ),0.5); if(Math::Abs ((Math::Pow ((overPoint.X -PX_2)/rx,2)+Math::Pow ((overPoint.Y -PY_2)/ry,2))-1)>0.00001) PY_2=PY_1; if(Math::Abs ((Math::Pow ((overPoint.X -PX_1)/rx,2)+Math::Pow ((overPoint.Y -PY_1)/ry,2))-1)>0.00001) PY_1=PY_2; //判断PY_2是否合理,如合理则继续,否则PY_2=PY_1; } } Drawing::PointF P1=Drawing::PointF (Convert::ToSingle (PX_1),Convert::ToSingle (PY_1)); Drawing::PointF P2=Drawing::PointF (Convert::ToSingle (PX_2),Convert::ToSingle (PY_2)); Drawing::PointF center; //为了判断四种情况,需要计算,先判断中心点在直线的左边还是右边 double k=(P1.X -startPoint.X )*(overPoint.Y-P1.Y)-(overPoint.X-P1.X )*(P1.Y -startPoint.Y ); if(large_arc_flag+sweep_flag==0||large_arc_flag+sweep_flag==2)//在左边 if(k>0) center=Drawing::PointF (P1.X ,P1.Y ); else center=Drawing::PointF (P2.X ,P2.Y ); else if(k>0) center=Drawing::PointF (P2.X ,P2.Y ); else center=Drawing::PointF (P1.X ,P1.Y ); //得到center为最终椭圆中心 //求两点在椭圆上的位置 //求开始点所在的角度,确保结果大于0度 double dx=center.X -startPoint.X ; double dy=center.Y -startPoint.Y ; double startAngle=Math::Asin(dy/Math::Pow ((dx*dx+dy*dy),0.5))*180/Math::PI ; if(dx>=0) startAngle=180-startAngle; else if(dy<0) startAngle+=360; startAngle=360-startAngle; //求终点所在的角度 dx=center.X -overPoint.X ; dy=center.Y -overPoint.Y ; double overAngle=Math::Asin(dy/Math::Pow ((dx*dx+dy*dy),0.5))*180/Math::PI ; if(dx>=0) overAngle=180-overAngle; else if(dy<0) overAngle+=360; overAngle=360-overAngle; //如果是逆时钟,交换起末点 double swepAngle=overAngle-startAngle; if(sweep_flag==0) { if(swepAngle>0) swepAngle=0-swepAngle; } else { if(swepAngle<0) swepAngle=0-swepAngle; } //必须保证弧的起点不变,可以使用转过负角来达到要求 tagPath->AddArc (center.X -rx,center.Y-ry,rx*2,ry*2,Convert::ToSingle (startAngle),Convert::ToSingle (swepAngle)); }
|