(module yasos-points (point? make-point-cartesian make-point-polar x y rho theta translate! scale! rotate! distance) (import scheme (chicken base) (chicken format) (except yasos object object-with-ancestors operate-as)) (define-predicate point?) (define-operation (x obj)) (define-operation (y obj)) (define-operation (rho obj)) (define-operation (theta obj)) (define-operation (translate! obj dx dy)) (define-operation (scale! obj factor)) (define-operation (rotate! obj angle)) (define-operation (distance obj other)) ;; internal (define pi (acos -1)) (define (normalize theta) (/ (remainder (floor (round (* 10E12 theta))) (floor (round (* 20E12 pi)))) 10E12)) (define (r2 x) ; round to precision 2 (/ (round (* x 100)) 100)) (define (point-maker %x %y %rho %theta) (operations () ((point? self) #t) ((size self) 2) ((show self . optional-arg) (if (null? optional-arg) (show self #t) (format (car optional-arg) "#,(point x: ~s y: ~s rho: ~s theta: ~s)~%" (r2 %x) (r2 %y) (r2 %rho) (r2 %theta)))) ((x self) %x) ((y self) %y) ((rho self) %rho) ((theta self) %theta) ((distance self other) (let ((dx (- %x (x other))) (dy (- %y (y other)))) (sqrt (+ (* dx dx) (* dy dy))))) ((translate! self dx dy) (set! %x (+ %x dx)) (set! %y (+ %y dy)) (set! %rho (sqrt (+ (* %x %x) (* %y %y)))) (set! %theta (atan %y %x))) ((scale! self factor) (set! %rho (* %rho factor)) (set! %x (* %rho (cos %theta))) (set! %y (* %rho (sin %theta)))) ((rotate! self angle) (set! %theta (normalize (+ %theta angle))) (set! %x (* %rho (cos %theta))) (set! %y (* %rho (sin %theta)))) )) (define (make-point-cartesian x y) (point-maker x y (sqrt (+ (* x x) (* y y))) (atan y x))) (define (make-point-polar rho theta) (point-maker (* rho (cos theta)) (* rho (sin theta)) rho (normalize theta))) ) ; points