-
Notifications
You must be signed in to change notification settings - Fork 62
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Projections - non-affine transformations #148
Conversation
Here are some examples, followed by the code. They show:
import Diagrams.Prelude
import Diagrams.TwoD.Project
import Diagrams.Project
import Diagrams.Backend.SVG
ptMark :: Diagram SVG R2
ptMark = circle 0.02 # lw 0
illustrateSegment :: FixedSegment R2 -> Diagram SVG R2
illustrateSegment (FLinear from to) = position [
(from, ptMark # fc blue),
(to, ptMark # fc blue)]
illustrateSegment (FCubic from c1 c2 to) = position [
(c1, ptMark # fc red),
(c2, ptMark # fc red)] <> illustrateSegment (FLinear from to)
illustratePath t =
stroke t
<> (mconcat . map illustrateSegment . concatMap fixTrail . pathTrails $ t)
sq :: Path R2
sq = unitSquare # translate (5 ^& 3)
shaft = arc 0 (1/8 @@ turn)
curvedArrow = arrowBetween' (with & arrowShaft .~ shaft
& shaftStyle %~ lc gray
& headStyle %~ fc gray
)
dashedLine :: P2 -> P2 -> Diagram SVG R2
dashedLine from to = fromVertices [from, to] # dashing [0.1, 0.1] 0
illustrateProjection :: Projection R2 -> Path R2 -> ([P2], [P2], Diagram SVG R2)
illustrateProjection t s = (basePts, projectedPts, projectedMarks) where
basePts = concat $ pathVertices sq
projectedPts = map (project t) basePts
projectedMarks = position $ zip projectedPts (repeat (ptMark # fc green))
x0 = mconcat $ [illustratePath sq, projectedMarks]
++ zipWith curvedArrow basePts projectedPts
++ zipWith dashedLine basePts projectedPts
where
(basePts, projectedPts, projectedMarks) = illustrateProjection parallelX0 sq
x1 = mconcat $ [illustratePath sq, projectedMarks]
++ zipWith curvedArrow basePts projectedPts
++ zipWith dashedLine basePts (repeat origin)
where
(basePts, projectedPts, projectedMarks) = illustrateProjection perspectiveX1 sq
y0Rotated = mconcat $ [illustratePath sq, projectedMarks]
++ zipWith curvedArrow basePts projectedPts
where
parallelY0' = asProjection (rotation (-1/4 @@ turn)) <> parallelX0 <> asProjection (rotation (1/4 @@ turn))
(basePts, projectedPts, projectedMarks) = illustrateProjection parallelY0' sq
skewSq = mconcat $ [stroke s, stroke (t s) # lc green]
++ zipWith dashedLine facing final
++ zipWith dashedLine (repeat origin) final where
s = unitSquare # translate (1 ^& 0)
t = project' 0.000001 facingX
basePts = concat . pathVertices $ s
facing = map (project facingX) basePts
final = map (project perspectiveX1) basePts
skewCircle = mconcat [stroke c, stroke (project' 0.01 facingX c) # lc green] where
c = unitCircle # translate (2 ^& 0)
d = [x0, x1, y0Rotated, skewSq, skewCircle]
main = do
renderSVG "projections.svg" (Dims 500 (300*(realToFrac $ length d))) .
vcat' (with & sep .~ 0.5) $ d |
I think representing more general things is great. Since we have to do approximations anyway, it seems there's nothing particularly to be gained by restricting to actual projective transforms (though I could be wrong).
|
I think including more general things is good. The main downside is that it's not clear (to me) what deformations are actually feasible. Because we sample at a few points and approximate, we'll stop the subdivision too soon on functions with small wiggles. But I'm fine crossing that bridge when we come to it, and we can probably use denser or more clever sampling if necessary in the future. In that case, we should probably rename
I'm leaning towards the |
What, you don't like |
what about simply On Sat, Feb 8, 2014 at 4:13 PM, Brent Yorgey notifications@github.comwrote:
|
What would be the noun form? i.e. ( |
@jeffreyrosenbluth Haskell programmers will never forgive me if I define |
Revert "Handle 'project' name collision" This reverts commit 4b1aca9.
Conflicts: diagrams-lib.cabal
I think this is ready to merge now, along with diagrams/diagrams-core#50 |
Looks good to me. If possible I'd like to have a patch to the user manual explaining deformations get merged at the same time. |
Sounds good. I'll try to write something in the next couple of days. |
Conflicts: src/Diagrams/Combinators.hs
Projections - non-affine transformations
This is a proposal for non-affine transformations, which I've provisionally called Projections. It depends on diagrams/diagrams-core#50
Before this is ready to merge, we should choose a better name for applying a Projection. The obvious choice
project
conflicts withData.VectorSpace.project
. A couple of thoughts; I hope someone has better ideas:Should this new type represent only projective transforms, or something more general? Either is fine with me, but I'd like to make it more clear in the docs. I originally set out to provide projective transforms, per #108. The current implementation is more general. The
Projection
type supports any spatial map, though small wiggles will probably be missed in the segment subdivision / approximation.The answer to that might help inform the function name, and also whether it's semantically sensible to use
Data.LinearMap
insideProjection
. I usedLinearMap
in an earlier version, and I'm happy to put it back in.The use-cases I have in mind are illustrations of perspective, and quick-and-dirty 3D wireframes by transforming
Path
s in 3D, transforming to 2D, and using the 2D Backends. The latter requires 3D Paths and #117