diff --git a/draw2d/curve/arc.go b/draw2d/curve/arc.go new file mode 100644 index 0000000..7e560be --- /dev/null +++ b/draw2d/curve/arc.go @@ -0,0 +1,37 @@ +// Copyright 2010 The draw2d Authors. All rights reserved. +// created: 21/11/2010 by Laurent Le Goff +package draw2d + +import ( + "freetype-go.googlecode.com/hg/freetype/raster" + "math" +) + +func SegmentArc(t LineTracer, x, y, rx, ry, start, angle, scale float64) { + end := start + angle + clockWise := true + if angle < 0 { + clockWise = false + } + ra := (math.Fabs(rx) + math.Fabs(ry)) / 2 + da := math.Acos(ra/(ra+0.125/scale)) * 2 + //normalize + if !clockWise { + da = -da + } + angle = start + da + var curX, curY float64 + for { + if (angle < end-da/4) != clockWise { + curX = x + math.Cos(end)*rx + curY = y + math.Sin(end)*ry + return curX, curY + } + curX = x + math.Cos(angle)*rx + curY = y + math.Sin(angle)*ry + + angle += da + t.LineTo(curX, curY) + } + t.LineTo(curX, curY) +} diff --git a/draw2d/curve/cubic_float64.go b/draw2d/curve/cubic_float64.go index f73f34e..a707bc3 100644 --- a/draw2d/curve/cubic_float64.go +++ b/draw2d/curve/cubic_float64.go @@ -40,9 +40,6 @@ func (c *CubicCurveFloat64) Subdivide(c1, c2 *CubicCurveFloat64) (x23, y23 float } func (curve *CubicCurveFloat64) Segment(t LineTracer, flattening_threshold float64) { - // Add the first point - t.LineTo(curve.X1, curve.Y1) - var curves [CurveRecursionLimit]CubicCurveFloat64 curves[0] = *curve i := 0 diff --git a/draw2d/curve/cubic_float64_others.go b/draw2d/curve/cubic_float64_others.go index 4e71fc9..5537d60 100644 --- a/draw2d/curve/cubic_float64_others.go +++ b/draw2d/curve/cubic_float64_others.go @@ -63,8 +63,6 @@ func (c *CubicCurveFloat64) EstimateDistance() float64 { // subdivide the curve in straight lines using line approximation and Casteljau recursive subdivision func (c *CubicCurveFloat64) SegmentRec(t LineTracer, flattening_threshold float64) { - // reinit segments - t.LineTo(c.X1, c.Y1) c.segmentRec(t, flattening_threshold) t.LineTo(c.X4, c.Y4) } @@ -115,7 +113,6 @@ func (c *CubicCurveFloat64) AdaptiveSegmentRec(t LineTracer, approximationScale, cuspLimit = computeCuspLimit(cuspLimit) distanceToleranceSquare := 0.5 / approximationScale distanceToleranceSquare = distanceToleranceSquare * distanceToleranceSquare - t.LineTo(c.X1, c.Y1) c.adaptiveSegmentRec(t, 0, distanceToleranceSquare, angleTolerance, cuspLimit) t.LineTo(c.X4, c.Y4) } @@ -314,8 +311,6 @@ func (c *CubicCurveFloat64) adaptiveSegmentRec(t LineTracer, level int, distance } func (curve *CubicCurveFloat64) AdaptiveSegment(t LineTracer, approximationScale, angleTolerance, cuspLimit float64) { - // Add the first point - t.LineTo(curve.X1, curve.Y1) cuspLimit = computeCuspLimit(cuspLimit) distanceToleranceSquare := 0.5 / approximationScale distanceToleranceSquare = distanceToleranceSquare * distanceToleranceSquare @@ -529,7 +524,6 @@ func (curve *CubicCurveFloat64) AdaptiveSegment(t LineTracer, approximationScale func (c *CubicCurveFloat64) ParabolicSegment(t LineTracer, flattening_threshold float64) { - t.LineTo(c.X1, c.Y1) estimatedIFP := c.numberOfInflectionPoints() if estimatedIFP == 0 { // If no inflection points then apply PA on the full Bezier segment. diff --git a/draw2d/curve/curve_test.go b/draw2d/curve/curve_test.go index 038b25d..e023706 100644 --- a/draw2d/curve/curve_test.go +++ b/draw2d/curve/curve_test.go @@ -108,6 +108,7 @@ func drawPoints(img draw.Image, c image.Color, s ...float64) image.Image { func TestCubicCurveRec(t *testing.T) { for i, curve := range testsCubicFloat64 { var p Path + p.LineTo(curve.X1, Y1) curve.SegmentRec(&p, flattening_threshold) img := image.NewNRGBA(300, 300) raster.PolylineBresenham(img, image.NRGBAColor{0xff, 0, 0, 0xff}, curve.X1, curve.Y1, curve.X2, curve.Y2, curve.X3, curve.Y3, curve.X4, curve.Y4) @@ -123,6 +124,7 @@ func TestCubicCurveRec(t *testing.T) { func TestCubicCurve(t *testing.T) { for i, curve := range testsCubicFloat64 { var p Path + p.LineTo(curve.X1, Y1) curve.Segment(&p, flattening_threshold) img := image.NewNRGBA(300, 300) raster.PolylineBresenham(img, image.NRGBAColor{0xff, 0, 0, 0xff}, curve.X1, curve.Y1, curve.X2, curve.Y2, curve.X3, curve.Y3, curve.X4, curve.Y4) @@ -138,6 +140,7 @@ func TestCubicCurve(t *testing.T) { func TestCubicCurveAdaptiveRec(t *testing.T) { for i, curve := range testsCubicFloat64 { var p Path + p.LineTo(curve.X1, Y1) curve.AdaptiveSegmentRec(&p, 1, 0, 0) img := image.NewNRGBA(300, 300) raster.PolylineBresenham(img, image.NRGBAColor{0xff, 0, 0, 0xff}, curve.X1, curve.Y1, curve.X2, curve.Y2, curve.X3, curve.Y3, curve.X4, curve.Y4) @@ -153,6 +156,7 @@ func TestCubicCurveAdaptiveRec(t *testing.T) { func TestCubicCurveAdaptive(t *testing.T) { for i, curve := range testsCubicFloat64 { var p Path + p.LineTo(curve.X1, Y1) curve.AdaptiveSegment(&p, 1, 0, 0) img := image.NewNRGBA(300, 300) raster.PolylineBresenham(img, image.NRGBAColor{0xff, 0, 0, 0xff}, curve.X1, curve.Y1, curve.X2, curve.Y2, curve.X3, curve.Y3, curve.X4, curve.Y4) @@ -168,6 +172,7 @@ func TestCubicCurveAdaptive(t *testing.T) { func TestCubicCurveParabolic(t *testing.T) { for i, curve := range testsCubicFloat64 { var p Path + p.LineTo(curve.X1, Y1) curve.ParabolicSegment(&p, flattening_threshold) img := image.NewNRGBA(300, 300) raster.PolylineBresenham(img, image.NRGBAColor{0xff, 0, 0, 0xff}, curve.X1, curve.Y1, curve.X2, curve.Y2, curve.X3, curve.Y3, curve.X4, curve.Y4) @@ -184,6 +189,7 @@ func TestCubicCurveParabolic(t *testing.T) { func TestQuadCurve(t *testing.T) { for i, curve := range testsQuadFloat64 { var p Path + p.LineTo(curve.X1, Y1) curve.Segment(&p, flattening_threshold) img := image.NewNRGBA(300, 300) raster.PolylineBresenham(img, image.NRGBAColor{0xff, 0, 0, 0xff}, curve.X1, curve.Y1, curve.X2, curve.Y2, curve.X3, curve.Y3) @@ -199,6 +205,7 @@ func BenchmarkCubicCurveRec(b *testing.B) { for i := 0; i < b.N; i++ { for _, curve := range testsCubicFloat64 { p := Path{make([]float64, 0, 32)} + p.LineTo(curve.X1, Y1) curve.SegmentRec(&p, flattening_threshold) } } @@ -208,6 +215,7 @@ func BenchmarkCubicCurve(b *testing.B) { for i := 0; i < b.N; i++ { for _, curve := range testsCubicFloat64 { p := Path{make([]float64, 0, 32)} + p.LineTo(curve.X1, Y1) curve.Segment(&p, flattening_threshold) } } @@ -217,6 +225,7 @@ func BenchmarkCubicCurveAdaptiveRec(b *testing.B) { for i := 0; i < b.N; i++ { for _, curve := range testsCubicFloat64 { p := Path{make([]float64, 0, 32)} + p.LineTo(curve.X1, Y1) curve.AdaptiveSegmentRec(&p, 1, 0, 0) } } @@ -226,6 +235,7 @@ func BenchmarkCubicCurveAdaptive(b *testing.B) { for i := 0; i < b.N; i++ { for _, curve := range testsCubicFloat64 { p := Path{make([]float64, 0, 32)} + p.LineTo(curve.X1, Y1) curve.AdaptiveSegment(&p, 1, 0, 0) } } @@ -235,6 +245,7 @@ func BenchmarkCubicCurveParabolic(b *testing.B) { for i := 0; i < b.N; i++ { for _, curve := range testsCubicFloat64 { p := Path{make([]float64, 0, 32)} + p.LineTo(curve.X1, Y1) curve.ParabolicSegment(&p, flattening_threshold) } } @@ -244,6 +255,7 @@ func BenchmarkQuadCurve(b *testing.B) { for i := 0; i < b.N; i++ { for _, curve := range testsQuadFloat64 { p := Path{make([]float64, 0, 32)} + p.LineTo(curve.X1, Y1) curve.Segment(&p, flattening_threshold) } } diff --git a/draw2d/curve/quad_float64.go b/draw2d/curve/quad_float64.go index ab30c70..4f776b7 100644 --- a/draw2d/curve/quad_float64.go +++ b/draw2d/curve/quad_float64.go @@ -28,9 +28,6 @@ func (c *QuadCurveFloat64) Subdivide(c1, c2 *QuadCurveFloat64) { func (curve *QuadCurveFloat64) Segment(t LineTracer, flattening_threshold float64) { - // Add the first point - t.LineTo(curve.X1, curve.Y1) - var curves [CurveRecursionLimit]QuadCurveFloat64 curves[0] = *curve i := 0