\documentclass{article}
%include lhs2TeX.fmt
\begin{document}
\begin{code}
{-# LANGUAGE FlexibleContexts, UnboxedTuples, BangPatterns, NamedFieldPuns, RecordWildCards, MagicHash, CPP #-}
module Graphics.Typography.Geometry.Bezier (
Curve(..),line,bezier3,
offset,
inter,
evalCurve,distance,
left,bottom,right,top) where
import Algebra.Polynomials.Bernstein
import Algebra.Polynomials.Numerical
import Graphics.Typography.Geometry
import qualified Data.Vector as V
import qualified Data.Vector.Unboxed as UV
import Data.List (partition,sort)
data Curve=
Bezier { cx::Bernsteinp Int Double,
cy::Bernsteinp Int Double,
t0::Double,
t1::Double }
| Offset { cx::Bernsteinp Int Double,
cy::Bernsteinp Int Double,
t0::Double,
t1::Double,
matrix::Matrix2 Double
}
| Circle { cx0::Double,
cy0::Double,
t0::Double,
t1::Double,
matrix::Matrix2 Double
}
deriving (Show)
line::Double->Double->Double->Double->Curve
line px py px' py'=Bezier { cx=Bernsteinp 2 $ UV.fromList [px,px'],
cy=Bernsteinp 2 $ UV.fromList [py,py'],
t0=0,t1=1 }
bezier3::Double->Double->Double->Double->Double->Double->Double->Double->Curve
bezier3 px0 py0 px1 py1 px2 py2 px3 py3=
Bezier { cx=Bernsteinp 4 $ UV.fromList [px0,px1,px2,px3],
cy=Bernsteinp 4 $ UV.fromList [py0,py1,py2,py3],
t0=0,t1=1 }
instance Geometric Curve where
translate x y cur@(Circle{cx0,cy0})=
cur { cx0=cx0+x,cy0=cy0+y }
translate x y cur=
cur { cx=(cx cur) { coefs=UV.map (+x) $ coefs $ cx cur},
cy=(cy cur) { coefs=UV.map (+y) $ coefs $ cy cur} }
apply m0@(Matrix2 a b c d) cir@(Circle{cx0,cy0,matrix})=
cir { cx0=a*cx0+b*cy0, cy0=c*cx0+d*cy0, matrix=m0*matrix }
apply (Matrix2 a b c d) cur=
cur { cx=(scale a $ cx cur)+(scale b $ cy cur),
cy=(scale c $ cx cur)+(scale d $ cy cur) }
evalCurve::Curve->Interval->(Interval,Interval)
evalCurve (Offset{..}) t=
let ix=intervalize cx
iy=intervalize cy
xt=eval ix t
yt=eval iy t
m@(Matrix2 a b c d)=intervalize matrix
(Matrix2 a_ b_ c_ d_)=inverse m
xt0'=eval (derivate ix) t
yt0'=eval (derivate iy) t
xt'=a_*xt0' + b_*yt0'
yt'=c_*xt0' + d_*yt0'
dd=sqrt $ xt'*xt' + yt'*yt'
in
(xt+(a*yt'-b*xt')/dd, yt+(c*yt'-d*xt')/dd)
evalCurve (Circle{..}) alpha=
let xx=cos alpha
yy=sin alpha
(Matrix2 a b c d)=intervalize matrix
in
(interval cx0+a*xx+b*yy, interval cy0+c*xx+d*yy)
evalCurve (Bezier{..}) t=
let ix=intervalize cx
iy=intervalize cy
xx=eval ix t
yy=eval iy t
in
(xx,yy)
data Topo=Dehors | SurLaLigne | Dedans deriving Eq
inter::Curve->Curve->[((Double,Double,Double,Double))]
inter op@(Offset { cx=bxp_,cy=byp_,matrix=mp,t0=t0a,t1=t1a })
(Offset { cx=bxq_,cy=byq_,matrix=mq,t0=t0b,t1=t1b })=
let thrx=1e-5
solutions _ []=[]
solutions thr boxes@(_:_)=
let sol0=concatMap (solve thr (V.fromList [eq0,eq1,eq2,eq3])) boxes
(correct,toRefine)=partition (\(u,v,_,_,_,_,_,_)->
let (xu,yu)=evalCurve op (Interval u u)
(xv,yv)=evalCurve op (Interval v v)
in
(iup $ (xu-xv)^(2::Int)+(yu-yv)^(2::Int))<=thrx) sol0
in
correct++(solutions (thr/2) toRefine)
in
map (\(u,v,w,x,_,_,_,_)->(u,v,w,x)) $ solutions 1e-2 $
[(t0a,t1a,t0b,t1b,0,1,0,1)::
(Double,Double,Double,Double,Double,Double,Double,Double)]
where
imp@(Matrix2 ap bp cp dp)=intervalize mp
imq@(Matrix2 aq bq cq dq)=intervalize mq
(Matrix2 ap_ bp_ cp_ dp_)=inverse imp
(Matrix2 aq_ bq_ cq_ dq_)=inverse imq
bxp=intervalize bxp_
byp=intervalize byp_
bxq=intervalize bxq_
byq=intervalize byq_
bxp4=promote 1 bxp
byp4=promote 1 byp
bxq4=promote 2 bxq
byq4=promote 2 byq
bxp'=derivate bxp
byp'=derivate byp
bxq'=derivate bxq
byq'=derivate byq
bXp'=promote 1 $ (scale ap_ bxp')+(scale bp_ byp')
bYp'=promote 1 $ (scale cp_ bxp')+(scale dp_ byp')
bXq'=promote 2 $ (scale aq_ bxq')+(scale bq_ byq')
bYq'=promote 2 $ (scale cq_ bxq')+(scale dq_ byq')
bomp@(Bernsteinp _ omegap)=(bXp'*bXp')+(bYp'*bYp') :: Bernsteinp (Int,Int,Int,Int) Interval
bomq@(Bernsteinp _ omegaq)=(bXq'*bXq')+(bYq'*bYq') :: Bernsteinp (Int,Int,Int,Int) Interval
au=
let au_=sqrt $ UV.minimum $ UV.map ilow omegap in
max 0 $ fpred au_
bu=
let bu_=sqrt $ UV.maximum $ UV.map iup omegap in
fsucc bu_
av=
let av_=sqrt $ UV.minimum $ UV.map ilow omegaq in
max 0 $ fpred av_
bv=
let bv_=sqrt $ UV.maximum $ UV.map iup omegaq in
fsucc bv_
alphau=Bernsteinp (1,1,2,1) $ UV.fromList [Interval au au,Interval bu bu]
alphav=Bernsteinp (1,1,1,2) $ UV.fromList [Interval av av,Interval bv bv]
eq0=
((bxp4*alphau*alphav) + (scale ap $ bYp'*alphav) - (scale bp $ bXp'*alphav)
-(bxq4*alphau*alphav) - (scale aq $ bYq'*alphau) + (scale bq $ bXq'*alphau))
eq1=
((byp4*alphau*alphav) + (scale cp $ bYp'*alphav) - (scale dp $ bXp'*alphav)
-(byq4*alphau*alphav) - (scale cq $ bYq'*alphau) + (scale dq $ bXq'*alphau))
eq2=bomp-(alphau*alphau)
eq3=bomq-(alphav*alphav)
inter b@(Circle{}) a@(Offset{})=
map (\(i,j,k,l)->(k,l,i,j)) $ inter a b
inter o@(Offset { cx=bxp, cy=byp, matrix=mp })
cir@(Circle{cx0,cy0,matrix=mq})=
let ix=intervalize bxp
iy=intervalize byp
m@(Matrix2 a b c d)=intervalize mp
(Matrix2 a_ b_ c_ d_)=inverse m
x'=derivate ix
y'=derivate iy
xx'=(scale a_ x')+(scale b_ y')
yy'=(scale c_ x')+(scale d_ y')
omega@(Bernsteinp _ omegap)=xx'*xx'+yy'*yy'
au=
let au_=sqrt $ UV.minimum $ UV.map ilow omegap in
max 0 $ fpred au_
bu=
let bu_=sqrt $ UV.maximum $ UV.map iup omegap in
fsucc bu_
alphau=Bernsteinp (1,2) $ UV.fromList [Interval au au,Interval bu bu]
lambda=(promote 1 omega) - alphau*alphau
xx0=(promote 1 $ ix-(intervalize $ constant cx0))*alphau
+(promote 1 $ scale a yy'-scale b xx')
yy0=(promote 1 $ iy-(intervalize $ constant cy0))*alphau
+(promote 1 $ scale c yy'-scale d xx') :: Bernsteinp (Int,Int) Interval
(Matrix2 ac_ bc_ cc_ dc_)=inverse $ intervalize mq
xx1=(scale ac_ xx0)+(scale bc_ yy0)
yy1=(scale cc_ xx0)+(scale dc_ yy0)
eqc=xx1*xx1+yy1*yy1-alphau*alphau
thrx=1e-5
solutions _ []=[]
solutions thr boxes@(_:_)=
let sol0=concatMap (solve thr (V.fromList [eqc,lambda])) boxes
(correct,toRefine)=partition (\(u,v,_,_)->
let (xu,yu)=evalCurve o (Interval u u)
(xv,yv)=evalCurve o (Interval v v)
in
(iup $ (xu-xv)^(2::Int)+(yu-yv)^(2::Int))<=thrx) sol0
in
correct++(solutions (thr/2) toRefine)
removeFalse cl0 (h@(_,v,_,_):h'@(u',_,_,_):s)=
let u''=(v+u')/2
(xu,yu)=evalCurve o (Interval u'' u'')
Interval dl du=distance xu yu cir
cl1
| du<1 = Dedans
| dl>1 = Dehors
| otherwise = SurLaLigne
in
if cl0/=cl1 then h:(removeFalse cl1 (h':s)) else
removeFalse cl1 (h':s)
removeFalse _ l=l
initCl=
let (x0,y0)=evalCurve o (Interval (t0 o) (t0 o))
Interval dl du=distance x0 y0 cir
in
if dl>1 then Dehors else if du<1 then Dedans else SurLaLigne
in
foldl (\l (u,v,_,_)->
let (Interval xl xu,Interval yl yu)=evalCurve o (Interval u v) in
case angle (Interval xl xu) (Interval yl yu) cir of
Just (Interval a0 a1)->
(u,v,a0,a1):l
Nothing->l
) [] $ removeFalse initCl $ sort $ solutions 1e-2 [(t0 o,t1 o,0::Double,1::Double)]
inter a@(Circle{cx0=x0a,cy0=y0a,matrix=ma})
b@(Circle{cx0=x0b,cy0=y0b,matrix=mb})=
if (intervalize ma)`intersects`(intervalize mb) && x0a==x0b && y0a==y0b then
let up ix@(Interval _ x_) tt0 tt1
| x_<tt0 =
up (ix+(2*interval pi)) tt0 tt1
| otherwise = down ix tt0 tt1
down ix@(Interval x_ x__) tt0 tt1
| x_>tt1 =
down (ix-(2*interval pi)) tt0 tt1
| x__<tt0 =
Nothing
| otherwise =
Just ix
alpha=up (interval $ t0 a) (t0 b) (t1 b)
beta=up (interval $ t0 b) (t0 b) (t1 b)
in
case (alpha,beta) of
(Just aa,Just ab)->
case (up aa (t0 a) (t1 a),
up ab (t0 a) (t1 a)) of
(Just ba,Just bb)
| ilow aa<=iup ab -> [(ilow ba, iup bb,
ilow aa, iup ab)]
| otherwise->
case (up (interval $ t0 b) (t0 a) (t1 a),
up (interval $ t1 b) (t0 a) (t1 a)) of
(Just b0,Just b1)->
[(ilow b0,iup bb,
t0 b, iup ab),
(ilow ba,iup b1,
ilow aa, t1 b)]
_->[]
_->[]
_->[]
else
let thr=1e-5
solutions=solve thr (V.fromList [eq0,eq1]) (fpred u0,fsucc v0,
fpred w0,fsucc x0)
in
foldl (\l (u,v,w,x)->
let alpha=angle (Interval u v) (Interval w x) a
beta=angle (Interval u v) (Interval w x) b
in
case alpha of
Just (Interval a0l a0u)->
case beta of
Just (Interval b0l b0u)->(a0l,a0u,b0l,b0u):l
_->l
_->l
) [] solutions
where
ima@(Matrix2 am bm cm dm)=intervalize ma
maxa=max (iup $ abs am+abs bm) (iup $ abs cm+abs dm)
(u0,v0,w0,x0)=(x0a-maxa,x0a+maxa,y0a-maxa,y0a+maxa)
xxa0=intervalize $ Bernsteinp (2,1) $ UV.fromList [-x0a,1-x0a] :: Bernsteinp (Int,Int) Interval
yya0=intervalize $ Bernsteinp (1,2) $ UV.fromList [-y0a,1-y0a] :: Bernsteinp (Int,Int) Interval
(Matrix2 aa_ ba_ ca_ da_)=inverse ima
xxa=(scale aa_ xxa0)+(scale ba_ yya0)::Bernsteinp (Int,Int) Interval
yya=(scale ca_ xxa0)+(scale da_ yya0)
xxb0=intervalize $ Bernsteinp (2,1) $ UV.fromList [-x0b,1-x0b]
yyb0=intervalize $ Bernsteinp (1,2) $ UV.fromList [-y0b,1-y0b]
(Matrix2 ab_ bb_ cb_ db_)=inverse $ intervalize mb
xxb=(scale ab_ xxb0)+(scale bb_ yyb0)
yyb=(scale cb_ xxb0)+(scale db_ yyb0)
c1=Bernsteinp (1,1) $ UV.singleton 1
eq0=xxa*xxa+yya*yya-c1
eq1=xxb*xxb+yyb*yyb-c1
inter op@(Bezier{cx=bxa,cy=bya,t0=t0a,t1=t1a}) (Bezier{cx=xb,cy=yb,t0=t0b,t1=t1b})=
let p0=(promote 1 $ intervalize bxa)-(promote 2 $ intervalize xb) :: Bernsteinp (Int,Int) Interval
p1=(promote 1 $ intervalize bya)-(promote 2 $ intervalize yb) :: Bernsteinp (Int,Int) Interval
thrx=1e-2
solutions _ []=[]
solutions thr boxes@(_:_)=
let sol0=concatMap (solve thr (V.fromList [p0,p1])) boxes
(correct,toRefine)=partition (\(u,v,_,_)->
let (xu,yu)=evalCurve op (Interval u u)
(xv,yv)=evalCurve op (Interval v v)
in
(iup $ (xu-xv)^(2::Int)+(yu-yv)^(2::Int))<=thrx) sol0
in
correct++(solutions (thr/2) toRefine)
in
solutions 1e-2 [(t0a,t1a,t0b,t1b)]
inter cir@(Circle{}) bez@(Bezier{})=map (\(u,v,w,x)->(w,x,u,v)) $ inter bez cir
inter bez@(Bezier{}) cir@(Circle{})=
let xx=(intervalize $ cx bez)-(intervalize $ constant $ cx0 cir)
yy=(intervalize $ cy bez)-(intervalize $ constant $ cy0 cir)
(Matrix2 a b c d)=inverse $ intervalize $ matrix cir
xx0=scale a xx+scale b yy
yy0=scale c xx+scale d yy
thrx=1e-5
solutions _ []=[]
solutions thr boxes@(_:_)=
let sol0=concatMap (solve thr (V.singleton (xx0*xx0+yy0*yy0-(constant 1)))) boxes
(correct,toRefine)=partition (\(u,v)->
let (xu,yu)=evalCurve bez (Interval u u)
(xv,yv)=evalCurve bez (Interval v v)
in
(iup $ (xu-xv)^(2::Int)+(yu-yv)^(2::Int))<=thrx) sol0
in
correct++(solutions (thr/2) toRefine)
in
foldl (\l (u,v)->
let (Interval xl xu,Interval yl yu)=evalCurve bez (Interval u v) in
case angle (Interval xl xu) (Interval yl yu) cir of
Just (Interval a0 a1)->
(u,v,a0,a1):l
Nothing->l
) [] $!
solutions (1e-2) [(t0 bez,t1 bez)]
inter bez@(Bezier{}) off@(Offset{})=map (\(u,v,w,x)->(w,x,u,v)) $ inter off bez
inter off@(Offset{}) bez@(Bezier{})=
let thr=1e-2
thrx=1e-5
solutions _ []=[]
solutions thr boxes@(_:_)=
let sol0=concatMap (solve thr (V.fromList [eq0,eq1,eq2])) boxes
(correct,toRefine)=partition (\(u,v,_,_,_,_)->
let (xu,yu)=evalCurve off (Interval u u)
(xv,yv)=evalCurve off (Interval v v)
in
(iup $ (xu-xv)^(2::Int)+(yu-yv)^(2::Int))<=thrx) sol0
in
correct++(solutions (thr/2) toRefine)
in
map (\(a,b,c,d,_,_)->(a,b,c,d)) $ solutions 1e-2 $
[(0,1,0,1,0,1)::(Double,Double,Double,Double,Double,Double)]
where
bxp=intervalize $ cx off
byp=intervalize $ cy off
bxq=intervalize $ cx bez
byq=intervalize $ cy bez
bxp'=derivate bxp
byp'=derivate byp
bxp3=promote 1 bxp
byp3=promote 1 byp
bxq3=promote 2 bxq
byq3=promote 2 byq
mp@(Matrix2 ap bp cp dp)=intervalize $ matrix $ off
(Matrix2 ap_ bp_ cp_ dp_)=inverse mp
bXp'=promote 1 $ (scale ap_ bxp')+(scale bp_ byp')
bYp'=promote 1 $ (scale cp_ bxp')+(scale dp_ byp')
omp@(Bernsteinp _ omegap)=(bXp'*bXp')+(bYp'*bYp')
au=
let au_=sqrt $ UV.minimum $ UV.map ilow omegap in
max 0 $ fpred au_
bu=
let bu_=sqrt $ UV.maximum $ UV.map iup omegap in
fsucc bu_
alphau=Bernsteinp (1,1,2) $ UV.fromList [Interval au au,Interval bu bu]
eq0=bxp3*alphau + (scale ap bYp') - (scale bp bXp') - bxq3
eq1=byp3*alphau + (scale cp bYp') - (scale dp bXp') - byq3
eq2=alphau*alphau-omp
angle::Interval->Interval->Curve->Maybe Interval
angle x y (Circle { cx0,cy0,matrix,t0,t1 })=
let vx=x-interval cx0
vy=y-interval cy0
Matrix2 a b c d=inverse $ intervalize matrix
alpha=
let co@(Interval col cou)=a*vx+b*vy
Interval sil siu=c*vx+d*vy
co2=
let (col2,cou2)=if col*col<cou*cou then (col*col,cou*cou) else
(cou*cou,col*col)
in
Interval (fpred col2) (fsucc cou2)
si2=
let (sil2,siu2)=if sil*sil<siu*siu then (sil*sil,siu*siu) else
(siu*siu,sil*sil)
in
Interval (fpred sil2) (fsucc siu2)
coco=co/(sqrt (co2+si2))
ac@(Interval acl acu)=acos $ Interval (max (-1) $ ilow coco) (min 1 $ iup coco)
in
if siu<0 then negate ac else
if sil>=0 then ac else
Interval (negate $ min (abs acl) (abs acu))
(max (abs acl) (abs acu))
up ix
| iup ix<t0 =
up $ ix+(2*interval pi)
| otherwise =
down ix
down ix
| ilow ix>t1 =
down $ ix-(2*interval pi)
| iup ix<t0 =
Nothing
| otherwise =
Just ix
in
up alpha
angle _ _ _=error "angle"
distance::Interval->Interval->Curve->Interval
distance x0 y0 (Bezier{..})=
distance x0 y0 (Offset{cx,cy,t0,t1,matrix=Matrix2 1 0 0 1})
distance x0 y0 (Offset{..})=
let (Matrix2 a b c d)=inverse $ intervalize matrix
vx_=intervalize cx-(constant x0)
vy_=intervalize cy-(constant y0)
vx=scale a vx_+scale b vy_
vy=scale c vx_+scale d vy_
dist=vx*vx+vy*vy
in
foldl (\di (u,v)->let di'=eval dist (Interval u v) in
if iup di<iup di' then di else di') (Interval (1/0) (1/0)) $
(t0,t0):(t1,t1):(solve 1e-5 (V.singleton (derivate dist)) (t0,t1))
distance x1 y1 (Circle{..})=
let (Matrix2 a b c d)=inverse $ intervalize matrix
vx_=x1-Interval cx0 cx0
vy_=y1-Interval cy0 cy0
vx=a*vx_+b*vy_
vy=c*vx_+d*vy_
in
vx*vx+vy*vy
offset::Matrix2 Double->Curve->[Curve]
offset m (Bezier{cx=x@(Bernsteinp nx bx),cy=y@(Bernsteinp ny by)})=
if nx <=1 && ny <=1 then
[Circle { cx0=UV.head bx,cy0=UV.head by,t0=ilow 0,t1=iup $ 2*pi,matrix=m }]
else
[ c0,c1,c2,c3 ]
where
im=intervalize m
(Matrix2 a_ b_ c_ d_)=inverse im
ibx=intervalize x
iby=intervalize y
lastCoef (Bernsteinp n c)
| n>=1 = UV.last c
| otherwise = 0
firstCoef (Bernsteinp n c)
| n>=1 = UV.head c
| otherwise = 0
c0=Offset { cx=x, cy=y, t0=0,t1=1,matrix=m }
ibx'=derivate ibx
iby'=derivate iby
alpha0=
let xx0=lastCoef ibx'
yy0=lastCoef iby'
xx0'=a_*xx0+b_*yy0
yy0'=c_*xx0+d_*yy0
norm0=sqrt $ xx0'*xx0'+yy0'*yy0'
xx'=xx0'/norm0
yy'=yy0'/norm0
in
if ilow xx'>=0 then
-(acos yy')
else
if iup xx'<=0 then
acos yy'
else
let Interval u v=acos yy' in
Interval (negate $ max (abs u) (abs v))
(max (abs u) (abs v))
alpha0'=alpha0+interval pi
c1=Circle { cx0=lastCoef x,
cy0=lastCoef y,
t0=ilow alpha0,
t1=iup alpha0',
matrix=m }
c2=Offset { cx=reorient x,
cy=reorient y,
t0=0,t1=1,
matrix=m }
alpha1=
let xx0=firstCoef ibx'
yy0=firstCoef iby'
xx0'=a_*xx0+b_*yy0
yy0'=c_*xx0+d_*yy0
norm0=sqrt $ xx0'*xx0'+yy0'*yy0'
xx'=xx0'/norm0
yy'=yy0'/norm0
in
if ilow xx'>=0 then
-(acos yy')
else
if iup xx'<=0 then
acos yy'
else
let Interval u v=acos yy' in
Interval (negate $ max (abs u) (abs v))
(max (abs u) (abs v))
alpha1'=alpha1-pi
c3=Circle { cx0=firstCoef x,
cy0=firstCoef y,
t0=ilow alpha1',
t1=iup alpha1,
matrix=m }
offset _ _=error "offset : undefined yet for other than Bezier"
rnd::Interval->Double
rnd (Interval a b)=(a+b)/2
derivRoots::Double->Curve->([(Double,Double)],[(Double,Double)])
derivRoots thr (Bezier{..})=
(solve thr (V.singleton $ derivate $ intervalize cx) (t0,t1),
solve thr (V.singleton $ derivate $ intervalize cy) (t0,t1))
derivRoots thr (Offset{..})=
let ix=intervalize cx
iy=intervalize cy
x'=derivate ix
y'=derivate iy
m@(Matrix2 a b c d)=intervalize matrix
(Matrix2 a_ b_ c_ d_)=inverse m
xx'=(scale a_ x')+(scale b_ y')
yy'=(scale c_ x')+(scale d_ y')
xx''=derivate xx'
yy''=derivate yy'
omega=xx'*xx'+yy'*yy'
au=
let au_=sqrt $ UV.minimum $ UV.map ilow $ coefs omega in
max 0 $ fpred au_
bu=
let bu_=sqrt $ UV.maximum $ UV.map iup $ coefs omega in
fsucc bu_
alphau=Bernsteinp (1,2) $ UV.fromList [Interval au au,Interval bu bu]
eqx0=(promote 1 yy'')*(alphau^(2::Int))-(promote 1 $ yy'*yy''+xx'*xx'')
eqy0=(promote 1 $ yy'*yy''+xx'*xx'')-(promote 1 xx'')*(alphau^(2::Int))
eqx=(promote 1 x')*(alphau^(3::Int))+(scale a eqx0)+(scale b eqy0)
:: Bernsteinp (Int,Int) Interval
eqy=(promote 1 y')*(alphau^(3::Int))+(scale c eqx0)+(scale d eqy0)
eq=(promote 1 omega)-alphau^(2::Int) :: Bernsteinp (Int,Int) Interval
in
(map (\(u,v,_,_)->(u,v)) $ solve thr (V.fromList [eqx,eq])
((t0,t1,0,1)::(Double,Double,Double,Double)),
map (\(u,v,_,_)->(u,v)) $ solve thr (V.fromList [eqy,eq])
((t0,t1,0,1)::(Double,Double,Double,Double)))
derivRoots _ (Circle{..})=
let (Matrix2 a b c d)=intervalize matrix
aa=sqrt $ a*a+b*b
cc=sqrt $ c*c+d*d
sx
| ilow a>=0 = acos $ b/aa
| otherwise = negate $ acos $ b/aa
sy
| ilow c>=0 = acos $ d/cc
| otherwise = negate $ acos $ d/cc
Interval ux vx=(-sx)-pi/2
Interval uy vy=(-sy)-pi/2
in
([(ux,vx)],[(uy,vy)])
left::Curve->(Double,Double)
left cur=
let (x,y)=
foldl (\m@(xx,_) (s,t)->
let m'@(xx',_)=evalCurve cur $ interval $ (s+t)/2 in
if ilow xx<ilow xx' then m else m') (1/0,1/0) $
(t0 cur,t0 cur):(t1 cur,t1 cur):(fst $ derivRoots 1e-5 cur)
in
(rnd x,rnd y)
bottom::Curve->(Double,Double)
bottom cur=
let (x,y)=
foldl (\m@(_,yy) (s,t)->
let m'@(_,yy')=evalCurve cur $ interval $ (s+t)/2 in
if ilow yy<ilow yy' then m else m') (1/0,1/0) $
(t0 cur,t0 cur):(t1 cur,t1 cur):(snd $ derivRoots 1e-5 cur)
in
(rnd x,rnd y)
right::Curve->(Double,Double)
right cur=
let (x,y)=
foldl (\m@(xx,_) (s,t)->
let m'@(xx',_)=evalCurve cur $ interval $ (s+t)/2 in
if iup xx>iup xx' then m else m') (-1/0,-1/0) $
(t0 cur,t0 cur):(t1 cur,t1 cur):(fst $ derivRoots 1e-5 cur)
in
(rnd x,rnd y)
top::Curve->(Double,Double)
top cur=
let (x,y)=
foldl (\m@(_,yy) (s,t)->
let m'@(_,yy')=evalCurve cur $ interval $ (s+t)/2 in
if iup yy>iup yy' then m else m') (-1/0,-1/0) $
(t0 cur,t0 cur):(t1 cur,t1 cur):(snd $ derivRoots 1e-5 cur)
in
(rnd x,rnd y)
\end{code}