2016-11-24 2 views
2

나는 pdfbox를 사용하여 파이 차트를 그려야합니다.pdfbox를 사용하여 파이 차트를 그리는 방법은 무엇입니까?

데이터 지니

제목 마크 백분율 표시에
하위 1 80 80 80
서브 2 70 70 150
하위 3 65 65 215
서브 학위 누적 각도 4 90 90 305
Sub-5 55 55 360

반경과 중심을 100 픽셀 및 (250, 400)으로합시다.

x 축에 초기 선을 평행하게합니다.
초기 회선 문을 그리는 데 사용됩니다 :
contentStream.drawLine (250, 400, 350, 400); 베 지어 곡선을 사용하여 두 점 사이의 반경을
b) 도면 호를 그리 일부도 떨어져 초기 라인으로부터 원호상의 점
a) X를 찾는 Y 좌표 :

난에 붙어 .

문제 해결에 대한 도움을 주시면 매우 감사하겠습니다.

답변

2

각도에 따라 원에서 x, y 좌표를 찾는 것은 학교 수학, 즉 sin() 및 cos()입니다. 까다로운 부분은 베 지어 곡선을 사용하여 호를 그리는 것입니다.

요청한 파이 차트를 그리는 코드는 다음과 같습니다. createSmallArc()은 최대 90 °의 각도에서만 작동합니다. 더 많은 것을 원한다면 (0,0)으로 돌아갈 때까지 여러 개의 호를 그려서 코드를 수정하거나 몇 개의 슬라이스를 그려야합니다.

(createSmallArc()Hans Muller 의해 라이센스이다. Creative Commons Attribution 3.0 변경했다 :. 자바로 코드 AS 원래 구현 알고리즘 Aleksas Riškus입니다) I는 code.But I 돈을 사용하여 세미 원을 그릴 수 있었다

public class PieChart 
{ 
    public static void main(String[] args) throws IOException 
    { 
     PDDocument doc = new PDDocument(); 
     PDPage page = new PDPage(); 
     doc.addPage(page); 
     PDPageContentStream cs = new PDPageContentStream(doc, page); 

     cs.transform(Matrix.getTranslateInstance(250, 400)); 

     cs.setNonStrokingColor(Color.yellow); 
     drawSlice(cs, 100, 0, 80); 
     cs.fill(); 
     cs.setNonStrokingColor(Color.red); 
     drawSlice(cs, 100, 80, 150); 
     cs.fill(); 
     cs.setNonStrokingColor(Color.green); 
     drawSlice(cs, 100, 150, 215); 
     cs.fill(); 
     cs.setNonStrokingColor(Color.blue); 
     drawSlice(cs, 100, 215, 305); 
     cs.fill(); 
     cs.setNonStrokingColor(Color.ORANGE); 
     drawSlice(cs, 100, 305, 360); 
     cs.fill(); 

     cs.close(); 
     doc.save("piechart.pdf"); 
     doc.close(); 
    } 

    private static void drawSlice(PDPageContentStream cs, float rad, float startDeg, float endDeg) throws IOException 
    { 
     cs.moveTo(0, 0); 
     List<Float> smallArc = createSmallArc(rad, Math.toRadians(startDeg), Math.toRadians(endDeg)); 
     cs.lineTo(smallArc.get(0), smallArc.get(1)); 
     cs.curveTo(smallArc.get(2), smallArc.get(3), smallArc.get(4), smallArc.get(5), smallArc.get(6), smallArc.get(7)); 
     cs.closePath(); 
    } 

    /** 
    * From https://hansmuller-flex.blogspot.com/2011/10/more-about-approximating-circular-arcs.html 
    * 
    * Cubic bezier approximation of a circular arc centered at the origin, 
    * from (radians) a1 to a2, where a2-a1 &lt; pi/2. The arc's radius is r. 
    * 
    * Returns a list with 4 points, where x1,y1 and x4,y4 are the arc's end points 
    * and x2,y2 and x3,y3 are the cubic bezier's control points. 
    * 
    * This algorithm is based on the approach described in: 
    * Aleksas Riškus, "Approximation of a Cubic Bezier Curve by Circular Arcs and Vice Versa," 
    * Information Technology and Control, 35(4), 2006 pp. 371-378. 
    */ 
    private static List<Float> createSmallArc(double r, double a1, double a2) 
    { 
     // Compute all four points for an arc that subtends the same total angle 
     // but is centered on the X-axis 
     double a = (a2 - a1)/2; 
     double x4 = r * Math.cos(a); 
     double y4 = r * Math.sin(a); 
     double x1 = x4; 
     double y1 = -y4; 
     double q1 = x1*x1 + y1*y1; 

     double q2 = q1 + x1*x4 + y1*y4; 
     double k2 = 4/3d * (Math.sqrt(2 * q1 * q2) - q2)/(x1 * y4 - y1 * x4); 
     double x2 = x1 - k2 * y1; 
     double y2 = y1 + k2 * x1; 
     double x3 = x2; 
     double y3 = -y2; 

     // Find the arc points' actual locations by computing x1,y1 and x4,y4 
     // and rotating the control points by a + a1 

     double ar = a + a1; 
     double cos_ar = Math.cos(ar); 
     double sin_ar = Math.sin(ar); 

     List<Float> list = new ArrayList<Float>(); 
     list.add((float) (r * Math.cos(a1))); 
     list.add((float) (r * Math.sin(a1))); 
     list.add((float) (x2 * cos_ar - y2 * sin_ar)); 
     list.add((float) (x2 * sin_ar + y2 * cos_ar)); 
     list.add((float) (x3 * cos_ar - y3 * sin_ar)); 
     list.add((float) (x3 * sin_ar + y3 * cos_ar)); 
     list.add((float) (r * Math.cos(a2))); 
     list.add((float) (r * Math.sin(a2))); 
     return list; 
    } 
} 
+0

arc.와 함께 선분을 그려야합니다. 어떻게 선을 제거합니까? lineTo 명령에 주석을 달았지만 작동하지 않았습니다. –

+0

@VK 첫 번째 영화를 삭제합니다. lineto를 moveto로 바꾸십시오 (단, 처음 만 나머지는 제거하십시오). closepath()를 제거하십시오. –

+0

그것은 일했다. 그러나 나는 "처음 만, 나머지를 제거하라"라는 말을 이해하지 못했습니다. –

관련 문제