luser droog
2022-10-19 16:27:55 UTC
Pursuant to Julian's parallel curve threads and my "snipping the ears"
thread, I dug into a few articles and found one with code that I could
mostly implement in PostScript.
Using this, one could define separate heuristics for each class of
curve and maybe convert loops into cusps. Thus identifying and
snipping all the ears.
But it calls for 3 functions (H0, H1, H2) which I don't know how to
implement. It's supposed to determine the position of the Origin
in the "hodograph associated with the implicit Bezier curve".
So presumably, I have to ... I don't know what .... do some crazy
stuff with resultant matrices and Sylvester matrices? Then take
the derivatives of the implicit equation wrt u and v, I suppose.
But I don't know how to do step 2.
$ cat bez.ps
% https://www.researchgate.net/profile/Abdelouahad-Bayar/publication/317351174_A_Practical_Way_to_Characterize_Non-degenerate_Cubic_BEZIER_Curves/links/5b43ee210f7e9bb59b1b0c0f/A-Practical-Way-to-Characterize-Non-degenerate-Cubic-BEZIER-Curves.pdf?origin=publication_detail
/bzGeoChz {
1 dict begin {y3 x3 y2 x2 y1 x1 y0 x0}{exch def}forall
/gx x3 x0 sub def
/gy y3 y0 sub def
/flt
3 x1 x0 sub mul 3 y1 y0 sub mul
3 x2 x1 sub mul 3 y2 y1 sub mul
3 x3 x2 sub mul 3 y3 y2 sub mul
0 0 linearFlag
3 x1 x0 sub mul 3 y1 y0 sub mul
3 x2 x1 sub mul 3 y2 y1 sub mul
3 x3 x2 sub mul 3 y3 y2 sub mul
gx gy linearFlag
xor
def
flt 0 eq {
/flt 7
x0 y0 x1 y1 x2 y2 x3 y3 0 0 quadLocationFlag
add def
} if
flt 1 eq { 1 }{
flt 6 eq { 2 }{
flt 10 eq { 3 }{
flt 2 eq
flt 4 eq or { 4 }{
flt 3 eq
flt 5 eq or { 5 }{
flt 9 eq { 6 }{
flt 7 eq { 7 }{
8
}ifelse }ifelse }ifelse }ifelse }ifelse }ifelse }ifelse
end
} def
/quadLocationFlag {
1 dict begin {y x y3 x3 y2 x2 y1 x2 y0 x0}{exch def}forall
/flag
x0 y0 x1 y1 x2 y2 x y H0
dup 0 gt { pop 2 }{
0 lt { 1 }{ 0 } ifelse
} ifelse
def
x0 y0 x1 y1 x2 y2 x y H1 0 lt
x0 y0 x1 y1 x2 y2 x y H2 0 lt or {
/flag flag 2 add def
} if
flag
end
} def
/linearFlag {
1 dict begin {y x hy2 hx2 hy1 hx1 hy0 hx0}{exch def}forall
/flag 0 def
/gx hx0 hx1 hx2 add add 3 div def
/gy hy0 hy1 hy2 add add 3 div def
hx1 hx0 sub gy hy0 sub mul
hy1 hy0 sub gx hx0 sub mul sub
0 gt {
hx1 hx0 sub y hy0 sub mul
hy1 hy0 sub x hx0 sub mul sub
0 ge {
/flag flag 4 add def
} if
hx2 hx1 sub y hy1 sub mul
hy2 hy1 sub x hx1 sub mul sub
0 ge {
/flag flag 2 add def
} if
hx0 hx2 sub y hy2 sub mul
hy0 hy2 sub x hx2 sub mul sub
0 ge {
/flag flag 1 add def
} if
}{
hx1 hx0 sub y hy0 sub mul
hy1 hy0 sub x hx0 sub mul sub
0 gt {
/flag flag 4 add def
} if
hx2 hx1 sub y hy1 sub mul
hy2 hy1 sub x hx1 sub mul sub
0 gt {
/flag flag 2 add def
} if
hx0 hx2 sub y hy2 sub mul
hy0 hy2 sub x hx2 sub mul sub
0 gt {
/flag flag 1 add def
} if
} ifelse
end
} def
/H0 {
} def
/H1 {
} def
/H2 {
} def
thread, I dug into a few articles and found one with code that I could
mostly implement in PostScript.
Using this, one could define separate heuristics for each class of
curve and maybe convert loops into cusps. Thus identifying and
snipping all the ears.
But it calls for 3 functions (H0, H1, H2) which I don't know how to
implement. It's supposed to determine the position of the Origin
in the "hodograph associated with the implicit Bezier curve".
So presumably, I have to ... I don't know what .... do some crazy
stuff with resultant matrices and Sylvester matrices? Then take
the derivatives of the implicit equation wrt u and v, I suppose.
But I don't know how to do step 2.
$ cat bez.ps
% https://www.researchgate.net/profile/Abdelouahad-Bayar/publication/317351174_A_Practical_Way_to_Characterize_Non-degenerate_Cubic_BEZIER_Curves/links/5b43ee210f7e9bb59b1b0c0f/A-Practical-Way-to-Characterize-Non-degenerate-Cubic-BEZIER-Curves.pdf?origin=publication_detail
/bzGeoChz {
1 dict begin {y3 x3 y2 x2 y1 x1 y0 x0}{exch def}forall
/gx x3 x0 sub def
/gy y3 y0 sub def
/flt
3 x1 x0 sub mul 3 y1 y0 sub mul
3 x2 x1 sub mul 3 y2 y1 sub mul
3 x3 x2 sub mul 3 y3 y2 sub mul
0 0 linearFlag
3 x1 x0 sub mul 3 y1 y0 sub mul
3 x2 x1 sub mul 3 y2 y1 sub mul
3 x3 x2 sub mul 3 y3 y2 sub mul
gx gy linearFlag
xor
def
flt 0 eq {
/flt 7
x0 y0 x1 y1 x2 y2 x3 y3 0 0 quadLocationFlag
add def
} if
flt 1 eq { 1 }{
flt 6 eq { 2 }{
flt 10 eq { 3 }{
flt 2 eq
flt 4 eq or { 4 }{
flt 3 eq
flt 5 eq or { 5 }{
flt 9 eq { 6 }{
flt 7 eq { 7 }{
8
}ifelse }ifelse }ifelse }ifelse }ifelse }ifelse }ifelse
end
} def
/quadLocationFlag {
1 dict begin {y x y3 x3 y2 x2 y1 x2 y0 x0}{exch def}forall
/flag
x0 y0 x1 y1 x2 y2 x y H0
dup 0 gt { pop 2 }{
0 lt { 1 }{ 0 } ifelse
} ifelse
def
x0 y0 x1 y1 x2 y2 x y H1 0 lt
x0 y0 x1 y1 x2 y2 x y H2 0 lt or {
/flag flag 2 add def
} if
flag
end
} def
/linearFlag {
1 dict begin {y x hy2 hx2 hy1 hx1 hy0 hx0}{exch def}forall
/flag 0 def
/gx hx0 hx1 hx2 add add 3 div def
/gy hy0 hy1 hy2 add add 3 div def
hx1 hx0 sub gy hy0 sub mul
hy1 hy0 sub gx hx0 sub mul sub
0 gt {
hx1 hx0 sub y hy0 sub mul
hy1 hy0 sub x hx0 sub mul sub
0 ge {
/flag flag 4 add def
} if
hx2 hx1 sub y hy1 sub mul
hy2 hy1 sub x hx1 sub mul sub
0 ge {
/flag flag 2 add def
} if
hx0 hx2 sub y hy2 sub mul
hy0 hy2 sub x hx2 sub mul sub
0 ge {
/flag flag 1 add def
} if
}{
hx1 hx0 sub y hy0 sub mul
hy1 hy0 sub x hx0 sub mul sub
0 gt {
/flag flag 4 add def
} if
hx2 hx1 sub y hy1 sub mul
hy2 hy1 sub x hx1 sub mul sub
0 gt {
/flag flag 2 add def
} if
hx0 hx2 sub y hy2 sub mul
hy0 hy2 sub x hx2 sub mul sub
0 gt {
/flag flag 1 add def
} if
} ifelse
end
} def
/H0 {
} def
/H1 {
} def
/H2 {
} def