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

added clipTo #144

Merged
merged 11 commits into from
Jan 23, 2014
Merged

added clipTo #144

merged 11 commits into from
Jan 23, 2014

Conversation

jeffreyrosenbluth
Copy link
Member

No description provided.

@jeffreyrosenbluth
Copy link
Member Author

Despite Travis' complaints I think this can be merged

@bergey
Copy link
Member

bergey commented Jan 1, 2014

Does the combined Trace yield intersections that lie outside the clipping path? I think it does, including for rays that don't intersect the clipped Diagram at all. I can put together some tests later, if this question isn't clear.

I'm OK merging this anyway, if we can't do better right now. I think the right solution requires explicitly (or implicitly) calculating the intersection Path. (Which I think @fryguybob wants to do.) I've been running into the same issue in 3D.

@jeffreyrosenbluth
Copy link
Member Author

I think it does as well, but I'm not sure. I was not sure what we should do with trace? The use case where I needed clipTo was for "cutting out" a triangle from a diagram made of dots and then using snug on this triangle. In this case I need the trace to be the trace of the Path (triangle) so this implementation doesn't do what I need, but neither would the one you propose. I wind up with ugly code like this:

mkTriangle :: Dia -> Dia
mkTriangle = withTrace (triangle 1 :: Dia) . clipTo (triangle 1 :: Path R2)

Perhaps we should have yet another function say clipped that sets both the envelope and trace to those of the clipping Path? Alternatively, maybe we should just set the envelope for now and leave the trace alone?

@bergey
Copy link
Member

bergey commented Jan 1, 2014

That's an interesting use case. I think I would try to (ab)use alignBy' with a custom boundary function, rather than 'snug'.

My intuition of Trace is that for an intersection of Paths A & B, it should find points which are on the Trace of A inside B, or on the Trace of B inside A. Do you have a different understanding of Trace, or do you just need a way to align your Diagram?

@fryguybob
Copy link
Member

I think there is value to a clipped as well. Then we can have clipping where we keep the original path's envelope and trace, a clipping where we limit to the parts of the original path that are inside the clip path (using the clip path itself when it is interior to the original path), and a clipping where we take the clip path's envelope and trace. We can also take both the path and the clip path, though I can't come up with a compelling use off hand.

@jeffreyrosenbluth
Copy link
Member Author

I agree with @bergey's intuition of Trace. I think this is consistent with the current implementation of clipTo for points inside the clip path, I think this is what @fryguybob alluded to - do you agree? If so perhaps it's not necessary to calculate the intersection path, we can just test to see if points are outside of the clip path and if so use the trace of the clip path instead.

I'll add a clipped function and if I'm not missing something (re above), I can attempt to reimplement clipTo

@bergey
Copy link
Member

bergey commented Jan 1, 2014

OK, adding clipped sounds good.

I now think you're right, that we can find the Trace of the intersection without finding the intersection path, assuming we have a function (Query?) that tells us if a point is inside a path.

@jeffreyrosenbluth
Copy link
Member Author

I think i can use combination of traceP and maxTraceP to do the query. I just need to think through the case where the Path is not a loop?

@jeffreyrosenbluth
Copy link
Member Author

Unfortunately, I think I have to recant. Due to the way we implement Trace (in particular, allowing negative multiples of the ray) the semigroup instance is equivalent to the trace of the union not the intersection of paths. I think what this means is that @bergey is right after all, and we need to calculate the intersection of the paths and then take it's trace. Unless of course I'm misunderstanding the trace semigroup.

@bergey
Copy link
Member

bergey commented Jan 2, 2014

You're right about the Semigroup instance. I was about to write a better explanation of how I think we can calculate the intersection trace, but I wrote the code instead. I haven't tested it yet, though! @jeffreyrosenbluth, if you have time to test this, that would be great; I'm not sure when I'll get to it.

@jeffreyrosenbluth
Copy link
Member Author

@bergey - I should have time to test it tomorrow.

@jeffreyrosenbluth
Copy link
Member Author

Unfortunately, the program hangs. Here is my test code:

{-# LANGUAGE NoMonomorphismRestriction #-}

import           Diagrams.Prelude
import           Diagrams.Backend.SVG.CmdLine

clipPath :: Path R2
clipPath = square 2 # alignR

loopyStar :: Diagram B R2
loopyStar = mconcat
          . map (cubicSpline True)
          . pathVertices
          . star (StarSkip 3)
          $ regPoly 7 1

clippedStar :: Diagram B R2
clippedStar = clipTo clipPath (loopyStar # fc lightgray)

example :: Diagram B R2
example = position (zip pts dots)
       <> clippedStar
       <> loopyStar

pts :: [P2]
pts = [ (-1) ^& 0.9, (-0.65) ^& 0.65, (-0.25) ^& 0.65, (-0.25) ^& 0.4
      , (-0.1) ^& 0.9, 0.1 ^& 0.9, 0.25 ^& 0.4, 0.25 ^& 0.65
      , 0.65 ^& 0.65, 1 ^& 0.9 ]

vecs :: [R2]
vecs = [unitX, unitY, unit_X, unit_Y]

tracePt :: P2 -> [Double]
tracePt p = map (maybe 0 magnitude) vs
  where
    vs = (traceV p) <$> vecs <*> [clippedStar]

traces :: [[Double]]
traces = map tracePt pts

dots :: [Diagram B R2]
dots = repeat (circle 0.015 # fc red # lw 0)

main = do
  putStr $ unlines $ map show traces
  mainWith $ example # centerXY # pad 1.1

@bergey
Copy link
Member

bergey commented Jan 18, 2014

Diagram showing traces of intersection after my latest push. The code tests the trace in 4 cardinal directions, but only draws an arrow if there is an intersection.

@bergey
Copy link
Member

bergey commented Jan 19, 2014

Here's a snug example. It looks as I expect.

snugCircle :: Diagram B R2
snugCircle = snugR $ dot <> circle 1 <> arrowAt origin unitX

snugExample :: Diagram B R2
snugExample = snugCircle <> snugL clippedStar

@jeffreyrosenbluth
Copy link
Member Author

Great, thanks

@jeffreyrosenbluth
Copy link
Member Author

Ready to merge

bergey added a commit that referenced this pull request Jan 23, 2014
add several clipping functions which set Envelope and Trace
@bergey bergey merged commit aab3d99 into master Jan 23, 2014
@jeffreyrosenbluth jeffreyrosenbluth deleted the clipTo branch February 11, 2014 19:25
@bergey bergey mentioned this pull request Feb 13, 2014
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.

4 participants