2009-11-26 167 views
0

我最近写了一个java program转化SVG文档转换为HTML/帆布:这是很容易转化的路径,例如SVG椭圆弧与Java

d="M 0 0 L 100 100 z" 

喜欢的东西

GeneralPath L= new GeneralPath(); 
L.moveTo(0,0); 
L.lineTo(100,100); 
L.closePath(); 

但是,我不知道如何将椭圆弧命令转换为Java/GeneralPath。例如,有没有人知道我应该如何将以下命令转换为Java/GeneralPath?

d = "M 750 200 a 100 50 135 1 1 250 50" 

感谢您的帮助。

+0

我认为这是一个正确的代码: http://www.java2s.com/Code/Java/2D-Graphics-GUI/AgeometricpathconstructedfromstraightlinesquadraticandcubicBeziercurvesandellipticalarc.htm问候 – ezsi 2011-04-18 08:03:32

回答

7

GeneralPath中没有直接命令。我用这个功能,

public static final void arcTo(GeneralPath path, float rx, float ry, float theta, boolean largeArcFlag, boolean sweepFlag, float x, float y) { 
      // Ensure radii are valid 
      if (rx == 0 || ry == 0) { 
        path.lineTo(x, y); 
        return; 
      } 
      // Get the current (x, y) coordinates of the path 
      Point2D p2d = path.getCurrentPoint(); 
      float x0 = (float) p2d.getX(); 
      float y0 = (float) p2d.getY(); 
      // Compute the half distance between the current and the final point 
      float dx2 = (x0 - x)/2.0f; 
      float dy2 = (y0 - y)/2.0f; 
      // Convert theta from degrees to radians 
      theta = (float) Math.toRadians(theta % 360f); 

      // 
      // Step 1 : Compute (x1, y1) 
      // 
      float x1 = (float) (Math.cos(theta) * (double) dx2 + Math.sin(theta) 
          * (double) dy2); 
      float y1 = (float) (-Math.sin(theta) * (double) dx2 + Math.cos(theta) 
          * (double) dy2); 
      // Ensure radii are large enough 
      rx = Math.abs(rx); 
      ry = Math.abs(ry); 
      float Prx = rx * rx; 
      float Pry = ry * ry; 
      float Px1 = x1 * x1; 
      float Py1 = y1 * y1; 
      double d = Px1/Prx + Py1/Pry; 
      if (d > 1) { 
        rx = Math.abs((float) (Math.sqrt(d) * (double) rx)); 
        ry = Math.abs((float) (Math.sqrt(d) * (double) ry)); 
        Prx = rx * rx; 
        Pry = ry * ry; 
      } 

      // 
      // Step 2 : Compute (cx1, cy1) 
      // 
      double sign = (largeArcFlag == sweepFlag) ? -1d : 1d; 
      float coef = (float) (sign * Math 
          .sqrt(((Prx * Pry) - (Prx * Py1) - (Pry * Px1)) 
              /((Prx * Py1) + (Pry * Px1)))); 
      float cx1 = coef * ((rx * y1)/ry); 
      float cy1 = coef * -((ry * x1)/rx); 

      // 
      // Step 3 : Compute (cx, cy) from (cx1, cy1) 
      // 
      float sx2 = (x0 + x)/2.0f; 
      float sy2 = (y0 + y)/2.0f; 
      float cx = sx2 
          + (float) (Math.cos(theta) * (double) cx1 - Math.sin(theta) 
              * (double) cy1); 
      float cy = sy2 
          + (float) (Math.sin(theta) * (double) cx1 + Math.cos(theta) 
              * (double) cy1); 

      // 
      // Step 4 : Compute the angleStart (theta1) and the angleExtent (dtheta) 
      // 
      float ux = (x1 - cx1)/rx; 
      float uy = (y1 - cy1)/ry; 
      float vx = (-x1 - cx1)/rx; 
      float vy = (-y1 - cy1)/ry; 
      float p, n; 
      // Compute the angle start 
      n = (float) Math.sqrt((ux * ux) + (uy * uy)); 
      p = ux; // (1 * ux) + (0 * uy) 
      sign = (uy < 0) ? -1d : 1d; 
      float angleStart = (float) Math.toDegrees(sign * Math.acos(p/n)); 
      // Compute the angle extent 
      n = (float) Math.sqrt((ux * ux + uy * uy) * (vx * vx + vy * vy)); 
      p = ux * vx + uy * vy; 
      sign = (ux * vy - uy * vx < 0) ? -1d : 1d; 
      float angleExtent = (float) Math.toDegrees(sign * Math.acos(p/n)); 
      if (!sweepFlag && angleExtent > 0) { 
        angleExtent -= 360f; 
      } else if (sweepFlag && angleExtent < 0) { 
        angleExtent += 360f; 
      } 
      angleExtent %= 360f; 
      angleStart %= 360f; 

      Arc2D.Float arc = new Arc2D.Float(); 
      arc.x = cx - rx; 
      arc.y = cy - ry; 
      arc.width = rx * 2.0f; 
      arc.height = ry * 2.0f; 
      arc.start = -angleStart; 
      arc.extent = -angleExtent; 
      path.append(arc, true); 
    } 
+1

哪可以找到Apache Batik库,org.apache.batik.ext.awt.geom.ExtendedGeneralPath.computeArc()。不知道该方法的原始版权是什么,您必须查看源代码管理, – David 2011-07-15 17:51:45