github.com/joshvarga/voronoi@v0.0.0-20180211004454-2fd26fbdfffb/geometry.go (about) 1 // MIT License: See https://github.com/pzsz/voronoi/LICENSE.md 2 3 // Author: Przemyslaw Szczepaniak (przeszczep@gmail.com) 4 // Port of Raymond Hill's (rhill@raymondhill.net) javascript implementation 5 // of Steven Forune's algorithm to compute Voronoi diagrams 6 7 package voronoi 8 9 import ( 10 "math" 11 ) 12 13 // Vertex on 2D plane 14 type Vertex struct { 15 Index int 16 X float64 17 Y float64 18 } 19 20 // Vertex representing lack of vertex (or bad vertex) 21 var NO_VERTEX = Vertex{X:math.Inf(1), Y:math.Inf(1)} 22 23 // For sort interface 24 type Vertices []Vertex 25 26 func (s Vertices) Len() int { return len(s) } 27 func (s Vertices) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 28 29 // Used for sorting vertices along the Y axis 30 type VerticesByY struct{ Vertices } 31 32 func (s VerticesByY) Less(i, j int) bool { return s.Vertices[i].Y < s.Vertices[j].Y } 33 34 type EdgeVertex struct { 35 Vertex 36 Edges []*Edge 37 } 38 39 // Edge structure 40 type Edge struct { 41 // Cell on the left 42 LeftCell *Cell 43 // Cell on the right 44 RightCell *Cell 45 // Start Vertex 46 Va EdgeVertex 47 // End Vertex 48 Vb EdgeVertex 49 } 50 51 func (e *Edge) GetOtherCell(cell *Cell) *Cell { 52 if cell == e.LeftCell { 53 return e.RightCell 54 } else if cell == e.RightCell { 55 return e.LeftCell 56 } 57 return nil 58 } 59 60 func (e *Edge) GetOtherEdgeVertex(v Vertex) EdgeVertex { 61 if v == e.Va.Vertex { 62 return e.Vb 63 } else if v == e.Vb.Vertex { 64 return e.Va 65 } 66 return EdgeVertex{NO_VERTEX, nil} 67 } 68 69 func newEdge(LeftCell, RightCell *Cell) *Edge { 70 return &Edge{ 71 LeftCell: LeftCell, 72 RightCell: RightCell, 73 Va: EdgeVertex{NO_VERTEX, nil}, 74 Vb: EdgeVertex{NO_VERTEX, nil}, 75 } 76 } 77 78 // Halfedge (directed edge) 79 type Halfedge struct { 80 Cell *Cell 81 Edge *Edge 82 Angle float64 83 } 84 85 // Sort interface for halfedges 86 type Halfedges []*Halfedge 87 88 func (s Halfedges) Len() int { return len(s) } 89 func (s Halfedges) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 90 91 // For sorting by angle 92 type halfedgesByAngle struct{ Halfedges } 93 94 func (s halfedgesByAngle) Less(i, j int) bool { return s.Halfedges[i].Angle > s.Halfedges[j].Angle } 95 96 func newHalfedge(edge *Edge, LeftCell, RightCell *Cell) *Halfedge { 97 ret := &Halfedge{ 98 Cell: LeftCell, 99 Edge: edge, 100 } 101 102 // 'angle' is a value to be used for properly sorting the 103 // halfsegments counterclockwise. By convention, we will 104 // use the angle of the line defined by the 'site to the left' 105 // to the 'site to the right'. 106 // However, border edges have no 'site to the right': thus we 107 // use the angle of line perpendicular to the halfsegment (the 108 // edge should have both end points defined in such case.) 109 if RightCell != nil { 110 ret.Angle = math.Atan2(RightCell.Site.Y-LeftCell.Site.Y, RightCell.Site.X-LeftCell.Site.X) 111 } else { 112 va := edge.Va 113 vb := edge.Vb 114 // rhill 2011-05-31: used to call GetStartpoint()/GetEndpoint(), 115 // but for performance purpose, these are expanded in place here. 116 if edge.LeftCell == LeftCell { 117 ret.Angle = math.Atan2(vb.X-va.X, va.Y-vb.Y) 118 } else { 119 ret.Angle = math.Atan2(va.X-vb.X, vb.Y-va.Y) 120 } 121 } 122 return ret 123 } 124 125 func (h *Halfedge) GetStartpoint() Vertex { 126 if h.Edge.LeftCell == h.Cell { 127 return h.Edge.Va.Vertex 128 } 129 return h.Edge.Vb.Vertex 130 131 } 132 133 func (h *Halfedge) GetEndpoint() Vertex { 134 if h.Edge.LeftCell == h.Cell { 135 return h.Edge.Vb.Vertex 136 } 137 return h.Edge.Va.Vertex 138 }