-
-
Notifications
You must be signed in to change notification settings - Fork 141
/
GetBox2.hs
125 lines (96 loc) · 3.19 KB
/
GetBox2.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
-- Implicit CAD. Copyright (C) 2011, Christopher Olah (chris@colah.ca)
-- Released under the GNU GPL, see LICENSE
{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances, FlexibleContexts, TypeSynonymInstances, UndecidableInstances #-}
module Graphics.Implicit.ObjectUtil.GetBox2 (getBox2, getDist2) where
import Graphics.Implicit.Definitions
import Data.VectorSpace
isEmpty :: Box2 -> Bool
isEmpty = (== ((0,0), (0,0)))
pointsBox :: [ℝ2] -> Box2
pointsBox points =
let
(xs, ys) = unzip points
in
((minimum xs, minimum ys), (maximum xs, maximum ys))
unionBoxes :: [Box2] -> Box2
unionBoxes boxes =
let
(leftbot, topright) = unzip $ filter (not.isEmpty) boxes
(lefts, bots) = unzip leftbot
(rights, tops) = unzip topright
in
((minimum lefts, minimum bots), (maximum rights, maximum tops))
outsetBox :: ℝ -> Box2 -> Box2
outsetBox r (a,b) =
(a ^-^ (r,r), b ^+^ (r,r))
getBox2 :: SymbolicObj2 -> Box2
-- Primitives
getBox2 (RectR _ a b) = (a,b)
getBox2 (Circle r ) = ((-r, -r), (r,r))
getBox2 (PolygonR _ points) = ((minimum xs, minimum ys), (maximum xs, maximum ys))
where (xs, ys) = unzip points
-- (Rounded) CSG
getBox2 (Complement2 _) =
((-infty, -infty), (infty, infty)) where infty = 1/0
getBox2 (UnionR2 r symbObjs) =
outsetBox r $ unionBoxes (map getBox2 symbObjs)
getBox2 (DifferenceR2 _ symbObjs) =
let
firstBox:_ = map getBox2 symbObjs
in
firstBox
getBox2 (IntersectR2 r symbObjs) =
let
boxes = map getBox2 symbObjs
(leftbot, topright) = unzip boxes
(lefts, bots) = unzip leftbot
(rights, tops) = unzip topright
left = maximum lefts
bot = maximum bots
right = minimum rights
top = minimum tops
in
((left-r,bot-r),(right+r,top+r))
-- Simple transforms
getBox2 (Translate2 v symbObj) =
let
(a,b) = getBox2 symbObj
in
if isEmpty (a,b)
then ((0,0),(0,0))
else (a^+^v, b^+^v)
getBox2 (Scale2 s symbObj) =
let
(a,b) = getBox2 symbObj
in
(s ⋯* a, s ⋯* b)
getBox2 (Rotate2 θ symbObj) =
let
((x1,y1), (x2,y2)) = getBox2 symbObj
rotate (x,y) = (cos(θ)*x - sin(θ)*y, sin(θ)*x + cos(θ)*y)
in
pointsBox [ rotate (x1, y1)
, rotate (x1, y2)
, rotate (x2, y1)
, rotate (x2, y2)
]
-- Boundary mods
getBox2 (Shell2 w symbObj) =
outsetBox (w/2) $ getBox2 symbObj
getBox2 (Outset2 d symbObj) =
outsetBox d $ getBox2 symbObj
-- Misc
getBox2 (EmbedBoxedObj2 (_,box)) = box
-- Get the maximum distance (read upper bound) an object is from a point.
-- Sort of a circular
getDist2 :: ℝ2 -> SymbolicObj2 -> ℝ
getDist2 p (UnionR2 r objs) = r + maximum [getDist2 p obj | obj <- objs ]
getDist2 p (Translate2 v obj) = getDist2 (p ^+^ v) obj
getDist2 p (Circle r) = magnitude p + r
getDist2 p (PolygonR r points) =
r + maximum [magnitude (p ^-^ p') | p' <- points]
getDist2 (x,y) symbObj =
let
((x1,y1), (x2,y2)) = getBox2 symbObj
in
sqrt ((max (abs (x1 - x)) (abs (x2 - x)))**2 + (max (abs (y1 - y)) (abs (y2 - y)))**2)