mirror of
https://gitlab.com/sheaf/metabrush.git
synced 2024-11-27 17:34:08 +00:00
use the correct tangent vector for stroke joins
This commit is contained in:
parent
3916fe2656
commit
d4561ad549
14
app/Main.hs
14
app/Main.hs
|
@ -102,7 +102,7 @@ testDocuments = IntMap.fromList
|
||||||
{ displayName = "Document 1"
|
{ displayName = "Document 1"
|
||||||
, filePath = Nothing
|
, filePath = Nothing
|
||||||
, unsavedChanges = False
|
, unsavedChanges = False
|
||||||
, strokes = [ Stroke ( circle ( PointData Normal ( razor $ BrushPointData Normal ) ) ) "Circle" True ( unsafeUnique 0 )
|
, strokes = [ Stroke ( circle ( PointData Normal ( rect $ BrushPointData Normal ) ) ) "Circle" True ( unsafeUnique 0 )
|
||||||
]
|
]
|
||||||
, bounds = AABB ( Point2D 0 0 ) ( Point2D 100 100 )
|
, bounds = AABB ( Point2D 0 0 ) ( Point2D 100 100 )
|
||||||
, viewportCenter = Point2D 50 50
|
, viewportCenter = Point2D 50 50
|
||||||
|
@ -157,6 +157,18 @@ razor d = Seq.fromList
|
||||||
pp p = PathPoint p d
|
pp p = PathPoint p d
|
||||||
cp p = ControlPoint p d
|
cp p = ControlPoint p d
|
||||||
|
|
||||||
|
rect :: forall a. a -> Seq ( StrokePoint a )
|
||||||
|
rect d = Seq.fromList
|
||||||
|
[ pp ( Point2D 20 5 )
|
||||||
|
, pp ( Point2D 20 -5 )
|
||||||
|
, pp ( Point2D -20 -5 )
|
||||||
|
, pp ( Point2D -20 5 )
|
||||||
|
, pp ( Point2D 20 5 )
|
||||||
|
]
|
||||||
|
where
|
||||||
|
pp :: Point2D Double -> StrokePoint a
|
||||||
|
pp p = PathPoint p d
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
main :: IO ()
|
main :: IO ()
|
||||||
|
|
|
@ -137,7 +137,7 @@ stroke allPts@( spt0 :<| spt1 :<| spts )
|
||||||
_ -> False
|
_ -> False
|
||||||
|
|
||||||
fwd, bwd :: Seq ( StrokePoint () )
|
fwd, bwd :: Seq ( StrokePoint () )
|
||||||
( fwd, bwd ) = go tgt_start spt0 ( spt1 :<| spts )
|
( fwd, bwd ) = go spt0 ( spt1 :<| spts )
|
||||||
|
|
||||||
(<~>)
|
(<~>)
|
||||||
:: ( Monoid a, Monoid b )
|
:: ( Monoid a, Monoid b )
|
||||||
|
@ -149,6 +149,7 @@ stroke allPts@( spt0 :<| spt1 :<| spts )
|
||||||
-- Connecting paths at a point of discontinuity of the tangent vector direction (G1 discontinuity).
|
-- Connecting paths at a point of discontinuity of the tangent vector direction (G1 discontinuity).
|
||||||
-- This happens at corners of the brush path (including endpoints of an open brush path, where the tangent flips direction).
|
-- This happens at corners of the brush path (including endpoints of an open brush path, where the tangent flips direction).
|
||||||
joinAndContinue :: Vector2D Double -> StrokePoint d -> Seq ( StrokePoint d ) -> ( Seq ( StrokePoint () ), Seq ( StrokePoint () ) )
|
joinAndContinue :: Vector2D Double -> StrokePoint d -> Seq ( StrokePoint d ) -> ( Seq ( StrokePoint () ), Seq ( StrokePoint () ) )
|
||||||
|
--joinAndContinue tgt sp sps = go sp sps
|
||||||
joinAndContinue _ _ Empty
|
joinAndContinue _ _ Empty
|
||||||
-- Closed curve.
|
-- Closed curve.
|
||||||
| isClosed
|
| isClosed
|
||||||
|
@ -164,52 +165,52 @@ stroke allPts@( spt0 :<| spt1 :<| spts )
|
||||||
)
|
)
|
||||||
joinAndContinue tgt sp0 ( sp1 :<| sps )
|
joinAndContinue tgt sp0 ( sp1 :<| sps )
|
||||||
| tgt' `parallel` tgt
|
| tgt' `parallel` tgt
|
||||||
= go tgt sp0 ( sp1 :<| sps )
|
= go sp0 ( sp1 :<| sps )
|
||||||
| let
|
| let
|
||||||
ptOffset :: Vector2D Double
|
ptOffset :: Vector2D Double
|
||||||
ptOffset = Point2D 0 0 --> coords sp0
|
ptOffset = Point2D 0 0 --> coords sp0
|
||||||
= ( ptOffset • joinWithBrush ( withTangent tgt brush0 ) ( withTangent tgt' brush0 ) brush0
|
= ( ptOffset • joinWithBrush ( withTangent tgt brush0 ) ( withTangent tgt' brush0 ) brush0
|
||||||
, ptOffset • joinWithBrush ( withTangent ( (-1) *^ tgt' ) brush0 ) ( withTangent ( (-1) *^ tgt ) brush0 ) brush0
|
, ptOffset • joinWithBrush ( withTangent ( (-1) *^ tgt' ) brush0 ) ( withTangent ( (-1) *^ tgt ) brush0 ) brush0
|
||||||
)
|
)
|
||||||
<~> go tgt sp0 ( sp1 :<| sps )
|
<~> go sp0 ( sp1 :<| sps )
|
||||||
where
|
where
|
||||||
tgt' :: Vector2D Double
|
tgt' :: Vector2D Double
|
||||||
tgt' = coords sp0 --> coords sp1
|
tgt' = coords sp0 --> coords sp1
|
||||||
brush0 :: Seq ( StrokePoint () )
|
brush0 :: Seq ( StrokePoint () )
|
||||||
brush0 = removePointData $ brushShape @x sp0
|
brush0 = removePointData $ brushShape @x sp0
|
||||||
|
|
||||||
go :: Vector2D Double -> StrokePoint d -> Seq ( StrokePoint d ) -> ( Seq ( StrokePoint () ), Seq ( StrokePoint () ) )
|
go :: StrokePoint d -> Seq ( StrokePoint d ) -> ( Seq ( StrokePoint () ), Seq ( StrokePoint () ) )
|
||||||
go _ _ Empty = ( Empty, Empty )
|
go _ Empty = ( Empty, Empty )
|
||||||
-- Line.
|
-- Line.
|
||||||
go tgt0 sp0 ( sp1 :<| sps )
|
go sp0 ( sp1 :<| sps )
|
||||||
| PathPoint {} <- sp1
|
| PathPoint {} <- sp1
|
||||||
, let
|
, let
|
||||||
p0, p1, fop0, fop1, bop0, bop1 :: Point2D Double
|
p0, p1, fop0, fop1, bop0, bop1 :: Point2D Double
|
||||||
p0 = coords sp0
|
p0 = coords sp0
|
||||||
p1 = coords sp1
|
p1 = coords sp1
|
||||||
fop0 = offset ( withTangent tgt0 ( brushShape @x sp0 ) ) • p0
|
fop0 = offset ( withTangent tgt ( brushShape @x sp0 ) ) • p0
|
||||||
fop1 = offset ( withTangent tgt0 ( brushShape @x sp1 ) ) • p1
|
fop1 = offset ( withTangent tgt ( brushShape @x sp1 ) ) • p1
|
||||||
bop0 = offset ( withTangent ( (-1) *^ tgt0 ) ( brushShape @x sp0 ) ) • p0
|
bop0 = offset ( withTangent ( (-1) *^ tgt ) ( brushShape @x sp0 ) ) • p0
|
||||||
bop1 = offset ( withTangent ( (-1) *^ tgt0 ) ( brushShape @x sp1 ) ) • p1
|
bop1 = offset ( withTangent ( (-1) *^ tgt ) ( brushShape @x sp1 ) ) • p1
|
||||||
tgt1 :: Vector2D Double
|
tgt :: Vector2D Double
|
||||||
tgt1 = p0 --> p1
|
tgt = p0 --> p1
|
||||||
brush :: Double -> Seq ( StrokePoint () )
|
brush :: Double -> Seq ( StrokePoint () )
|
||||||
brush t = lerpBrush t ( brushShape @x sp0 ) ( brushShape @x sp1 )
|
brush t = lerpBrush t ( brushShape @x sp0 ) ( brushShape @x sp1 )
|
||||||
fwdPts, bwdPts :: [ Point2D Double ]
|
fwdPts, bwdPts :: [ Point2D Double ]
|
||||||
fwdPts
|
fwdPts
|
||||||
= [ ( offset $ withTangent tgt0 $ brush t )
|
= [ ( offset $ withTangent tgt $ brush t )
|
||||||
• ( lerp @( Vector2D Double ) t p0 p1 )
|
• ( lerp @( Vector2D Double ) t p0 p1 )
|
||||||
| t <- [0.1,0.2..0.9]
|
| t <- [0.1,0.2..0.9]
|
||||||
]
|
]
|
||||||
bwdPts
|
bwdPts
|
||||||
= [ ( offset $ withTangent ( (-1) *^ tgt0 ) $ brush t ) •
|
= [ ( offset $ withTangent ( (-1) *^ tgt ) $ brush t ) •
|
||||||
( lerp @( Vector2D Double ) t p0 p1 )
|
( lerp @( Vector2D Double ) t p0 p1 )
|
||||||
| t <- [0.9,0.8..0.1]
|
| t <- [0.9,0.8..0.1]
|
||||||
]
|
]
|
||||||
= ( fitCurve fop0 tgt0 fwdPts fop1 tgt0, fitCurve bop1 ( (-1) *^ tgt1 ) bwdPts bop0 ( (-1) *^ tgt0 ) )
|
= ( fitCurve fop0 tgt fwdPts fop1 tgt, fitCurve bop1 ( (-1) *^ tgt ) bwdPts bop0 ( (-1) *^ tgt ) )
|
||||||
<~> joinAndContinue tgt1 sp1 sps
|
<~> joinAndContinue tgt sp1 sps
|
||||||
-- Quadratic Bézier curve.
|
-- Quadratic Bézier curve.
|
||||||
go tgt0 sp0 ( sp1 :<| sp2 :<| sps )
|
go sp0 ( sp1 :<| sp2 :<| sps )
|
||||||
| ControlPoint {} <- sp1
|
| ControlPoint {} <- sp1
|
||||||
, PathPoint {} <- sp2
|
, PathPoint {} <- sp2
|
||||||
, let
|
, let
|
||||||
|
@ -221,7 +222,8 @@ stroke allPts@( spt0 :<| spt1 :<| spts )
|
||||||
fop2 = offset ( withTangent tgt2 ( brushShape @x sp2 ) ) • p2
|
fop2 = offset ( withTangent tgt2 ( brushShape @x sp2 ) ) • p2
|
||||||
bop0 = offset ( withTangent ( (-1) *^ tgt0 ) ( brushShape @x sp0 ) ) • p0
|
bop0 = offset ( withTangent ( (-1) *^ tgt0 ) ( brushShape @x sp0 ) ) • p0
|
||||||
bop2 = offset ( withTangent ( (-1) *^ tgt2 ) ( brushShape @x sp2 ) ) • p2
|
bop2 = offset ( withTangent ( (-1) *^ tgt2 ) ( brushShape @x sp2 ) ) • p2
|
||||||
tgt2 :: Vector2D Double
|
tgt0, tgt2 :: Vector2D Double
|
||||||
|
tgt0 = p0 --> p1
|
||||||
tgt2 = p1 --> p2
|
tgt2 = p1 --> p2
|
||||||
bez :: Quadratic.Bezier ( Point2D Double )
|
bez :: Quadratic.Bezier ( Point2D Double )
|
||||||
bez = Quadratic.Bezier { .. }
|
bez = Quadratic.Bezier { .. }
|
||||||
|
@ -242,7 +244,7 @@ stroke allPts@( spt0 :<| spt1 :<| spts )
|
||||||
= ( fitCurve fop0 tgt0 fwdPts fop2 tgt2, fitCurve bop2 ( (-1) *^ tgt2 ) bwdPts bop0 ( (-1) *^ tgt0 ) )
|
= ( fitCurve fop0 tgt0 fwdPts fop2 tgt2, fitCurve bop2 ( (-1) *^ tgt2 ) bwdPts bop0 ( (-1) *^ tgt0 ) )
|
||||||
<~> joinAndContinue tgt2 sp2 sps
|
<~> joinAndContinue tgt2 sp2 sps
|
||||||
-- Cubic Bézier curve.
|
-- Cubic Bézier curve.
|
||||||
go tgt0 sp0 ( sp1 :<| sp2 :<| sp3 :<| sps )
|
go sp0 ( sp1 :<| sp2 :<| sp3 :<| sps )
|
||||||
| ControlPoint {} <- sp1
|
| ControlPoint {} <- sp1
|
||||||
, ControlPoint {} <- sp2
|
, ControlPoint {} <- sp2
|
||||||
, PathPoint {} <- sp3
|
, PathPoint {} <- sp3
|
||||||
|
@ -256,7 +258,8 @@ stroke allPts@( spt0 :<| spt1 :<| spts )
|
||||||
fop3 = offset ( withTangent tgt3 ( brushShape @x sp3 ) ) • p3
|
fop3 = offset ( withTangent tgt3 ( brushShape @x sp3 ) ) • p3
|
||||||
bop0 = offset ( withTangent ( (-1) *^ tgt0 ) ( brushShape @x sp0 ) ) • p0
|
bop0 = offset ( withTangent ( (-1) *^ tgt0 ) ( brushShape @x sp0 ) ) • p0
|
||||||
bop3 = offset ( withTangent ( (-1) *^ tgt3 ) ( brushShape @x sp3 ) ) • p3
|
bop3 = offset ( withTangent ( (-1) *^ tgt3 ) ( brushShape @x sp3 ) ) • p3
|
||||||
tgt3 :: Vector2D Double
|
tgt0, tgt3 :: Vector2D Double
|
||||||
|
tgt0 = p0 --> p1
|
||||||
tgt3 = p2 --> p3
|
tgt3 = p2 --> p3
|
||||||
bez :: Cubic.Bezier ( Point2D Double )
|
bez :: Cubic.Bezier ( Point2D Double )
|
||||||
bez = Cubic.Bezier { .. }
|
bez = Cubic.Bezier { .. }
|
||||||
|
@ -276,7 +279,7 @@ stroke allPts@( spt0 :<| spt1 :<| spts )
|
||||||
]
|
]
|
||||||
= ( fitCurve fop0 tgt0 fwdPts fop3 tgt3, fitCurve bop3 ( (-1) *^ tgt3 ) bwdPts bop0 ( (-1) *^ tgt0 ) )
|
= ( fitCurve fop0 tgt0 fwdPts fop3 tgt3, fitCurve bop3 ( (-1) *^ tgt3 ) bwdPts bop0 ( (-1) *^ tgt0 ) )
|
||||||
<~> joinAndContinue tgt3 sp3 sps
|
<~> joinAndContinue tgt3 sp3 sps
|
||||||
go _ p0 ps = error $ "stroke: unrecognised stroke type\n" <> show ( p0 :<| ps )
|
go p0 ps = error $ "stroke: unrecognised stroke type\n" <> show ( p0 :<| ps )
|
||||||
|
|
||||||
-----------------------------------
|
-----------------------------------
|
||||||
-- Various utility functions
|
-- Various utility functions
|
||||||
|
|
Loading…
Reference in a new issue