Skip to content
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 #229

Merged
merged 23 commits into from
Feb 28, 2015
Merged

Projections #229

merged 23 commits into from
Feb 28, 2015

Conversation

cchalmers
Copy link
Member

Not ready.

Just a start at projections of path-like things. I'm still working things out and open to suggestions.

  • Added LinearMappable class
  • Added AffineMappable class
  • Added Matrix functions
  • Add common orthographic projection functions
  • Add projections from Cameras
  • Perspective projections using Deformable

@bergey
Copy link
Member

bergey commented Nov 24, 2014

Thank you for adding the matrix-to-Transformation code. That's been a weird omission.

Camera and Deformable look the way we do because we didn't have any matrix code, and I didn't want to add a linear dependency just for them. Now that we have linear, and you're working on this, maybe we should change those. I'd be fine ditching Deformable in favor of representing projections with homogeneous transformation matrices. Camera is essentially the same thing, and recent versions of linear have lookAt and similar functions.

Do you think vmap = fmap would be easier to read, in the cases where it's true? I think defining some instances that way would make it more obvious which instances aren't also Functor.

@cchalmers
Copy link
Member Author

I've been thinking about how to do projective transforms. Ideally we would use rational Bézier curves, which are closed under projective transforms and have lots of other nice properties. But it looks like a lot of work.

For now I was going to use Deformable and use homogeneous matrices to make the Deformation. I'll try to get something done soon.

I don't think I can use vmap in place of fmap. fmap's usually just on n.

@bergey
Copy link
Member

bergey commented Nov 24, 2014

Yeah, I wrote some NURBs code. Not as fun as I expected, and since then the folks who wrote the book on NURBs have come out against NURBS. =) I think rational curves have much less to recommend them in 2D than in 3D, since we already have a good story about continuity, and we want to output integral Bezier curves. (With 3D, there's the option to pass rational Bezier surfaces to a geometry shader on the GPU, and approximate by segments / triangles there.)

Unfortunately, the recursive subdivision I implemented for Deformation is very bad. If you know of a good algorithm, I'd be happy to implement it.

Ah yes, still waiting for higher order functors =)

@cchalmers
Copy link
Member Author

Ah OK. I saw some things about approximating rational Béziers with normal ones which should be a lot better than the current Deformable. So maybe we could rationals as an intermediate. But I don't know much about it. :)

@bergey
Copy link
Member

bergey commented Nov 24, 2014

Sounds good. (Except the part about you not knowing everything.) Let me know how I can help.

@cchalmers
Copy link
Member Author

I've tried to make a start at projections. The orthographic ones seems OKish but I struggling with perspective projections (never used homogenous coordinates before). Could you take a look @bergey?

There's a house path for you to play with :)

house

@bergey
Copy link
Member

bergey commented Nov 30, 2014

I think you want something like

m44Deformation :: M44 Double -> Deformation V3 V2 Double
m44Deformation m =
    Deformation (P . view _xy . normalizePoint . (m !*) . point . view _Point)

point and normalizePoint are from Linear.V4. I haven't tested this yet, though.

@cchalmers
Copy link
Member Author

Ah yeah, that looks better, thanks. Thought I tried _xy but obviously not :)

perspective

I'll get things cleaned up and it should be ready soonish.

@cchalmers
Copy link
Member Author

I've had a little look at rational approximation and found a couple of papers:

http://link.springer.com/article/10.1007%2FBF02936562
http://arxiv.org/pdf/1212.3385.pdf

but I haven't looked at them properly. Maybe one of us could look at this later to replace Deformation for perspective projections.

I'll leave cameras for now. For me they feel like a backend thing. Maybe we can deal with it when we get more 3D backends.

Even thought this PR isn't particularly useful on it's own it's a start. I think this is ready to merge.

facingXY = lookingAt unitX origin zDir

facingXZ :: (Epsilon n, Floating n) => AffineMap V3 V2 n
facingXZ = lookingAt unitY origin yDir
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain the naming convention here? Also, up and forward shouldn't be the same direction.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My idea was to have projections for facing the xy, xz, and yz planes in the "natural" way. Looking at them now they're clearly wrong :)

@bergey
Copy link
Member

bergey commented Dec 15, 2014

I'm sorry it's taken me so long to respond to this. I definitely want to merge the matrix -> Transformation code, and some way of getting from V3 to V2. We should add functions to multiply LinearMap and AffineMap on the left and right with a matching Transformation. Ie, it should be possible to construct them without going through matrices.

It feels a bit heavy-weight to me, adding two types and the associated type classes & combinators, when AffineMap V3 V2 n is no larger than (T2 n, T3 n) and isn't large enough to include perspective transforms. Do you think it's useful to make this many type-level distinctions?

I know, usually I'm the one trying to add more types. One argument in favor is that the implementation is simpler for AffineMap than for Deformable, since a Segment is always mapped to only one Segment. And therefore more types are AffineMapable than Deformable.

@cchalmers
Copy link
Member Author

I see where you're coming from. There's no real need for the LinearMap type. The problem with using transformations for linear maps is we have to worry about whether the transform is invertible when coming from a matrix.

The nice thing about splitting it into affine and linear maps is we can change the number type with the linear map and the affine map class follows nicely. But I'm open to any simpler solutions.

@bergey
Copy link
Member

bergey commented Dec 20, 2014

That's a good point about the matrix conversion. I wouldn't expect anyone to want a non-invertible matrix, but that leaves users writing a Nothing case that will never occur. And having a way to change the n is certainly useful; I was only thinking about changing v.

The only simpler solution I've come up with is like this (please excuse my poor naming):

reduceV :: (Coordinates vn, Decomposition vn ~ (u n :& n)) => vn -> u n
reduceV (coords -> u :& _) = u

class ReduceDim t where
    reduce :: (Coordinates (v n), Decomposition (v n) ~ (u n :& n)) => t v n -> t u n

instance ReduceDim Point where
    reduce (P v) = P $ reduceV v

I'm undecided about what usage pattern is most readable. What do you think?

-- this PR
dia2 = amap facingXY . transform t $ dia3
-- this PR plus new combinator
dia2 = amap (facingXY `amapTimesTr` t) dia3
-- ReduceDim
dia2 = reduce . transform t $ dia3

@cchalmers
Copy link
Member Author

Just having reduce means we'd lose some functionally, like promoting planar paths to V3.

In terms of readable patterns, I don't expect most users to use this class directly. It's meant as a tool for other things like a Diagram V3 -> Diagram V2 backend. So the user would give a camera or Euler angle or something.

@bergey
Copy link
Member

bergey commented Dec 23, 2014

Sounds good. Once you fix up the facingFoo definitions, I'm happy to merge this.

3D attributes haven't been changed yet. This requires changes to the povray backend.
Now _Attribute is an Iso and _attribute is a lens onto the attribute in a style.
They're just added noise, you never really use them because you need to know the types. We can always add them later.
There's no need to use the maybe value, transparent it equivilent to no
fill.

This reverts commit 731f181.
@cchalmers
Copy link
Member Author

Sorry it took so long to make the small fixes, I'll merge this too after travis builds.

cchalmers added a commit that referenced this pull request Feb 28, 2015
@cchalmers cchalmers merged commit 68bc53c into master Feb 28, 2015
@cchalmers cchalmers deleted the projections branch February 28, 2015 13:24
@bergey
Copy link
Member

bergey commented Feb 28, 2015

Great. I was worried that the ball was in my court, and I'd forgotten.

@cchalmers
Copy link
Member Author

Nah, I was just busy on doc and forgot about it. Speaking of which there's diagrams/diagrams-doc#79 if you're looking for something to do :)

If not I'll get back to it eventually. I just got a little bored and needed a break from it.

@bergey
Copy link
Member

bergey commented Feb 28, 2015

I won't get to it this weekend, but likely later this week.

@cchalmers
Copy link
Member Author

Great, thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants