Documentation ¶
Overview ¶
Package gencitymap generates a city map.
Index ¶
- Constants
- Variables
- func AveragePoint(polygon []vectors.Vec2) vectors.Vec2
- func CalcPolygonArea(polygon []vectors.Vec2) float64
- func Hilbert(x uint, y uint) uint
- func ResizeGeometry(geometry []vectors.Vec2, spacing float64, isPolygon bool) []vectors.Vec2
- func SubdividePolygon(poly []vectors.Vec2, minArea float64) [][]vectors.Vec2
- type BasisField
- type BasisFieldInterface
- type Bush
- type BushAsyncState
- type BushOptions
- type EulerIntegrator
- type FieldIntegrator
- type FieldIntegratorIf
- type Flatbush
- func (f *Flatbush) Add(minX float64, minY float64, maxX float64, maxY float64)
- func (f *Flatbush) Finish()
- func (f *Flatbush) Query(minX float64, minY float64, maxX float64, maxY float64, ...) []int
- func (f *Flatbush) Sort(values []uint, boxes []float64, indices []int, left int, right int, ...)
- func (f *Flatbush) Swap(values []uint, boxes []float64, indices []int, i int, j int)
- func (f *Flatbush) VisitQuery(minX float64, minY float64, maxX float64, maxY float64, ...)
- type Graph
- type GridField
- type GridStorage
- func (gs *GridStorage) AddAll(gridStorage *GridStorage)
- func (gs *GridStorage) AddPolyline(line []vectors.Vec2)
- func (gs *GridStorage) AddSample(v vectors.Vec2, coords *vectors.Vec2)
- func (gs *GridStorage) GetNearbyPoints(v vectors.Vec2, distance float64) []vectors.Vec2
- func (gs *GridStorage) GetSampleCoords(worldV vectors.Vec2) vectors.Vec2
- func (gs *GridStorage) IsValidSample(v vectors.Vec2, dSq float64) bool
- func (gs *GridStorage) VectorOutOfBounds(v vectors.Vec2, bounds vectors.Vec2) bool
- type Intersection
- type Map
- type MapConfig
- type Node
- type NoiseParams
- type OvalField
- type PolygonFinder
- type PolygonParams
- type PolygonUtil
- type PriorityQueue
- type QuadTree
- type RK4Integrator
- type RadialField
- type RoadType
- type Segment
- type SegmentTypeConfig
- type StreamlineGenerator
- type StreamlineIntegration
- type StreamlineParams
- type Tensor
- type TensorField
- type TotalTensorThing
Constants ¶
const ( FTRadialField = iota // RadialField represents a radial field. FTGridField // GridField represents a grid field. )
Variables ¶
var ( HighwayConfig = SegmentTypeConfig{ LengthMin: 200, LengthVariation: 0.1, AngleMin: 10.0, AngleVariance: 1.0, AngleReversal: true, BranchingChance: 0.3, BranchingAngle: 90.0, BranchingReversal: true, } StreetConfig = SegmentTypeConfig{ LengthMin: 100, LengthVariation: 0.5, AngleVariance: 4.0, AngleReversal: true, BranchingChance: 0.7, BranchingAngle: 90.0, BranchingReversal: true, BranchSameType: true, BranchSameTypeChance: 0.2, } FootpathConfig = SegmentTypeConfig{ LengthMin: 50, LengthVariation: 0.6, AngleVariance: 3.0, AngleReversal: true, BranchingChance: 0.5, BranchingAngle: 90.0, } )
var DefaultMapConfig = &MapConfig{ SeedRoots: func() []*Segment { root1 := &Segment{ Point: vectors.NewVec2(0, 0), Length: 100, Type: 0, } return []*Segment{root1} }, Rules: []*SegmentTypeConfig{ &HighwayConfig, &StreetConfig, &FootpathConfig, }, }
var DefaultNoiseParams = &NoiseParams{ Seed: 0, globalNoise: true, noiseSizePark: 2, noiseAnglePark: 9, noiseSizeGlobal: 3, noiseAngleGlobal: 2, }
var DefaultStreamlineParams = &StreamlineParams{
Dsep: 20,
Dtest: 15,
Dstep: 1,
Dcirclejoin: 5,
Dlookahead: 40,
Joinangle: 0.1,
PathIterations: 2000,
SeedTries: 30,
SimplifyTolerance: 10,
CollideEarly: 0.01,
}
Functions ¶
func AveragePoint ¶
AveragePoint returns the average point of a polygon.
func CalcPolygonArea ¶
func Hilbert ¶
Fast Hilbert curve algorithm by http://threadlocalmutex.com/ Ported from C++ https://github.com/rawrunprotected/hilbert_curves (public domain)
func ResizeGeometry ¶
ResizeGeometry resizes a polygon to a given spacing.
Types ¶
type BasisField ¶
BasisField represents a basis field used for generating a city map.
func NewBasisField ¶
func NewBasisField(centre vectors.Vec2, size, decay float64, fieldType int) *BasisField
NewBasisField creates a new basis field.
func (*BasisField) GetCentre ¶
func (b *BasisField) GetCentre() vectors.Vec2
type BasisFieldInterface ¶
type BushAsyncState ¶
type BushAsyncState struct {
I int
}
type BushOptions ¶
type EulerIntegrator ¶
type EulerIntegrator struct { *FieldIntegrator // contains filtered or unexported fields }
func NewEulerIntegrator ¶
func NewEulerIntegrator(field *TensorField, params *StreamlineParams) *EulerIntegrator
type FieldIntegrator ¶
type FieldIntegrator struct {
// contains filtered or unexported fields
}
func NewFieldIntegrator ¶
func NewFieldIntegrator(field *TensorField) *FieldIntegrator
func (*FieldIntegrator) SampleFieldVector ¶
type FieldIntegratorIf ¶
type Flatbush ¶
type Flatbush struct { NumItems int NodeSize int LevelBounds []int Boxes []float64 Indices []int Pos int MinX float64 MinY float64 MaxX float64 MaxY float64 }
This code is based on https://github.com/mourner/flatbush
func NewFlatbush ¶
func (*Flatbush) Finish ¶
func (f *Flatbush) Finish()
/ <summary> / Method to perform the indexing, to be called after adding all the boxes via <see cref="Add"/>. / </summary>
func (*Flatbush) Query ¶
func (f *Flatbush) Query(minX float64, minY float64, maxX float64, maxY float64, filter func(index int) bool) []int
/ <summary> / Returns a list of indices to boxes that intersect or overlap the bounding box given, <see cref="Finish"/> must be called before querying. / </summary> / <param name="minX">Min x value of the bounding box.</param> / <param name="minY">Min y value of the bounding box.</param> / <param name="maxX">Max x value of the bounding box.</param> / <param name="maxY">Max y value of the bounding box.</param> / <param name="filter">Optional filter function, if not null then only indices for which the filter function returns true will be included.</param> / <returns>List of indices that intersect or overlap with the bounding box given.</returns>
func (*Flatbush) Sort ¶
func (f *Flatbush) Sort(values []uint, boxes []float64, indices []int, left int, right int, nodeSize int)
custom quicksort that partially sorts bbox data alongside the hilbert values
func (*Flatbush) VisitQuery ¶
func (f *Flatbush) VisitQuery(minX float64, minY float64, maxX float64, maxY float64, visitor func(index int) bool)
/ <summary> / Invokes a function on each of the indices of boxes that intersect or overlap with the bounding box given, <see cref="Finish"/> must be called before querying. / </summary> / <param name="minX">Min x value of the bounding box.</param> / <param name="minY">Min y value of the bounding box.</param> / <param name="maxX">Max x value of the bounding box.</param> / <param name="maxY">Max y value of the bounding box.</param> / <param name="visitor">The function to visit each of the result indices, if false is returned no more results will be visited.</param>
type GridField ¶
type GridField struct { *BasisField Theta float64 }
func NewGridField ¶
NewGridField creates a new grid field.
type GridStorage ¶
type GridStorage struct {
// contains filtered or unexported fields
}
GridStorage is a grid-based storage for samples. NOTE: Cartesian grid accelerated data structure, Grid of cells, each containing a list of vectors.
func NewGridStorage ¶
NewGridStorage creates a new grid storage. NOTE: worldDimensions assumes origin of 0,0, dsep is the separation distance between samples.
func (*GridStorage) AddAll ¶
func (gs *GridStorage) AddAll(gridStorage *GridStorage)
AddAll adds all samples from another grid to this one.
func (*GridStorage) AddPolyline ¶
func (gs *GridStorage) AddPolyline(line []vectors.Vec2)
func (*GridStorage) AddSample ¶
func (gs *GridStorage) AddSample(v vectors.Vec2, coords *vectors.Vec2)
AddSample adds a sample to the grid. NOTE: Does not enforce separation, does not clone.
func (*GridStorage) GetNearbyPoints ¶
GetNearbyPoints returns points in cells surrounding v. Results include v, if it exists in the grid. NOTE: Returns samples (kind of) closer than distance - returns all samples in cells so approximation (square to approximate circle).
func (*GridStorage) GetSampleCoords ¶
func (gs *GridStorage) GetSampleCoords(worldV vectors.Vec2) vectors.Vec2
GetSampleCoords returns the cell coords corresponding to the vector. NOTE: Performance is important here - this is called at every integration step.
func (*GridStorage) IsValidSample ¶
func (gs *GridStorage) IsValidSample(v vectors.Vec2, dSq float64) bool
IsValidSample returns true if the sample is valid and within the world dimensions. Tests whether v is at least d away from samples. NOTE: Performance is very important - this is called at every integration step! dSq=this.dsepSq squared test distance Could be dtest if we are integrating a streamline
func (*GridStorage) VectorOutOfBounds ¶
type Intersection ¶
type Intersection struct {
// contains filtered or unexported fields
}
type Map ¶
type Map struct {
// contains filtered or unexported fields
}
Map is a map.
func (*Map) Dimensions ¶
Dimensions returns the dimensions of the map.
func (*Map) ExportToPNG ¶
ExportToPNG exports the map to a PNG file.
func (*Map) Streamlines ¶
type MapConfig ¶
type MapConfig struct { SeedRoots func() []*Segment Rules []*SegmentTypeConfig }
type Node ¶
type Node struct {
// contains filtered or unexported fields
}
Node located along any intersection or point along the simplified road polylines.
type NoiseParams ¶
type NoiseParams struct { Seed int64 // contains filtered or unexported fields }
type OvalField ¶
type OvalField struct { *BasisField Theta float64 // Direction of the major axis Ratio float64 // Ratio of the major and minor axis }
func NewOvalField ¶
NewOvalField creates a new oval field. NOTE: This tends to create spirals, so use with caution.
type PolygonFinder ¶
type PolygonFinder struct { Polygons [][]vectors.Vec2 ShrunkPolygons [][]vectors.Vec2 DividedPolygons [][]vectors.Vec2 Nodes []*Node Params PolygonParams TensorField *TensorField // contains filtered or unexported fields }
PolygonFinder finds polygons in a graph, used for finding lots and parks.
func NewPolygonFinder ¶
func NewPolygonFinder(nodes []*Node, params PolygonParams, tensorField *TensorField) *PolygonFinder
func (*PolygonFinder) Divide ¶
func (p *PolygonFinder) Divide(animate bool)
func (*PolygonFinder) Reset ¶
func (p *PolygonFinder) Reset()
func (*PolygonFinder) Shrink ¶
func (p *PolygonFinder) Shrink(animate bool)
Shrink shrinks the polygons by the given amount. Properly shrink polygon so the edges are all the same distance from the road.
func (*PolygonFinder) Update ¶
func (p *PolygonFinder) Update() bool
type PolygonParams ¶
type PolygonUtil ¶
type PolygonUtil struct { }
func (*PolygonUtil) InsidePolygon ¶
func (*PolygonUtil) PointInRectangle ¶
func (*PolygonUtil) SliceRectangle ¶
func (p *PolygonUtil) SliceRectangle(origin, worldDimensions, p1, p2 vectors.Vec2) []vectors.Vec2
SliceRectangle slices a rectangle by line, returning the smallest polygon.
type PriorityQueue ¶
type PriorityQueue []*Segment
func (PriorityQueue) Len ¶
func (pq PriorityQueue) Len() int
func (PriorityQueue) Less ¶
func (pq PriorityQueue) Less(i, j int) bool
func (*PriorityQueue) Pop ¶
func (pq *PriorityQueue) Pop() interface{}
func (*PriorityQueue) Push ¶
func (pq *PriorityQueue) Push(x interface{})
func (PriorityQueue) Swap ¶
func (pq PriorityQueue) Swap(i, j int)
type RK4Integrator ¶
type RK4Integrator struct { *FieldIntegrator // contains filtered or unexported fields }
func NewRK4Integrator ¶
func NewRK4Integrator(field *TensorField, params *StreamlineParams) *RK4Integrator
type RadialField ¶
type RadialField struct {
*BasisField
}
func NewRadialField ¶
func NewRadialField(centre vectors.Vec2, size, decay float64) *RadialField
NewRadialField creates a new radial field.
func (*RadialField) GetWeightedTensor ¶
func (r *RadialField) GetWeightedTensor(point vectors.Vec2, smooth bool) *Tensor
type Segment ¶
type Segment struct { Point vectors.Vec2 // end point of the segment Length float64 // length of the segment Next *Segment // next segment in the same road Prev *Segment // previous segment in the same road Type RoadType // type of the segment Branches []*Segment // branches from the same road Step int // Iteration when this segment was created End bool // true if this segment is the end of a road }
Segment is a segment of a road.
func (*Segment) Intersects ¶
Intersects returns true if the segment intersects with the given segment and the intersection point.
func (*Segment) IsPointOnLine ¶
IsPointOnLine returns true if the given point is on the line of the segment (within 0.0001)
type SegmentTypeConfig ¶
type SegmentTypeConfig struct { LengthMin float64 // minimum length of a segment of this type LengthVariation float64 // maximum length variation of a segment of this type (0.1 = 10%) AngleMin float64 // minimum angle of a segment extension in degrees (10.0 = 10°) AngleVariance float64 // maximum angle variation of a segment extension in degrees (10.0 = 10°) AngleReversal bool // allow reverse angle of the road BranchingChance float64 // chance of branching (0.1 = 10%) BranchingAngle float64 // angle of subbranches in degrees (10.0 = 10°) BranchingReversal bool // allow reverse branching direction of the road BranchSameType bool // allow branching to the same type of road BranchSameTypeChance float64 // chance of branching to the same type of road (0.1 = 10%) }
SegmentTypeConfig is the configuration for a segment type.
type StreamlineGenerator ¶
type StreamlineGenerator struct { SEED_AT_ENDPOINTS bool NEAR_EDGE int // Sample near edge // contains filtered or unexported fields }
func NewStreamlineGenerator ¶
func NewStreamlineGenerator(seed int64, integrator FieldIntegratorIf, origin, worldDimensions vectors.Vec2, params *StreamlineParams) (*StreamlineGenerator, error)
func (*StreamlineGenerator) ClearStreamlines ¶
func (sg *StreamlineGenerator) ClearStreamlines()
func (*StreamlineGenerator) ExportToSVG ¶
func (sg *StreamlineGenerator) ExportToSVG(filename string) error
ExportToSVG exports the streamlines to an SVG file.
type StreamlineIntegration ¶
type StreamlineParams ¶
type StreamlineParams struct { Dsep float64 // Streamline seed separating distance Dtest float64 // Streamline integration separating distance Dstep float64 // Step size Dcirclejoin float64 // How far to look to join circles - (e.g. 2 x dstep) Dlookahead float64 // How far to look ahead to join up dangling Joinangle float64 // Angle to join roads in radians PathIterations int // Path integration iteration limit SeedTries int // Max failed seeds SimplifyTolerance float64 CollideEarly float64 // Chance of early collision 0-1 }
type Tensor ¶
type Tensor struct {
// contains filtered or unexported fields
}
Tensor represents a tensor used for generating a city map. Represent the matrix as a 2 element list [ 0, 1 , 1, -0 ]
type TensorField ¶
type TensorField struct {
// contains filtered or unexported fields
}
func NewTensorField ¶
func NewTensorField(n *NoiseParams) *TensorField
NewTensorField creates a new tensor field.
type TotalTensorThing ¶
type TotalTensorThing struct {
// contains filtered or unexported fields
}
func TensorTest ¶
func TensorTest() (*TotalTensorThing, error)
func (*TotalTensorThing) ExportToPNG ¶
func (t *TotalTensorThing) ExportToPNG(filename string) error