Skip to content

Commit

Permalink
Adding Box Frame as a primitive.
Browse files Browse the repository at this point in the history
Adding a box frame primitive, and associated test.
  • Loading branch information
lepsa committed Dec 29, 2023
1 parent 5128285 commit b69275c
Show file tree
Hide file tree
Showing 8 changed files with 57 additions and 8 deletions.
5 changes: 4 additions & 1 deletion Graphics/Implicit/Canon.hs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ import Graphics.Implicit.Definitions
, RotateExtrude
, Shared3
, Sphere
, Transform3
, Transform3, BoxFrame
)
, hasZeroComponent
)
Expand Down Expand Up @@ -171,6 +171,7 @@ fmapObj3
fmapObj3 f _ _ (Cube v) = f $ Cube v
fmapObj3 f _ _ (Sphere r) = f $ Sphere r
fmapObj3 f _ _ (Cylinder r1 r2 h) = f $ Cylinder r1 r2 h
fmapObj3 f _ _ (BoxFrame b e) = f $ BoxFrame b e
fmapObj3 f g s (Rotate3 q o) = f $ Rotate3 q (fmapObj3 f g s o)
fmapObj3 f g s (Transform3 m o) = f $ Transform3 m (fmapObj3 f g s o)
fmapObj3 f g s (Extrude o2 h) = f $ Extrude (fmapObj2 g f s o2) h
Expand Down Expand Up @@ -226,6 +227,7 @@ instance EqObj SymbolicObj3 where
Cube a =^= Cube b = a == b
Sphere a =^= Sphere b = a == b
Cylinder r1a r2a ha =^= Cylinder r1b r2b hb = r1a == r1b && r2a == r2b && ha == hb
BoxFrame b1 e1 =^= BoxFrame b2 e2 = b1 == b2 && e1 == e2
Rotate3 x a =^= Rotate3 y b = x == y && a =^= b
Transform3 x a =^= Transform3 y b = x == y && a =^= b
Extrude a x =^= Extrude b y = x == y && a =^= b
Expand Down Expand Up @@ -299,6 +301,7 @@ canon3 :: SymbolicObj3 -> SymbolicObj3
canon3 (Cube v) | hasZeroComponent v = emptySpace
canon3 (Sphere 0) = emptySpace
canon3 (Cylinder 0 _ _) = emptySpace
canon3 (BoxFrame _ 0) = emptySpace
canon3 (Extrude _o2 0) = emptySpace
canon3 (Rotate3 0 o) = o
canon3 (RotateExtrude 0 _t _r _o) = emptySpace
Expand Down
3 changes: 3 additions & 0 deletions Graphics/Implicit/Definitions.hs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ module Graphics.Implicit.Definitions (
Cylinder,
Rotate3,
Transform3,
BoxFrame,
Extrude,
ExtrudeM,
ExtrudeOnEdgeOf,
Expand Down Expand Up @@ -324,6 +325,7 @@ data SymbolicObj3 =
Cube ℝ3 -- rounding, size.
| Sphere -- radius
| Cylinder --
| BoxFrame ℝ3 -- b e from https://iquilezles.org/articles/distfunctions/
-- Simple transforms
| Rotate3 (Quaternion ) SymbolicObj3
| Transform3 (M44 ) SymbolicObj3
Expand Down Expand Up @@ -351,6 +353,7 @@ instance Show SymbolicObj3 where
-- centered.
Cube sz -> showCon "cube" @| False @| sz
Sphere d -> showCon "sphere" @| d
BoxFrame b e -> showCon "boxFrame" @| b @| e
-- NB: The arguments to 'Cylinder' are backwards compared to 'cylinder' and
-- 'cylinder2'.
Cylinder h r1 r2 | r1 == r2 ->
Expand Down
2 changes: 1 addition & 1 deletion Graphics/Implicit/Export/RayTrace.hs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
-- Copyright 2016, Julia Longtin ([email protected])
-- Released under the GNU AGPLV3+, see LICENSE

module Graphics.Implicit.Export.RayTrace( Color(Color), average, Camera(Camera), Light(Light), Scene(Scene), traceRay, cameraRay) where
module Graphics.Implicit.Export.RayTrace( Color(Color), average, Camera(Camera), Light(Light), Scene(Scene), traceRay, cameraRay, vectorDistance) where

import Prelude(Show, RealFrac, Maybe(Just, Nothing), Bool(False, True), (-), (.), ($), (*), (/), min, fromInteger, max, round, fromIntegral, unzip, fmap, length, sum, maximum, minimum, (>), (+), (<), (==), pred, flip, not, abs, floor, toRational, otherwise, pure)

Expand Down
6 changes: 5 additions & 1 deletion Graphics/Implicit/Export/SymbolicFormats.hs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ module Graphics.Implicit.Export.SymbolicFormats (scad2, scad3) where

import Prelude((.), fmap, Either(Left, Right), ($), (*), ($!), (-), (/), pi, error, (+), (==), take, floor, (&&), const, pure, (<>), sequenceA, (<$>))

import Graphics.Implicit.Definitions(, SymbolicObj2(Shared2, Square, Circle, Polygon, Rotate2, Transform2), SymbolicObj3(Shared3, Cube, Sphere, Cylinder, Rotate3, Transform3, Extrude, ExtrudeM, RotateExtrude, ExtrudeOnEdgeOf), isScaleID, SharedObj(Empty, Full, Complement, UnionR, IntersectR, DifferenceR, Translate, Scale, Mirror, Outset, Shell, EmbedBoxedObj, WithRounding), quaternionToEuler)
import Graphics.Implicit.Definitions(, SymbolicObj2(Shared2, Square, Circle, Polygon, Rotate2, Transform2), SymbolicObj3(Shared3, Cube, Sphere, Cylinder, BoxFrame, Rotate3, Transform3, Extrude, ExtrudeM, RotateExtrude, ExtrudeOnEdgeOf), isScaleID, SharedObj(Empty, Full, Complement, UnionR, IntersectR, DifferenceR, Translate, Scale, Mirror, Outset, Shell, EmbedBoxedObj, WithRounding), quaternionToEuler)
import Graphics.Implicit.Export.TextBuilderUtils(Text, Builder, toLazyText, fromLazyText, bf)

import Control.Monad.Reader (Reader, runReader, ask)
Expand Down Expand Up @@ -127,6 +127,10 @@ buildS3 (Cube (V3 w d h)) = call "cube" [bf w, bf d, bf h] []

buildS3 (Sphere r) = callNaked "sphere" ["r = " <> bf r] []

buildS3 (BoxFrame (V3 w d h) e) = callNaked "boxFrame"
["w = " <> bf w, "d = " <> bf d, "h = " <> bf h, "e = " <> bf e]
[]

buildS3 (Cylinder h r1 r2) = callNaked "cylinder" [
"r1 = " <> bf r1
,"r2 = " <> bf r2
Expand Down
3 changes: 2 additions & 1 deletion Graphics/Implicit/ObjectUtil/GetBox3.hs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import Graphics.Implicit.Definitions
( Fastℕ,
fromFastℕ,
ExtrudeMScale(C2, C1),
SymbolicObj3(Shared3, Cube, Sphere, Cylinder, Rotate3, Transform3, Extrude, ExtrudeOnEdgeOf, ExtrudeM, RotateExtrude),
SymbolicObj3(Shared3, Cube, Sphere, Cylinder, Rotate3, Transform3, Extrude, ExtrudeOnEdgeOf, ExtrudeM, RotateExtrude, BoxFrame),
Box3,
,
fromFastℕtoℝ,
Expand All @@ -34,6 +34,7 @@ getBox3 (Shared3 obj) = getBoxShared obj
getBox3 (Cube size) = (pure 0, size)
getBox3 (Sphere r) = (pure (-r), pure r)
getBox3 (Cylinder h r1 r2) = (V3 (-r) (-r) 0, V3 r r h ) where r = max r1 r2
getBox3 (BoxFrame b _) = (-b, b)
-- (Rounded) CSG
-- Simple transforms
getBox3 (Rotate3 q symbObj) =
Expand Down
32 changes: 30 additions & 2 deletions Graphics/Implicit/ObjectUtil/GetImplicit3.hs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,20 @@

module Graphics.Implicit.ObjectUtil.GetImplicit3 (getImplicit3) where

import Prelude (id, (||), (/=), either, round, fromInteger, Either(Left, Right), abs, (-), (/), (*), sqrt, (+), atan2, max, cos, minimum, ($), sin, pi, (.), Bool(True, False), ceiling, floor, pure, (==), otherwise)
import Prelude (id, (||), (/=), either, round, fromInteger, Either(Left, Right), abs, (-), (/), (*), sqrt, (+), atan2, max, cos, minimum, ($), sin, pi, (.), Bool(True, False), ceiling, floor, pure, (==), otherwise, min)

import Graphics.Implicit.Definitions
( objectRounding, ObjectContext, , SymbolicObj3(Cube, Sphere, Cylinder, Rotate3, Transform3, Extrude, ExtrudeM, ExtrudeOnEdgeOf, RotateExtrude, Shared3), Obj3, ℝ2, , fromℕtoℝ, toScaleFn )
( objectRounding,
ObjectContext,
,
SymbolicObj3(Cube, Sphere, Cylinder, Rotate3, Transform3, Extrude,
ExtrudeM, ExtrudeOnEdgeOf, RotateExtrude, Shared3, BoxFrame),
Obj3,
ℝ2,
,
fromℕtoℝ,
toScaleFn,
ℝ3 )

import Graphics.Implicit.MathUtil ( rmax, rmaximum )

Expand Down Expand Up @@ -37,6 +47,24 @@ getImplicit3 _ (Cylinder h r1 r2) = \(V3 x y z) ->
θ = atan2 (r2-r1) h
in
max (d * cos θ) (abs (z-h/2) - (h/2))
getImplicit3 _ (BoxFrame b e) = \p' ->
let p@(V3 px py pz) = abs p' - b
V3 qx qy qz = abs (p + pure e) - pure e
-- Splitting out bits from https://iquilezles.org/articles/distfunctions/
-- to make it somewhat readable.
length :: ℝ3 ->
length v = Linear.distance (abs v) $ pure 0
-- Component wise maximum. This is what the opengl language is doing, so we need
-- it for the function as defined by the blog above.
-- See "Maximum" http://15462.courses.cs.cmu.edu/fall2019/article/20
compMax :: ℝ3 -> ℝ3 -> ℝ3
compMax (V3 a1 b1 c1) (V3 a2 b2 c2) = V3 (max a1 a2) (max b1 b2) (max c1 c2)
-- These names don't mean anything, and are just for splitting up the code.
x', y', z' ::
x' = length (compMax (V3 px qy qz) (pure 0)) + min (max px (max qy qz)) 0
y' = length (compMax (V3 qx py qz) (pure 0)) + min (max qx (max py qz)) 0
z' = length (compMax (V3 qx qy pz) (pure 0)) + min (max qx (max qy pz)) 0
in min (min x' y') z'
-- Simple transforms
getImplicit3 ctx (Rotate3 q symbObj) =
getImplicit3 ctx symbObj . Linear.rotate (Linear.conjugate q)
Expand Down
6 changes: 5 additions & 1 deletion Graphics/Implicit/Primitives.hs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ module Graphics.Implicit.Primitives (
withRounding,
_Shared,
pattern Shared,
Object(Space, canonicalize)) where
Object(Space, canonicalize), boxFrame) where

import Prelude(Applicative, Eq, Foldable, Num, abs, (<), otherwise, Num, (+), (-), (*), (/), (.), negate, Bool(True, False), Maybe(Just, Nothing), Either, fmap, ($), (**), sqrt, (<=), (&&), max, Ord)

Expand Down Expand Up @@ -84,6 +84,7 @@ import Graphics.Implicit.Definitions (ObjectContext, ℝ, ℝ2, ℝ3, Box2,
Cube,
Sphere,
Cylinder,
BoxFrame,
Rotate3,
Transform3,
Extrude,
Expand Down Expand Up @@ -140,6 +141,9 @@ cylinder ::
-> SymbolicObj3 -- ^ Resulting cylinder
cylinder r = cylinder2 r r

boxFrame :: ℝ3 -> -> SymbolicObj3
boxFrame = BoxFrame

cone ::
-- ^ Radius of the cylinder
-> -- ^ Height of the cylinder
Expand Down
8 changes: 7 additions & 1 deletion tests/GoldenSpec/Spec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Graphics.Implicit
import Graphics.Implicit.Export.OutputFormat (OutputFormat (PNG))
import Prelude
import Test.Hspec ( describe, Spec )
import Graphics.Implicit.Primitives (torus, ellipsoid, cone)
import Graphics.Implicit.Primitives (torus, ellipsoid, cone, boxFrame)

default (Int)

Expand Down Expand Up @@ -172,6 +172,12 @@ spec = describe "golden tests" $ do
, ellipsoid 10 15 20
, translate (V3 0 0 25) $ cone 20 20
]

golden "boxFrame" 2 $
union
[ boxFrame (V3 20 20 20) 2
, translate (V3 0 0 10) $ boxFrame (V3 10 10 10) 2
]

golden "closing-paths-1" 0.5 $
extrudeM
Expand Down

0 comments on commit b69275c

Please sign in to comment.