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  }