Start path package
This commit is contained in:
parent
06178b5d2d
commit
d6812fd8e6
3 changed files with 283 additions and 0 deletions
44
path/drawing_kit.go
Normal file
44
path/drawing_kit.go
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
// Copyright 2010 The draw2d Authors. All rights reserved.
|
||||||
|
// created: 13/12/2010 by Laurent Le Goff
|
||||||
|
|
||||||
|
package path
|
||||||
|
|
||||||
|
import (
|
||||||
|
"math"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Rectangle draw a rectangle using a PathBuilder
|
||||||
|
func Rectangle(path PathBuilder, x1, y1, x2, y2 float64) {
|
||||||
|
path.MoveTo(x1, y1)
|
||||||
|
path.LineTo(x2, y1)
|
||||||
|
path.LineTo(x2, y2)
|
||||||
|
path.LineTo(x1, y2)
|
||||||
|
path.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// RoundedRectangle draw a rounded rectangle using a PathBuilder
|
||||||
|
func RoundedRectangle(path PathBuilder, x1, y1, x2, y2, arcWidth, arcHeight float64) {
|
||||||
|
arcWidth = arcWidth / 2
|
||||||
|
arcHeight = arcHeight / 2
|
||||||
|
path.MoveTo(x1, y1+arcHeight)
|
||||||
|
path.QuadCurveTo(x1, y1, x1+arcWidth, y1)
|
||||||
|
path.LineTo(x2-arcWidth, y1)
|
||||||
|
path.QuadCurveTo(x2, y1, x2, y1+arcHeight)
|
||||||
|
path.LineTo(x2, y2-arcHeight)
|
||||||
|
path.QuadCurveTo(x2, y2, x2-arcWidth, y2)
|
||||||
|
path.LineTo(x1+arcWidth, y2)
|
||||||
|
path.QuadCurveTo(x1, y2, x1, y2-arcHeight)
|
||||||
|
path.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ellipse draw an ellipse using a PathBuilder
|
||||||
|
func Ellipse(path PathBuilder, cx, cy, rx, ry float64) {
|
||||||
|
path.ArcTo(cx, cy, rx, ry, 0, -math.Pi*2)
|
||||||
|
path.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Circle draw an circle using a PathBuilder
|
||||||
|
func Circle(path PathBuilder, cx, cy, radius float64) {
|
||||||
|
path.ArcTo(cx, cy, radius, radius, 0, -math.Pi*2)
|
||||||
|
path.Close()
|
||||||
|
}
|
63
path/interpret.go
Normal file
63
path/interpret.go
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
// Copyright 2010 The draw2d Authors. All rights reserved.
|
||||||
|
// created: 06/12/2010 by Laurent Le Goff
|
||||||
|
|
||||||
|
package path
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/llgcode/draw2d/curve"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PathConverter struct {
|
||||||
|
converter LineBuilder
|
||||||
|
ApproximationScale float64
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPathConverter(converter LineBuilder) *PathConverter {
|
||||||
|
return &PathConverter{converter, 1, 0, 0, 0, 0}
|
||||||
|
}
|
||||||
|
|
||||||
|
// may not been in path instead put it in a troke package thing
|
||||||
|
func (c *PathConverter) Interpret(liner LineBuilder, scale float64, paths ...*Path) {
|
||||||
|
// First Point
|
||||||
|
var startX, startY float64 = 0, 0
|
||||||
|
// Current Point
|
||||||
|
var x, y float64 = 0, 0
|
||||||
|
for _, path := range paths {
|
||||||
|
i := 0
|
||||||
|
for _, cmd := range path.Components {
|
||||||
|
switch cmd {
|
||||||
|
case MoveToCmp:
|
||||||
|
x, y = path.Points[i], path.Points[i+1]
|
||||||
|
startX, startY = x, y
|
||||||
|
if i != 0 {
|
||||||
|
liner.End()
|
||||||
|
}
|
||||||
|
liner.MoveTo(x, y)
|
||||||
|
i += 2
|
||||||
|
case LineToCmp:
|
||||||
|
x, y = path.Points[i], path.Points[i+1]
|
||||||
|
liner.LineTo(x, y)
|
||||||
|
liner.LineJoin()
|
||||||
|
i += 2
|
||||||
|
case QuadCurveToCmp:
|
||||||
|
curve.TraceQuad(liner, path.Points[i-2:], 0.5)
|
||||||
|
x, y = path.Points[i+2], path.Points[i+3]
|
||||||
|
liner.LineTo(x, y)
|
||||||
|
i += 4
|
||||||
|
case CubicCurveToCmp:
|
||||||
|
curve.TraceCubic(liner, path.Points[i-2:], 0.5)
|
||||||
|
x, y = path.Points[i+4], path.Points[i+5]
|
||||||
|
liner.LineTo(x, y)
|
||||||
|
i += 6
|
||||||
|
case ArcToCmp:
|
||||||
|
x, y = arc(liner, path.Points[i], path.Points[i+1], path.Points[i+2], path.Points[i+3], path.Points[i+4], path.Points[i+5], scale)
|
||||||
|
liner.LineTo(x, y)
|
||||||
|
i += 6
|
||||||
|
case CloseCmp:
|
||||||
|
liner.LineTo(startX, startY)
|
||||||
|
liner.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
liner.End()
|
||||||
|
}
|
||||||
|
}
|
176
path/path.go
Normal file
176
path/path.go
Normal file
|
@ -0,0 +1,176 @@
|
||||||
|
// Copyright 2010 The draw2d Authors. All rights reserved.
|
||||||
|
// created: 21/11/2010 by Laurent Le Goff
|
||||||
|
|
||||||
|
// Package path implements function to build path
|
||||||
|
package path
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PathBuilder define method that create path
|
||||||
|
type PathBuilder interface {
|
||||||
|
// Return the current point of the current path
|
||||||
|
LastPoint() (x, y float64)
|
||||||
|
|
||||||
|
// MoveTo start a new path at (x, y) position
|
||||||
|
MoveTo(x, y float64)
|
||||||
|
|
||||||
|
// LineTo add a line to the current path
|
||||||
|
LineTo(x, y float64)
|
||||||
|
|
||||||
|
// QuadCurveTo add a quadratic curve to the current path
|
||||||
|
QuadCurveTo(cx, cy, x, y float64)
|
||||||
|
|
||||||
|
// CubicCurveTo add a cubic bezier curve to the current path
|
||||||
|
CubicCurveTo(cx1, cy1, cx2, cy2, x, y float64)
|
||||||
|
|
||||||
|
// ArcTo add an arc to the path
|
||||||
|
ArcTo(cx, cy, rx, ry, startAngle, angle float64)
|
||||||
|
|
||||||
|
// Close the current path
|
||||||
|
Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Component represent components of a path
|
||||||
|
type Component int
|
||||||
|
|
||||||
|
const (
|
||||||
|
MoveToCmp Component = iota
|
||||||
|
LineToCmp
|
||||||
|
QuadCurveToCmp
|
||||||
|
CubicCurveToCmp
|
||||||
|
ArcToCmp
|
||||||
|
CloseCmp
|
||||||
|
)
|
||||||
|
|
||||||
|
// Type Path store path
|
||||||
|
type Path struct {
|
||||||
|
Components []Component
|
||||||
|
Points []float64
|
||||||
|
x, y float64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Path) Clear() {
|
||||||
|
p.Components = p.Components[0:0]
|
||||||
|
p.Points = p.Points[0:0]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Path) appendToPath(cmd Component, points ...float64) {
|
||||||
|
p.Components = append(p.Components, cmd)
|
||||||
|
p.Points = append(p.Points, points...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy make a clone of the current path and return it
|
||||||
|
func (src *Path) Copy() (dest *Path) {
|
||||||
|
dest = new(Path)
|
||||||
|
dest.Components = make([]Component, len(src.Components))
|
||||||
|
copy(dest.Components, src.Components)
|
||||||
|
dest.Points = make([]float64, len(src.Points))
|
||||||
|
copy(dest.Points, src.Points)
|
||||||
|
dest.x, dest.y = src.x, src.y
|
||||||
|
return dest
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Path) LastPoint() (x, y float64) {
|
||||||
|
return p.x, p.y
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Path) IsEmpty() bool {
|
||||||
|
return len(p.Components) == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Path) Close() {
|
||||||
|
p.appendToPath(CloseCmp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Path) MoveTo(x, y float64) {
|
||||||
|
p.appendToPath(MoveToCmp, x, y)
|
||||||
|
|
||||||
|
p.x = x
|
||||||
|
p.y = y
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Path) LineTo(x, y float64) {
|
||||||
|
if len(p.Components) == 0 { //special case when no move has been done
|
||||||
|
p.MoveTo(0, 0)
|
||||||
|
}
|
||||||
|
p.appendToPath(LineToCmp, x, y)
|
||||||
|
p.x = x
|
||||||
|
p.y = y
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Path) QuadCurveTo(cx, cy, x, y float64) {
|
||||||
|
if len(p.Components) == 0 { //special case when no move has been done
|
||||||
|
p.MoveTo(0, 0)
|
||||||
|
}
|
||||||
|
p.appendToPath(QuadCurveToCmp, cx, cy, x, y)
|
||||||
|
p.x = x
|
||||||
|
p.y = y
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Path) CubicCurveTo(cx1, cy1, cx2, cy2, x, y float64) {
|
||||||
|
if len(p.Components) == 0 { //special case when no move has been done
|
||||||
|
p.MoveTo(0, 0)
|
||||||
|
}
|
||||||
|
p.appendToPath(CubicCurveToCmp, cx1, cy1, cx2, cy2, x, y)
|
||||||
|
p.x = x
|
||||||
|
p.y = y
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Path) ArcTo(cx, cy, rx, ry, startAngle, angle float64) {
|
||||||
|
endAngle := startAngle + angle
|
||||||
|
clockWise := true
|
||||||
|
if angle < 0 {
|
||||||
|
clockWise = false
|
||||||
|
}
|
||||||
|
// normalize
|
||||||
|
if clockWise {
|
||||||
|
for endAngle < startAngle {
|
||||||
|
endAngle += math.Pi * 2.0
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for startAngle < endAngle {
|
||||||
|
startAngle += math.Pi * 2.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
startX := cx + math.Cos(startAngle)*rx
|
||||||
|
startY := cy + math.Sin(startAngle)*ry
|
||||||
|
if len(p.Components) > 0 {
|
||||||
|
p.LineTo(startX, startY)
|
||||||
|
} else {
|
||||||
|
p.MoveTo(startX, startY)
|
||||||
|
}
|
||||||
|
p.appendToPath(ArcToCmp, cx, cy, rx, ry, startAngle, angle)
|
||||||
|
p.x = cx + math.Cos(endAngle)*rx
|
||||||
|
p.y = cy + math.Sin(endAngle)*ry
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Path) String() string {
|
||||||
|
s := ""
|
||||||
|
j := 0
|
||||||
|
for _, cmd := range p.Components {
|
||||||
|
switch cmd {
|
||||||
|
case MoveToCmp:
|
||||||
|
s += fmt.Sprintf("MoveTo: %f, %f\n", p.Points[j], p.Points[j+1])
|
||||||
|
j = j + 2
|
||||||
|
case LineToCmp:
|
||||||
|
s += fmt.Sprintf("LineTo: %f, %f\n", p.Points[j], p.Points[j+1])
|
||||||
|
j = j + 2
|
||||||
|
case QuadCurveToCmp:
|
||||||
|
s += fmt.Sprintf("QuadCurveTo: %f, %f, %f, %f\n", p.Points[j], p.Points[j+1], p.Points[j+2], p.Points[j+3])
|
||||||
|
j = j + 4
|
||||||
|
case CubicCurveToCmp:
|
||||||
|
s += fmt.Sprintf("CubicCurveTo: %f, %f, %f, %f, %f, %f\n", p.Points[j], p.Points[j+1], p.Points[j+2], p.Points[j+3], p.Points[j+4], p.Points[j+5])
|
||||||
|
j = j + 6
|
||||||
|
case ArcToCmp:
|
||||||
|
s += fmt.Sprintf("ArcTo: %f, %f, %f, %f, %f, %f\n", p.Points[j], p.Points[j+1], p.Points[j+2], p.Points[j+3], p.Points[j+4], p.Points[j+5])
|
||||||
|
j = j + 6
|
||||||
|
case CloseCmp:
|
||||||
|
s += "Close\n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
Loading…
Reference in a new issue