#lang scheme
(require "../../common/main.ss")
(provide (all-from-out "../../common/main.ss")
(all-from-out "acad-utils.ss")
start-backend
(rename-out [draw-top-level draw])
com-stats
opt-stats
turn-off-caching
turn-off-translation-opt)
(require "../../utils.ss")
(require "acad-utils.ss"
"operations.ss"
"primitives.ss"
"com-utils.ss")
(require "base.ss")
(require "marshal.ss")
(define tag list)
(define tagged-object first)
(define tagged-tag second)
(define cache #f)
(define (clean-cache)
(hash-for-each cache
(lambda (key val)
(with-handlers
((exn:fail?
(lambda (_) #t)))
(invoke Delete
val))))
(set! cache #f))
(define make-hash* make-hash)
(define hash-ref* hash-ref)
(define hash-set!* hash-set!)
(define copy-entity* copy-entity)
(define (turn-off-caching)
(let ([f (lambda args #f)])
(set! make-hash* f)
(set! clean-cache f)
(set! hash-ref* f)
(set! copy-entity* (lambda args (first args)))
(set! hash-set!* f)))
(define (draw-top-level object)
(set! cache (make-hash*))
(let ([res (draw object)])
(clean-cache)
res))
(define (draw object)
(let ([obj (hash-ref* cache object #f)])
(if obj
(set! obj (copy-entity* obj))
(begin
(set! obj (tagged-object (draw* object)))
(unless (primitive? object)
(hash-set!* cache
object
(copy-entity* obj)))))
(tag obj object)))
(define (draw* object)
(case* object
[primitive? => draw-primitive]
[csg? => apply-csg]
[operation? => apply-operation]
[else (error 'draw
"Don't know how to draw objects of type ~a: ~a [~a]"
(vector-ref (struct->vector object) 0)
object (struct->vector object))]))
(define (draw-primitive primitive)
(assert (primitive? primitive))
(case* primitive
[circle? => draw-circle]
[box? => draw-box]
[cone? => draw-cone]
[cylinder? => draw-cylinder]
[loft? => draw-loft]
[sphere? => draw-sphere] [text? => draw-text] [torus? => draw-torus]
[wedge? => draw-wedge]
[else (error "Don't know how to draw primitives of type "
(vector-ref (struct->vector primitive) 0))]))
(define-syntax define-prim-bridge
(syntax-rules ()
[(_ name prim arg prop ...)
(define (name arg)
(tag (prim (prop arg)
...)
arg))]))
(define (draw-circle circle)
(tag (vector-ref
(prim:region
(vector (prim:circle (circle-center circle)
(circle-radius circle))))
0)
circle))
(define (draw-box box)
(tag (prim:box (box-center box)
(box-length box)
(box-width box)
(box-height box))
box))
(define (draw-cone cone)
(tag (prim:cone (cone-center cone)
(cone-base-radius cone)
(cone-cap cone))
cone))
(define (draw-cylinder cylinder)
(tag (prim:cylinder (cylinder-center cylinder)
(cylinder-radius cylinder)
(cylinder-height cylinder))
cylinder))
(define-prim-bridge draw-sphere
prim:sphere sphere
sphere-center sphere-radius)
(define (draw-loft loft)
(let* ([f (loft-f loft)]
[start (loft-start loft)]
[step (loft-step loft)]
[stop? (loft-stop? loft)]
[surfs (unfold stop? f step start)]
[drawn-surfs (map (compose tagged-object draw) surfs)])
(apply prim:command* "._loft"
(append drawn-surfs
(list "" "")))
(tag (entlast)
loft)))
(define-prim-bridge draw-text
prim:text text
text-string text-lower-left text-height)
(define-prim-bridge draw-torus
prim:torus torus
torus-center torus-radius torus-tube-radius)
(define-prim-bridge draw-wedge
prim:wedge wedge
wedge-center wedge-length wedge-width wedge-height)
(define (apply-csg csg)
(assert (csg? csg))
(case* csg
[union? => apply-union]
[intersection? => apply-intersection]
[subtraction? => apply-subtraction]
[else (error "CSG ("
(vector-ref (struct->vector csg) 0)
") not implemented")]))
(define ac-union 0)
(define ac-intersection 1)
(define ac-subtraction 2)
(require "com-utils.ss")
(define aaa #f)
(define fx (lambda (o1 o2)
(invoke Boolean
(tagged-object o1)
ac-union
(tagged-object o2))
(tag (tagged-object o1) aaa)))
(define (apply-union union)
(set! aaa union)
(let* ([o (first (union-objects union))]
[objs (rest (union-objects union))]
[o* (draw o)]
[objs* (map draw objs)])
(foldl fx
o* objs*)))
(define ac-extend-none 0) (define ac-extend-this-entity 1) (define ac-extend-other-entity 2) (define ac-extend-both 3)
(define (apply-intersection intersection)
(let ([o (first (intersection-objects intersection))]
[objs (rest (intersection-objects intersection))])
(foldl (lambda (o1 o2)
(invoke IntersectWith (tagged-object o1) (tagged-object o2) ac-extend-none)
(tag (tagged-object o1) intersection))
(draw o)
(map draw objs))))
(define (apply-subtraction subtraction)
(let ([o (subtraction-main-object subtraction)]
[objs (subtraction-objects subtraction)])
(foldl (lambda (o2 o1)
(invoke Boolean (tagged-object o1) ac-subtraction (tagged-object o2))
(tag (tagged-object o1) subtraction))
(draw o)
(map draw objs))))
(define (apply-operation operation)
(assert (operation? operation))
(case* operation
[rotation? => apply-rotation]
[translation? => apply-translation]
[scale? => apply-scale]
[transform? => apply-transform]
[else (error "Operation ("
(vector-ref (struct->vector operation) 0)
") not implemented")]))
(define (apply-rotation rotation)
(let ([adder (case (rotation-coordinate rotation)
[(x) +x]
[(y) +y]
[(z) +z]
[else (error "Unknown coordinate: "
(rotation-coordinate rotation))])]
[obj (draw (rotation-object rotation))])
(prim:rotate3d (tagged-object obj)
origin
(adder origin 1)
(rotation-angle rotation))
(tag (tagged-object obj)
rotation)))
(define optimize-translation #t)
(define (turn-off-translation-opt)
(set! optimize-translation #f))
(define opts 0)
(define (opt-stats)
(display* opts " translation optimizations"))
(define (apply-translation translation)
(if (and optimize-translation (cylinder? (translation-object translation)))
(draw (let ([cyl (translation-object translation)])
(set! opts (add1 opts))
(make-cylinder ((case (translation-coordinate translation)
[(x) +x]
[(y) +y]
[(z) +z]
[else (error "Unknown coordinate: "
(translation-coordinate translation))])
(cylinder-center cyl) (translation-magnitude translation))
(cylinder-radius cyl)
(cylinder-height cyl))))
(let ([adder (case (translation-coordinate translation)
[(x) +x]
[(y) +y]
[(z) +z]
[else (error "Unknown coordinate: "
(translation-coordinate translation))])]
[obj (draw (translation-object translation))])
(prim:move (tagged-object obj)
origin
(adder origin (translation-magnitude translation)))
(tag (tagged-object obj)
translation))))
(define (apply-scale scale)
(error 'apply-scale))
(define (apply-transform transform)
(error 'apply-transform))