--- /dev/null
+(define-module (dungeon-master geom)
+ #:use-module (dungeon-master geom point)
+ #:export (angle-sign))
+
+
+(define (angle-sign center a b)
+ "Return the sign of (- (atan (- a center))
+ (atan (- b center)))"
+ (let ((x1 (- (point-x a) (point-x center)))
+ (y1 (- (point-y a) (point-y center)))
+ (x2 (- (point-x b) (point-x center)))
+ (y2 (- (point-y b) (point-y center))))
+ (cond ((and (>= x1 0) (< x2 0))
+ 1)
+ ((and (>= x2 0) (< x1 0))
+ -1)
+ ((and (= x1 0) (= x2 0))
+ (if (> y2 y1) 1 -1))
+ (else
+ (if (> (- (* x2 y1) (* x1 y2)) 0) 1 -1)))))
(define-module (dungeon-master geom voronoi)
#:use-module (ice-9 receive)
+ #:use-module (rnrs sorting)
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-9)
+ #:use-module (dungeon-master geom)
#:use-module (dungeon-master geom point)
#:use-module (dungeon-master geom triangle)
#:use-module (dungeon-master geom bowyer-watson)
;;; Voronoi mesh region
(define-record-type <voronoi-region>
- (make-voronoi-region seed vertices)
+ (make-raw-voronoi-region seed vertices)
voronoi-region?
(seed voronoi-region-seed)
(vertices voronoi-region-vertices))
+(define (make-voronoi-region seed vertices)
+ (define (compare-angles triangle1 triangle2)
+ (let ((c1 (triangle-center triangle1))
+ (c2 (triangle-center triangle2)))
+ (> (angle-sign seed c1 c2) 0)))
+ (make-raw-voronoi-region seed (list-sort compare-angles vertices)))
;;; Voronoi mesh
(regions voronoi-mesh-regions))
(define* (make-voronoi-mesh vertices #:optional (relax-steps 3))
- ; Delaunay triangulation
+ ;; Delaunay triangulation
(receive (triangles points frame)
(bowyer-watson vertices)
(make-raw-voronoi-mesh
frame
(make-regions points triangles))))
+(define (partitioning voronoi)
+ (define (is-real-triangle triangle)
+ ;; real triangle points cannot be frame points
+ (let ((frame (voronoi-mesh-frame voronoi)))
+ (let check-points ((points (triangle-points triangle)))
+ (cond ((null? points)
+ #t) ; triangle is real
+ (else
+ (and (not (member (car points) frame))
+ (check-points (cdr points))))))))
+
+ (define (is-real-region region)
+ ;; real region points cannot be frame points
+ (let check-vertices ((vertices (voronoi-region-vertices region)))
+ (cond ((null? vertices)
+ #t) ; region is real
+ (else
+ (and (is-real-triangle (car vertices))
+ (check-vertices (cdr vertices)))))))
+
+ (let* ((points (voronoi-mesh-points voronoi))
+ (regions (voronoi-mesh-regions voronoi))
+ ;; we need the regions in the same order as points are
+ (ordered-regions
+ (map-in-order
+ (lambda (p)
+ (assoc-ref regions p))
+ points))
+ ;; only real regions without frame points
+ (filtered-regions
+ (filter (lambda (r) (is-real-region r))
+ ordered-regions)))
+ filtered-regions))
+
(define* (voronoi-mesh-relax voronoi #:optional (to-relax '()))
- voronoi)
-
-(define* (make-regions points triangles #:optional (regions '()))
- (cond ((null? points)
- regions)
- (else
- (let* ((p (car points))
- (vertices (filter
- (lambda (tr) (member p (triangle-points tr)))
- triangles))
- (region (make-voronoi-region p vertices)))
- (make-regions (cdr points)
- triangles
- (alist-cons p region regions))))))
+ (let ((regions (partitioning voronoi)))
+ voronoi))
+
+(define (make-regions points triangles)
+ (map-in-order
+ (lambda (p)
+ (let ((vertices
+ (filter
+ (lambda (tr) (member p (triangle-points tr)))
+ triangles)))
+ (cons p (make-voronoi-region p vertices))))
+ points))