Skip to content

Instantly share code, notes, and snippets.

@zeffii
Created August 7, 2014 16:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zeffii/e43f3ba67bf8043a17e8 to your computer and use it in GitHub Desktop.
Save zeffii/e43f3ba67bf8043a17e8 to your computer and use it in GitHub Desktop.
coffee_Arc path Redux

[ Launch: coffee_svg path test ] e43f3ba67bf8043a17e8 by zeffii
[ Launch: coffee_templatefux ] 6d59f4d6ef8145d48ef9 by zeffii
[ Launch: boomstick_motion_wcolor_coffee ] 6399870 by zeffii
[ Launch: boomstick_motion_wcolor_coffee ] 6382272 by zeffii
[ Launch: boomstick_motion_wcolor_coffee ] 6382237 by zeffii
[ Launch: boomstick_motion_wcolor_coffee ] 6379220 by zeffii
[ Launch: boomstick_motion_wcolor ] 6376715 by zeffii
[ Launch: boomstick_motion2 ] 6365156 by zeffii
[ Launch: boomstick_motion ] 6364686 by zeffii
[ Launch: boomstick ] 6364584 by zeffii
[ Launch: zeffii default ] 6364028 by zeffii
[ Launch: zeffii default ] 5033869 by zeffii

{"description":"coffee_Arc path Redux","endpoint":"","display":"svg","public":true,"require":[],"fileconfigs":{"inlet.js":{"default":true,"vim":false,"emacs":false,"fontSize":12},"style.css":{"default":true,"vim":false,"emacs":false,"fontSize":12},"_.md":{"default":true,"vim":false,"emacs":false,"fontSize":12},"config.json":{"default":true,"vim":false,"emacs":false,"fontSize":12},"data2.csv":{"default":true,"vim":false,"emacs":false,"fontSize":12},"util.js":{"default":true,"vim":false,"emacs":false,"fontSize":12},"injet.coffee":{"default":true,"vim":false,"emacs":false,"fontSize":12},"inlet.coffee":{"default":true,"vim":false,"emacs":false,"fontSize":12},"utils.coffee":{"default":true,"vim":false,"emacs":false,"fontSize":12},"details.ssv":{"default":true,"vim":false,"emacs":false,"fontSize":12},"details.txt":{"default":true,"vim":false,"emacs":false,"fontSize":12},"details.tsv":{"default":true,"vim":false,"emacs":false,"fontSize":12}},"fullscreen":false,"play":false,"loop":false,"restart":false,"autoinit":true,"pause":true,"loop_type":"period","bv":false,"nclones":15,"clone_opacity":0.4,"duration":3000,"ease":"linear","dt":0.01,"thumbnail":"http://i.imgur.com/rUN41qB.png","ajax-caching":true}
sqrt = Math.sqrt
sin = Math.sin
cos = Math.cos
acos = Math.acos
pi = Math.PI
abs = Math.abs
degrees = (x) ->
# Converts angle x from radians to degrees.
180 * x / pi
radians = (x) ->
# Converts angle x from degrees to radians
x / 180 * pi
class Arc
'''
translated from python to coffeescript
original found at
https://github.com/regebro/svg.path/blob/master/src/svg/path/path.py
'''
constructor: (@start, @radius, @rotation, @arc, @sweep, @end) ->
"""radius is complex, rotation is in degrees,
large and sweep are 1 or 0"""
@arc = if (@arc == 1) then true else false
@sweep = if (@sweep == 1) then true else false
@parameterize()
parameterize: ->
# Conversion from endpoint to center parameterization
# http://www.w3.org/TR/SVG/implnote.html#ArcImplementationNotes
cosr = cos(radians(@rotation))
sinr = sin(radians(@rotation))
dx = (@start.real - @end.real) / 2
dy = (@start.imag - @end.imag) / 2
x1prim = cosr * dx + sinr * dy
x1prim_sq = x1prim * x1prim
y1prim = -sinr * dx + cosr * dy
y1prim_sq = y1prim * y1prim
rx = @radius.real
rx_sq = rx * rx
ry = @radius.imag
ry_sq = ry * ry
# Correct out of range radii
radius_check = (x1prim_sq / rx_sq) + (y1prim_sq / ry_sq)
if radius_check > 1
rx *= sqrt(radius_check)
ry *= sqrt(radius_check)
rx_sq = rx * rx
ry_sq = ry * ry
t1 = rx_sq * y1prim_sq
t2 = ry_sq * x1prim_sq
c = sqrt(abs((rx_sq * ry_sq - t1 - t2) / (t1 + t2)))
if @arc == @sweep
c = -c
cxprim = c * rx * y1prim / ry
cyprim = -c * ry * x1prim / rx
@center =
real: ((cosr * cxprim - sinr * cyprim) + ((@start.real + @end.real) / 2))
imag: ((sinr * cxprim + cosr * cyprim) + ((@start.imag + @end.imag) / 2))
ux = (x1prim - cxprim) / rx
uy = (y1prim - cyprim) / ry
vx = (-x1prim - cxprim) / rx
vy = (-y1prim - cyprim) / ry
n = sqrt(ux * ux + uy * uy)
p = ux
theta = degrees(acos(p / n))
if uy < 0
theta = -theta
@theta = theta % 360
n = sqrt((ux * ux + uy * uy) * (vx * vx + vy * vy))
p = ux * vx + uy * vy
if p == 0
delta = degrees(acos(0))
else
delta = degrees(acos(p / n))
if (ux * vy - uy * vx) < 0
delta = -delta
@delta = delta % 360
if not @sweep
@delta -= 360
point: (pos) ->
angle = radians(@theta + (@delta * pos))
cosr = cos(radians(@rotation))
sinr = sin(radians(@rotation))
x = cosr * cos(angle) * @radius.real - sinr * sin(angle) * @radius.imag + @center.real
y = sinr * cos(angle) * @radius.real + cosr * sin(angle) * @radius.imag + @center.imag
[x, y]
A = (args) ->
"A" + args
Ar = (start_xy, args) ->
[rx, ry, rotate, flag1, flag2, x, y] = args
"""
it is a very fuzzy function. assumptions and thoughts:
- if rx === ry, does the radius expand if distance is too big to bridge?
- if rx !== ry, are both scaled if distance is too large?
"""
num_points = 20 # off by one, I know.
start = real:start_xy[0], imag:start_xy[1]
radius = real:rx, imag:ry
end = real:x, imag:y
myArc = new Arc(start, radius, rotate, flag1, flag2, end)
arc_points = []
theta = 1/num_points
for i in [0..num_points]
xy = myArc.point(theta * i)
arc_points.push(xy)
return "L " + arc_points
svg = d3.select("svg")
svg.append("rect").attr({width:"100%", height:"100%", fill: '#c6c6c6'})
style_1 =
fill: 'none',
stroke: '#17f1bb'
'stroke-width': 4
style_2 =
fill: 'none',
stroke: '#45012c'
'stroke-width': 2
group1 = svg.append('g')
.classed('group1', true)
.attr
transform: 'translate(' + [172, 65] + ')'
''' DEMO THESE --------------------'''
start_xy = [-4,110]
rx = 129
ry = 111
rot = 26
flag1 = 1
flag2 = 0
end_xy = [116, 107]
''' END ---------------------------'''
ArcArray = [rx, ry, rot, flag1, flag2, end_xy[0], end_xy[1]]
group1.append('path')
.attr
d: () -> "M" + start_xy + A(ArcArray)
.style style_1
group1.append('path')
.attr
d: () -> "M" + start_xy + Ar(start_xy, ArcArray)
.style style_2
.cm-s-elegant.CodeMirror { background: #1e2426; color: #696969; }
.cm-s-elegant div.CodeMirror-selected {background: #064968 !important;} /* 33322B*/
.cm-s-elegant span.cm-variable { color:#22EFFF; }
.cm-s-elegant span.cm-variable-2 { color: #FFCCB4; }
.cm-s-elegant span.cm-variable-3 { color: white; }
.cm-s-elegant span.cm-string { color: Chartreuse; }
.cm-s-elegant span.cm-string-2 {color: Chartreuse;}
.cm-s-elegant span.cm-def {color: #FFCCB4; opacity: 1.0}
.cm-s-elegant span.cm-bracket { color: #EBEFE7; }
.cm-s-elegant pre { color:#FFF; }
.cm-s-elegant span.cm-qualifier { color:#C0C0C0; }
.cm-s-elegant span.cm-comment { color: #AFB4B4;}
.cm-s-elegant span.cm-property {color: #FDA676;}
.cm-s-elegant span.cm-number { color: #FF92EE;}
.cm-s-elegant span.cm-keyword { color: #FFFF18; }
.cm-s-elegant .CodeMirror-cursor { border-left: 1px solid white !important; }
.cm-s-elegant .CodeMirror-gutters {background: #505050;}
.cm-s-elegant .CodeMirror-linenumber {color: #D3D3D3;}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment