1 (define-module (dungeon-master geom voronoi)
2 #:use-module (ice-9 receive)
3 #:use-module (rnrs sorting)
4 #:use-module (srfi srfi-1)
5 #:use-module (srfi srfi-9)
6 #:use-module (dungeon-master geom)
7 #:use-module (dungeon-master geom point)
8 #:use-module (dungeon-master geom triangle)
9 #:use-module (dungeon-master geom bowyer-watson)
10 #:export (make-voronoi-mesh
12 voronoi-mesh-triangles
18 "https://github.com/watabou/TownGeneratorOS/blob/master/Source/com/watabou/geom/Voronoi.hx"
20 ;;; Voronoi mesh region
22 (define-record-type <voronoi-region>
23 (make-raw-voronoi-region seed vertices)
25 (seed voronoi-region-seed)
26 (vertices voronoi-region-vertices))
28 (define (make-voronoi-region seed vertices)
29 (define (compare-angles triangle1 triangle2)
30 (let ((c1 (triangle-center triangle1))
31 (c2 (triangle-center triangle2)))
32 (> (angle-sign seed c1 c2) 0)))
33 (make-raw-voronoi-region seed (list-sort compare-angles vertices)))
37 (define-record-type <voronoi-mesh>
38 (make-raw-voronoi-mesh triangles points frame regions)
40 (triangles voronoi-mesh-triangles)
41 (points voronoi-mesh-points)
42 (frame voronoi-mesh-frame)
43 (regions voronoi-mesh-regions))
45 (define* (make-voronoi-mesh vertices #:optional (relax-steps 3))
46 ;; Delaunay triangulation
47 (receive (triangles points frame)
48 (bowyer-watson vertices)
49 (make-raw-voronoi-mesh
53 (make-regions points triangles))))
55 (define (partitioning voronoi)
56 (define (is-real-triangle triangle)
57 ;; real triangle points cannot be frame points
58 (let ((frame (voronoi-mesh-frame voronoi)))
59 (let check-points ((points (triangle-points triangle)))
61 #t) ; triangle is real
63 (and (not (member (car points) frame))
64 (check-points (cdr points))))))))
66 (define (is-real-region region)
67 ;; real region points cannot be frame points
68 (let check-vertices ((vertices (voronoi-region-vertices region)))
69 (cond ((null? vertices)
72 (and (is-real-triangle (car vertices))
73 (check-vertices (cdr vertices)))))))
75 (let* ((points (voronoi-mesh-points voronoi))
76 (regions (voronoi-mesh-regions voronoi))
77 ;; we need the regions in the same order as points are
81 (assoc-ref regions p))
83 ;; only real regions without frame points
85 (filter (lambda (r) (is-real-region r))
89 (define* (voronoi-mesh-relax voronoi #:optional (to-relax '()))
90 (let ((regions (partitioning voronoi)))
93 (define (make-regions points triangles)
98 (lambda (tr) (member p (triangle-points tr)))
100 (cons p (make-voronoi-region p vertices))))