Skip to content

Instantly share code, notes, and snippets.

@simonecesano
Last active August 22, 2021 09:27
Show Gist options
  • Save simonecesano/cc9d6ca5289fbdf97607d1fa55330cd9 to your computer and use it in GitHub Desktop.
Save simonecesano/cc9d6ca5289fbdf97607d1fa55330cd9 to your computer and use it in GitHub Desktop.

La documentazione di svgpathtools è qui - non è perfetta, ma credo ti serva solo sapere come si converte una curva a una polinomiale in numpy, che è annotata nel programma in python.

Un bel documento sulle curve di Bezier è qui, e la documentazione su <path> in SVG è qui

Le due domande che ti ho mandato sono qui e qui

Parsed path is 1774 long

Parsed path has 14 segments

Segment 0

Python object

CubicBezier(start=(269.68858+24.762486j), control1=(229.17994+23.061973j), control2=(187.55291+49.515361999999996j), end=(179.14956+90.566948j))

CubicBezier

b.point(x) = (269.68858+24.762486j)*(1-t)^3 + 3*(229.17994+23.061973j)*(1-t)^2*t + 3*(187.55291+49.515361999999996j)*(1-t)*t^2 + (179.14956+90.566948j)*t^3

Standard form

                   3                     2
(34.34 + -13.56j) t + (-3.355 + 84.46j) t + (-121.5 + -5.102j) t + (269.7 + 24.76j)

Segment 1

Python object

CubicBezier(start=(179.14956+90.566948j), control1=(166.00662+127.95951j), control2=(161.91976+167.59620999999999j), end=(157.83991+206.73017j))

CubicBezier

b.point(x) = (179.14956+90.566948j)*(1-t)^3 + 3*(166.00662+127.95951j)*(1-t)^2*t + 3*(161.91976+167.59620999999999j)*(1-t)*t^2 + (157.83991+206.73017j)*t^3

Standard form

                    3                    2
(-9.049 + -2.747j) t + (27.17 + 6.732j) t + (-39.43 + 112.2j) t + (179.1 + 90.57j)

Segment 2

Python object

CubicBezier(start=(157.83991+206.73017j), control1=(160.02+242.26772999999997j), control2=(159.84508+279.05634999999995j), end=(176.334+311.74527j))

CubicBezier

b.point(x) = (157.83991+206.73017j)*(1-t)^3 + 3*(160.02+242.26772999999997j)*(1-t)^2*t + 3*(159.84508+279.05634999999995j)*(1-t)*t^2 + (176.334+311.74527j)*t^3

Standard form

                   3                     2
(19.02 + -5.351j) t + (-7.065 + 3.753j) t + (6.54 + 106.6j) t + (157.8 + 206.7j)

Segment 3

Python object

CubicBezier(start=(176.334+311.74527j), control1=(193.99072+361.62555j), control2=(216.93461000000002+401.09014j), end=(232.57034+449.3044j))

CubicBezier

b.point(x) = (176.334+311.74527j)*(1-t)^3 + 3*(193.99072+361.62555j)*(1-t)^2*t + 3*(216.93461000000002+401.09014j)*(1-t)*t^2 + (232.57034+449.3044j)*t^3

Standard form

                  3                     2
(-12.6 + 19.17j) t + (15.86 + -31.25j) t + (52.97 + 149.6j) t + (176.3 + 311.7j)

Segment 4

Python object

CubicBezier(start=(232.57034+449.3044j), control1=(240.59013+482.42762999999997j), control2=(231.92991999999998+515.4757099999999j), end=(232.65573999999998+548.61444j))

CubicBezier

b.point(x) = (232.57034+449.3044j)*(1-t)^3 + 3*(240.59013+482.42762999999997j)*(1-t)^2*t + 3*(231.92991999999998+515.4757099999999j)*(1-t)*t^2 + (232.65573999999998+548.61444j)*t^3

Standard form

                   3                       2
(26.07 + 0.1658j) t + (-50.04 + -0.2255j) t + (24.06 + 99.37j) t + (232.6 + 449.3j)

Segment 5

Python object

CubicBezier(start=(232.65573999999998+548.61444j), control1=(230.95422+607.4213599999999j), control2=(213.96302999999997+666.58476j), end=(229.08323+724.9743199999999j))

CubicBezier

b.point(x) = (232.65573999999998+548.61444j)*(1-t)^3 + 3*(230.95422+607.4213599999999j)*(1-t)^2*t + 3*(213.96302999999997+666.58476j)*(1-t)*t^2 + (229.08323+724.9743199999999j)*t^3

Standard form

                 3                     2
(47.4 + -1.13j) t + (-45.87 + 1.069j) t + (-5.105 + 176.4j) t + (232.7 + 548.6j)

Segment 6

Python object

CubicBezier(start=(229.08323+724.9743199999999j), control1=(233.83543999999998+766.1593899999999j), control2=(276.69431+793.94369j), end=(313.52186+794.3263499999999j))

CubicBezier

b.point(x) = (229.08323+724.9743199999999j)*(1-t)^3 + 3*(233.83543999999998+766.1593899999999j)*(1-t)^2*t + 3*(276.69431+793.94369j)*(1-t)*t^2 + (313.52186+794.3263499999999j)*t^3

Standard form

                 3                    2
(-44.14 + -14j) t + (114.3 + -40.2j) t + (14.26 + 123.6j) t + (229.1 + 725j)

Segment 7

Python object

CubicBezier(start=(313.52186+794.3263499999999j), control1=(350.34942+794.709j), control2=(380.12225+776.1642899999999j), end=(391.39668+744.0384499999999j))

CubicBezier

b.point(x) = (313.52186+794.3263499999999j)*(1-t)^3 + 3*(350.34942+794.709j)*(1-t)^2*t + 3*(380.12225+776.1642899999999j)*(1-t)*t^2 + (391.39668+744.0384499999999j)*t^3

Standard form

                   3                      2
(-11.44 + 5.346j) t + (-21.16 + -56.78j) t + (110.5 + 1.148j) t + (313.5 + 794.3j)

Segment 8

Python object

CubicBezier(start=(391.39668+744.0384499999999j), control1=(409.30074+702.0257299999998j), control2=(409.18903+662.5394299999999j), end=(407.81744000000003+610.37988j))

CubicBezier

b.point(x) = (391.39668+744.0384499999999j)*(1-t)^3 + 3*(409.30074+702.0257299999998j)*(1-t)^2*t + 3*(409.18903+662.5394299999999j)*(1-t)*t^2 + (407.81744000000003+610.37988j)*t^3

Standard form

                  3                     2
(16.76 + -15.2j) t + (-54.05 + 7.579j) t + (53.71 + -126j) t + (391.4 + 744j)

Segment 9

Python object

CubicBezier(start=(407.81744000000003+610.37988j), control1=(406.44585+558.22033j), control2=(414.25272+475.76565999999997j), end=(419.17633+432.2167099999999j))

CubicBezier

b.point(x) = (407.81744000000003+610.37988j)*(1-t)^3 + 3*(406.44585+558.22033j)*(1-t)^2*t + 3*(414.25272+475.76565999999997j)*(1-t)*t^2 + (419.17633+432.2167099999999j)*t^3

Standard form

                  3                     2
(-12.06 + 69.2j) t + (27.54 + -90.89j) t + (-4.115 + -156.5j) t + (407.8 + 610.4j)

Segment 10

Python object

CubicBezier(start=(419.17633+432.2167099999999j), control1=(424.09993000000003+388.66775999999993j), control2=(428.20425+377.29185999999993j), end=(427.83555+349.29007999999993j))

CubicBezier

b.point(x) = (419.17633+432.2167099999999j)*(1-t)^3 + 3*(424.09993000000003+388.66775999999993j)*(1-t)^2*t + 3*(428.20425+377.29185999999993j)*(1-t)*t^2 + (427.83555+349.29007999999993j)*t^3

Standard form

                   3                     2
(-3.654 + -48.8j) t + (-2.458 + 96.52j) t + (14.77 + -130.6j) t + (419.2 + 432.2j)

Segment 11

Python object

CubicBezier(start=(427.83555+349.29007999999993j), control1=(434.67597+283.85003j), control2=(417.4602+218.83964j), end=(391.752+159.17256j))

CubicBezier

b.point(x) = (427.83555+349.29007999999993j)*(1-t)^3 + 3*(434.67597+283.85003j)*(1-t)^2*t + 3*(417.4602+218.83964j)*(1-t)*t^2 + (391.752+159.17256j)*t^3

Standard form

                  3                     2
(15.56 + 4.914j) t + (-72.17 + 1.289j) t + (20.52 + -196.3j) t + (427.8 + 349.3j)

Segment 12

Python object

CubicBezier(start=(391.752+159.17256j), control1=(381.13197+135.51373j), control2=(372.07804+115.94824j), end=(355.87316+89.293903j))

CubicBezier

b.point(x) = (391.752+159.17256j)*(1-t)^3 + 3*(381.13197+135.51373j)*(1-t)^2*t + 3*(372.07804+115.94824j)*(1-t)*t^2 + (355.87316+89.293903j)*t^3

Standard form

                    3                    2
(-8.717 + -11.18j) t + (4.698 + 12.28j) t + (-31.86 + -70.98j) t + (391.8 + 159.2j)

Segment 13

Python object

CubicBezier(start=(355.87316+89.293903j), control1=(339.66828+62.639564j), control2=(309.19251+27.626442j), end=(269.68858+24.762486j))

CubicBezier

b.point(x) = (355.87316+89.293903j)*(1-t)^3 + 3*(339.66828+62.639564j)*(1-t)^2*t + 3*(309.19251+27.626442j)*(1-t)*t^2 + (269.68858+24.762486j)*t^3

Standard form

                  3                      2
(5.243 + 40.51j) t + (-42.81 + -25.08j) t + (-48.61 + -79.96j) t + (355.9 + 89.29j)
from svgpathtools import parse_path, kinks
import numpy
# a bunch of paths - atually all quite similar
paths = [
'm 269.68858,24.762486 c -40.50864,-1.700513 -82.13567,24.752876 -90.53902,65.804462 -13.14294,37.392562 -17.2298,77.029262 -21.30965,116.163222 2.18009,35.53756 2.00517,72.32618 18.49409,105.0151 17.65672,49.88028 40.60061,89.34487 56.23634,137.55913 8.01979,33.12323 -0.64042,66.17131 0.0854,99.31004 -1.70152,58.80692 -18.69271,117.97032 -3.57251,176.35988 4.75221,41.18507 47.61108,68.96937 84.43863,69.35203 36.82756,0.38265 66.60039,-18.16206 77.87482,-50.2879 17.90406,-42.01272 17.79235,-81.49902 16.42076,-133.65857 -1.37159,-52.15955 6.43528,-134.61422 11.35889,-178.16317 4.9236,-43.54895 9.02792,-54.92485 8.65922,-82.92663 C 434.67597,283.85003 417.4602,218.83964 391.752,159.17256 381.13197,135.51373 372.07804,115.94824 355.87316,89.293903 339.66828,62.639564 309.19251,27.626442 269.68858,24.762486 Z',
'm 269.903,19.8186 c -11.91711,-0.51685 -32.27731,1.070319 -53.46034,13.363287 -7.57964,4.398624 -15.09441,10.115707 -21.7639,17.309543 -6.10547,6.585479 -11.48984,14.405852 -15.42262,23.411503 -1.88956,4.341093 -3.20655,8.762796 -4.45743,13.203647 -0.006,0.02087 -0.16665,0.593017 -0.17253,0.613887 -0.92526,3.298648 -2.13708,7.795125 -3.58284,11.703021 -0.0335,0.0905 -0.0643,0.181961 -0.0924,0.274263 -10.08152,33.076419 -13.8021,65.940699 -18.03284,106.519239 -0.0282,0.27038 -0.0341,0.54266 -0.0175,0.814 0.98132,16.11317 1.53474,33.95368 3.54713,50.93551 2.03496,17.17236 5.60753,34.19583 12.80558,50.3898 0.01,0.0224 0.02,0.0446 0.0303,0.0669 2.63691,5.70301 4.88806,11.66869 7.07194,17.50312 2.39713,6.40418 4.5705,12.24991 7.19584,18.13489 8.15411,19.54232 16.41702,37.29627 23.38065,53.17688 10.17192,23.19711 16.22795,38.97872 20.92776,53.58235 a 4.9485337,4.9485337 90 0 0 9.4212,-3.03198 c -4.83331,-15.01844 -11.02505,-31.12699 -21.28502,-54.5249 -7.02031,-16.00985 -15.28013,-33.76328 -23.33392,-53.06904 -0.0157,-0.0377 -0.032,-0.0753 -0.0486,-0.11262 -2.4887,-5.57281 -4.56,-11.13612 -6.98887,-17.62505 -2.16627,-5.78741 -4.53371,-12.07537 -7.34197,-18.15331 -6.63971,-14.94999 -10.03852,-30.89399 -12.00657,-47.50167 -1.9519,-16.47139 -2.48119,-33.55744 -3.4719,-49.96405 4.19097,-40.19716 7.83789,-72.12408 17.5727,-104.11915 1.59772,-4.346868 2.91877,-9.259422 3.77871,-12.325233 -0.007,0.02482 0.17656,-0.62828 0.1696,-0.603457 1.2399,-4.401869 2.40609,-8.261978 4.00337,-11.931579 3.44767,-7.894808 8.18241,-14.785879 13.6081,-20.638137 5.93027,-6.396497 12.64887,-11.517647 19.47371,-15.47825 19.10508,-11.087085 37.44871,-12.495977 48.06391,-12.035592 Z',
'm 317.49193,24.762486 c 40.50864,-1.700513 82.13567,24.752876 90.53902,65.804462 13.14294,37.392562 17.2298,77.029262 21.30965,116.163222 -2.18009,35.53756 -2.00517,72.32618 -18.49409,105.0151 -17.65672,49.88028 -40.60061,89.34487 -56.23634,137.55913 -8.01979,33.12323 0.64042,66.17131 -0.0854,99.31004 1.70152,58.80692 18.69271,117.97032 3.57251,176.35988 -4.75221,41.18507 -47.61108,68.96937 -84.43863,69.35203 -36.82756,0.38265 -66.60039,-18.16206 -77.87482,-50.2879 -17.90406,-42.01272 -17.79235,-81.49902 -16.42076,-133.65857 1.37159,-52.15955 -6.43528,-134.61422 -11.35889,-178.16317 -4.9236,-43.54895 -9.02792,-54.92485 -8.65922,-82.92663 -6.84042,-65.44005 10.37535,-130.45044 36.08355,-190.11752 10.62003,-23.65883 19.67396,-43.22432 35.87884,-69.878657 16.20488,-26.654339 46.68065,-61.667461 86.18458,-64.531417 z',
'M 43.179732,261.02847 C 43.179732,194.89491 43.179732,194.89491 109.1273,194.89491',
'm 43.179732,261.02847 c 0,-66.13356 60.431218,-66.13356 65.947568,-66.13356',
]
path = parse_path(paths[0])
print("Parsed path is %d long\n" % path.length())
print("Parsed path has %d segments\n" % len(path))
i=0
# the path is made up of segments
for s in path:
# convert segment to numpy polynomial for later use
p = s.poly()
print("### Segment %d\n" % i)
i += 1
# print segment as python object
print("#### Python object\n\n " + str(s) + "\n")
# prettify equation
bpretty = "{}*(1-t)^3 + 3*{}*(1-t)^2*t + 3*{}*(1-t)*t^2 + {}*t^3".format(*s.bpoints())
# print it, and print its standard format
print("#### CubicBezier\n\n b.point(x) = " +
bpretty + "\n\n" +
"#### Standard form\n\n " +
str(p).replace('x','t').replace("\n","\n ") + "\n")
# find roots - in this case of the derivative
# this is the part that needs figuring out
roots=numpy.roots(p.deriv())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment