//Added by Dozed internal VEdge(VPoint start, VPoint end, FortuneSite left, FortuneSite right) { Start = start; End = end; Left = left; Right = right; }
internal VEdge(VPoint start, FortuneSite left, FortuneSite right) { Start = start; Left = left; Right = right; //for bounding box edges if (left == null || right == null) { return; } //from negative reciprocal of slope of line from left to right //ala m = (left.y -right.y / left.x - right.x) SlopeRise = left.X - right.X; SlopeRun = -(left.Y - right.Y); Intercept = null; if (SlopeRise.ApproxEqual(0) || SlopeRun.ApproxEqual(0)) { return; } Slope = SlopeRise / SlopeRun; Intercept = start.Y - Slope * start.X; }
public void Initialize(VPoint start, FortuneSite left, FortuneSite right) { Start = start; End = VPoint.Default; Left = left; Right = right; IsClipped = false; Neighbor = null; //for bounding box edges if (left == null || right == null) { return; } //from negative reciprocal of slope of line from left to right //ala m = (left.y -right.y / left.x - right.x) SlopeRise = left.X - right.X; SlopeRun = -(left.Y - right.Y); Intercept = null; if (SlopeRise.ApproxEqual(0) || SlopeRun.ApproxEqual(0)) { return; } Slope = SlopeRise / SlopeRun; Intercept = start.Y - Slope * start.X; }
private static VPoint FindCentroid(IReadOnlyList <VPoint> vertices) { var point = new VPoint(0d, 0d); var area = 0d; for (var i = 0; i < vertices.Count; i++) { var nextI = (i + 1) % vertices.Count; var x0 = vertices[i].X; var y0 = vertices[i].Y; var x1 = vertices[nextI].X; var y1 = vertices[nextI].Y; var a = (x0 * y1) - (x1 * y0); area += a; point.X += (x0 + x1) * a; point.Y += (y0 + y1) * a; } if (!area.ApproxEqual(0d)) { area *= 3d; point.X /= area; point.Y /= area; } return(point); }
/// <summary> /// /// </summary> /// <param name="times"></param> /// <param name="log">開始時はnullを指定してください。</param> /// <returns></returns> private static IEnumerable <List <VPoint> > Answers(int times, List <VPoint> log = null) { if (log == null) { log = new List <VPoint>() { new VPoint(0, 0) }; } var now = log.Last(); foreach (var move in moves) { var next = new VPoint(now.X + move.X, now.Y + move.Y); if (!log.Contains(next)) { var nextLog = new List <VPoint>(log); nextLog.Add(next); if (nextLog.Count == times + 1) { yield return(nextLog); } else { foreach (var item in Answers(times, nextLog)) { yield return(item); } } } } }
protected override void DrawLine(VPoint a, VPoint b) { var triangle = new Triangle(a, b, b); //Console.WriteLine($"DrawLine({a}, {b})"); TriangleRasterizer.RasterizeLine(a.P, b.P, triangle); }
private static VEdge AddEdgeForBoundingBox(VPoint startPoint, VPoint otherPoint, FortuneSite site, bool left) { var newEdge = new VEdge(startPoint, left ? site : null, left ? null : site) { End = otherPoint }; site.Cell.Add(newEdge); return(newEdge); }
public Line(VPoint p0, VPoint p1) { // Sort the points so that y0 <= y1 <= y2 if (p1.P.Y < p0.P.Y) { Swap(ref p1, ref p0); } P0 = p0; P1 = p1; }
protected override void Update(GameTime gameTime) { if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape)) { Exit(); } var newKeys = Keyboard.GetState(); var newMouse = Mouse.GetState(); if (keyboard.IsKeyDown(Keys.H) && newKeys.IsKeyUp(Keys.H)) { showHelp = !showHelp; } if (keyboard.IsKeyDown(Keys.G) && newKeys.IsKeyUp(Keys.G)) { GeneratePoints(); } if (keyboard.IsKeyDown(Keys.C) && newKeys.IsKeyUp(Keys.C)) { ClearPoints(); } if (keyboard.IsKeyDown(Keys.W) && newKeys.IsKeyUp(Keys.W)) { wiggle = !wiggle; } if (keyboard.IsKeyDown(Keys.V) && newKeys.IsKeyUp(Keys.V)) { showVoronoi = !showVoronoi; } if (keyboard.IsKeyDown(Keys.B) && newKeys.IsKeyUp(Keys.B)) { showCells = !showCells; } if (keyboard.IsKeyDown(Keys.D) && newKeys.IsKeyUp(Keys.D)) { showDelaunay = !showDelaunay; } if (mouse.LeftButton == ButtonState.Pressed && newMouse.LeftButton == ButtonState.Released) { AddPoint(mouse.X, mouse.Y); } if (mouse.RightButton == ButtonState.Pressed && newMouse.RightButton == ButtonState.Released) { testPoint = new VPoint(mouse.X, mouse.Y); } if (wiggle && points.Count > 0) { WigglePoints(); } keyboard = newKeys; mouse = newMouse; ////mouse = newMouse; base.Update(gameTime); }
private VPoint PQ_min() { VPoint answer = new VPoint(); while (PQhash[PQmin].PQnext == null) { PQmin++; } answer.x = PQhash[PQmin].PQnext.vertex.coord.x; answer.y = PQhash[PQmin].PQnext.ystar; return(answer); }
public static void Demo() { VPoint vp = new VPoint { X = 10, Y = -10 }; RPoint rp = new RPoint { X = 10, Y = -10 }; ClearPoints(vp, rp); Console.WriteLine($"VPoint: X={vp.X}, Y={vp.Y}"); // VPoint: X=10, Y=-10 Console.WriteLine($"RPoint: X={rp.X}, Y={rp.Y}"); // RPoint: X=0, Y=0 }
public Triangle(VPoint p0, VPoint p1, VPoint p2) { // Sort the points so that y0 <= y1 <= y2 if (p1.P.Y < p0.P.Y) { Swap(ref p1, ref p0); } if (p2.P.Y < p0.P.Y) { Swap(ref p2, ref p0); } if (p2.P.Y < p1.P.Y) { Swap(ref p2, ref p1); } P0 = p0; P1 = p1; P2 = p2; }
/// <summary> /// Returns the best path between the given start point (sole element of currentPath) and the endpoint within the voronoiGraph /// </summary> private static List <VPoint> GetShortestPath(List <VPoint> currentPath, VPoint endPoint, Dictionary <VPoint, List <VPoint> > voronoiGraph) { VPoint currentPoint = currentPath.Last(); if (voronoiGraph[currentPoint].Contains(endPoint)) { List <VPoint> nextPath = new List <VPoint>(); nextPath.AddRange(currentPath); nextPath.Add(endPoint); return(nextPath); } else if (voronoiGraph[currentPoint].All(x => currentPath.Contains(x))) { return(null); } else { List <VPoint> shortestPath = null; float shortestDistance = float.MaxValue; foreach (VPoint nextPoint in voronoiGraph[currentPoint].Where(x => !currentPath.Contains(x))) { List <VPoint> nextPath = new List <VPoint>(); nextPath.AddRange(currentPath); nextPath.Add(nextPoint); List <VPoint> nextPointPath = GetShortestPath(nextPath, endPoint, voronoiGraph); if (nextPointPath != null) { float nextPointPathDistance = GetPathDistance(nextPointPath, 0f); if (nextPointPathDistance < shortestDistance) { shortestDistance = nextPointPathDistance; shortestPath = nextPointPath; } } } return(shortestPath); } }
private void treeView_points_AfterSelect(object sender, TreeViewEventArgs e) { try { if (e.Node.Text.StartsWith(TB.L.Phrase["Form_Dialog_Edit.StartOfCont"])) { var a = new GraphicsPath(FillMode.Winding); a.AddPolygon(Vector.PointexToPoint(dat.BaseData.RawData[e.Node.Index])); SelectedContour = e.Node.Index; parent.RenderEX(Color.Violet, a); } else { SelectedContour = -1; var a = new GraphicsPath(FillMode.Winding); VPoint pnt = dat.BaseData.RawData[e.Node.Parent.Index][e.Node.Index].BasePoint; a.AddEllipse((float)pnt.Y, (float)pnt.X, 5, 5); parent.RenderEX(Color.Blue, a); } } catch { } }
public int Compare(Site p1, Site p2) { VPoint s1 = p1.coord; VPoint s2 = p2.coord; if (s1.y < s2.y) { return(-1); } if (s1.y > s2.y) { return(1); } if (s1.x < s2.x) { return(-1); } if (s1.x > s2.x) { return(1); } return(0); }
private static List <VPoint> SmoothLine(List <VPoint> line) { List <VPoint> smoothLine = new List <VPoint>(); smoothLine.Add(line[0]); for (int i = 1; i < line.Count - 1; i++) { List <VPoint> avgPoints = new List <VPoint>(); if (i > 0) { avgPoints.Add(line[i - 1]); } avgPoints.Add(line[i]); if (i < line.Count - 1) { avgPoints.Add(line[i + 1]); } VPoint smoothenedPoint = new VPoint(avgPoints.Average(x => x.X), avgPoints.Average(x => x.Y)); smoothLine.Add(smoothenedPoint); } smoothLine.Add(line.Last()); return(smoothLine); }
private static bool ClipRay(VEdge edge, double minX, double minY, double maxX, double maxY) { var start = edge.Start; //horizontal ray if (edge.SlopeRise.ApproxEqual(0)) { if (!Within(start.Y, minY, maxY)) { return(false); } if (edge.SlopeRun > 0 && start.X > maxX) { return(false); } if (edge.SlopeRun < 0 && start.X < minX) { return(false); } if (Within(start.X, minX, maxX)) { if (edge.SlopeRun > 0) { edge.End = new VPoint(maxX, start.Y); } else { edge.End = new VPoint(minX, start.Y); } } else { if (edge.SlopeRun > 0) { edge.Start = new VPoint(minX, start.Y); edge.End = new VPoint(maxX, start.Y); } else { edge.Start = new VPoint(maxX, start.Y); edge.End = new VPoint(minX, start.Y); } } return(true); } //vertical ray if (edge.SlopeRun.ApproxEqual(0)) { if (start.X < minX || start.X > maxX) { return(false); } if (edge.SlopeRise > 0 && start.Y > maxY) { return(false); } if (edge.SlopeRise < 0 && start.Y < minY) { return(false); } if (Within(start.Y, minY, maxY)) { if (edge.SlopeRise > 0) { edge.End = new VPoint(start.X, maxY); } else { edge.End = new VPoint(start.X, minY); } } else { if (edge.SlopeRise > 0) { edge.Start = new VPoint(start.X, minY); edge.End = new VPoint(start.X, maxY); } else { edge.Start = new VPoint(start.X, maxY); edge.End = new VPoint(start.X, minY); } } return(true); } //works for outside Debug.Assert(edge.Slope != null, "edge.Slope != null"); Debug.Assert(edge.Intercept != null, "edge.Intercept != null"); var topX = new VPoint(CalcX(edge.Slope.Value, maxY, edge.Intercept.Value), maxY); var bottomX = new VPoint(CalcX(edge.Slope.Value, minY, edge.Intercept.Value), minY); var leftY = new VPoint(minX, CalcY(edge.Slope.Value, minX, edge.Intercept.Value)); var rightY = new VPoint(maxX, CalcY(edge.Slope.Value, maxX, edge.Intercept.Value)); //reject intersections not within bounds var candidates = new List <VPoint>(); if (Within(topX.X, minX, maxX)) { candidates.Add(topX); } if (Within(bottomX.X, minX, maxX)) { candidates.Add(bottomX); } if (Within(leftY.Y, minY, maxY)) { candidates.Add(leftY); } if (Within(rightY.Y, minY, maxY)) { candidates.Add(rightY); } //reject candidates which don't align with the slope for (var i = candidates.Count - 1; i > -1; i--) { var candidate = candidates[i]; //grab vector representing the edge var ax = candidate.X - start.X; var ay = candidate.Y - start.Y; if (edge.SlopeRun * ax + edge.SlopeRise * ay < 0) { candidates.RemoveAt(i); } } //if there are two candidates we are outside the closer one is start //the further one is the end if (candidates.Count == 2) { var ax = candidates[0].X - start.X; var ay = candidates[0].Y - start.Y; var bx = candidates[1].X - start.X; var by = candidates[1].Y - start.Y; if (ax * ax + ay * ay > bx * bx + by * by) { edge.Start = candidates[1]; edge.End = candidates[0]; } else { edge.Start = candidates[0]; edge.End = candidates[1]; } } //if there is one candidate we are inside if (candidates.Count == 1) { edge.End = candidates[0]; } //there were no candidates return(edge.End != null); }
public static Vector2 ToVector2(this VPoint site) { return(new Vector2((float)site.X, (float)site.Y)); }
protected override void DrawTriangle(VPoint a, VPoint b, VPoint c) { var triangle = new Triangle(a, b, c); TriangleRasterizer.RasterizeTriangle(triangle.P0.P, triangle.P1.P, triangle.P2.P, triangle); }
public void Initialize(VPoint lowest, double yCenter, RBTreeNode <BeachSection> toDelete) { Lowest = lowest; YCenter = yCenter; ToDelete = toDelete; }
public Tile(VPoint point, Texture2D texture, Rectangle source, bool isPassable = true) : this(point.X, point.Y, point.Type, texture, source, isPassable) { }
public ImageSource GetKingdomMap(string kingdomName) { if (mapPerlin == null) { GenPerlinMap(); } Bitmap bmp = new Bitmap(mapPerlin); Kingdom currentK = this.kingdoms.Where(e => e.Name == kingdomName).First(); using (Graphics g = Graphics.FromImage(bmp)) { List <Point> frontier = new List <Point>(); foreach (Region site in currentK.regions) { List <VEdge> tmp = new List <VEdge>(); int i = 0; tmp.Add(site.Cell.First()); site.Cell.Remove(site.Cell.First()); while (!site.Cell.IsEmpty() && i < site.Cell.Count) { VEdge ve = site.Cell.ElementAt(i); VEdge t = tmp.Last(); if (t.End == ve.Start) { tmp.Add(ve); site.Cell.Remove(ve); i = 0; } else if (t.End == ve.End) { VPoint vp = ve.End; ve.End = ve.Start; ve.Start = vp; tmp.Add(ve); site.Cell.Remove(ve); i = 0; } else { i++; } } site.Cell = tmp; List <Point> points = new List <Point>(); foreach (var edge in site.Cell) { points.Add(new Point((int)edge.Start.X, (int)edge.Start.Y)); points.Add(new Point((int)edge.End.X, (int)edge.End.Y)); } Point[] tab = points.ToArray(); Color color = Color.FromArgb(150, site.Kingdom.Color.R, site.Kingdom.Color.G, site.Kingdom.Color.B); g.FillPolygon(new SolidBrush(color), tab); if (site.City) { if (!site.Capital) { g.FillEllipse(new SolidBrush(Color.White), (float)(site.X - 2), (float)(site.Y - 2), 5f, 5f); } else { g.FillEllipse(new SolidBrush(Color.Yellow), (float)(site.X - 2), (float)(site.Y - 2), 5f, 5f); } } } g.FillRectangle(new SolidBrush(Color.FromArgb(50, 255, 255, 255)), 0, 0, this.mapWidth, this.mapHeight); } return(ImageSourceFromBitmap(bmp)); }
public ImageSource GetGodMap(string godString) { God currentG = this.pantheon.Gods.Where(e => e.ToString() == godString).First(); if (!currentG.Forgot) { if (mapPerlin == null) { GenPerlinMap(); } Bitmap bmp = new Bitmap(mapPerlin); using (Graphics g = Graphics.FromImage(bmp)) { foreach (Region site in currentG.Followers) { List <VEdge> tmp = new List <VEdge>(); int i = 0; tmp.Add(site.Cell.First()); site.Cell.Remove(site.Cell.First()); while (!site.Cell.IsEmpty() && i < site.Cell.Count) { VEdge ve = site.Cell.ElementAt(i); VEdge t = tmp.Last(); if (t.End == ve.Start) { tmp.Add(ve); site.Cell.Remove(ve); i = 0; } else if (t.End == ve.End) { VPoint vp = ve.End; ve.End = ve.Start; ve.Start = vp; tmp.Add(ve); site.Cell.Remove(ve); i = 0; } else { i++; } } site.Cell = tmp; List <Point> points = new List <Point>(); foreach (var edge in site.Cell) { points.Add(new Point((int)edge.Start.X, (int)edge.Start.Y)); points.Add(new Point((int)edge.End.X, (int)edge.End.Y)); } Point[] tab = points.ToArray(); Color color = Color.FromArgb(150, site.God.Color.R, site.God.Color.G, site.God.Color.B); g.FillPolygon(new SolidBrush(color), tab); if (site.City) { if (site == site.God.Capitale) { g.FillEllipse(new SolidBrush(Color.White), (float)(site.X - 2), (float)(site.Y - 2), 5f, 5f); } else { g.FillEllipse(new SolidBrush(Color.Yellow), (float)(site.X - 2), (float)(site.Y - 2), 5f, 5f); } } } g.FillRectangle(new SolidBrush(Color.FromArgb(50, 255, 255, 255)), 0, 0, this.mapWidth, this.mapHeight); } return(ImageSourceFromBitmap(bmp)); } else { return(this.ImageSourceFromBitmap((Bitmap)Bitmap.FromFile("Assets/Background/BackgroundTemple.jpg"))); } }
public ImageSource GetVoronoiGraph(bool delaunay = false) { if (mapPerlin == null) { GenPerlinMap(); } Bitmap bmp = new Bitmap(mapPerlin); using (Graphics g = Graphics.FromImage(bmp)) { int seed = -1; foreach (Region site in sites) { seed++; if (site.Kingdom != null && affSite) { List <VEdge> tmp = new List <VEdge>(); int i = 0; tmp.Add(site.Cell.First()); site.Cell.Remove(site.Cell.First()); while (!site.Cell.IsEmpty() && i < site.Cell.Count) { VEdge ve = site.Cell.ElementAt(i); VEdge t = tmp.Last(); if (t.End == ve.Start) { tmp.Add(ve); site.Cell.Remove(ve); i = 0; } else if (t.End == ve.End) { VPoint vp = ve.End; ve.End = ve.Start; ve.Start = vp; tmp.Add(ve); site.Cell.Remove(ve); i = 0; } else { i++; } } site.Cell = tmp; List <Point> points = new List <Point>(); foreach (var edge in site.Cell) { points.Add(new Point((int)edge.Start.X, (int)edge.Start.Y)); points.Add(new Point((int)edge.End.X, (int)edge.End.Y)); } Point[] tab = points.ToArray(); Random rand = new Random(seed); Color color = Color.FromArgb(90, site.Kingdom.Color.R, site.Kingdom.Color.G, site.Kingdom.Color.B); g.FillPolygon(new SolidBrush(color), tab); } if (site.God != null && this.croyance) { List <VEdge> tmp = new List <VEdge>(); int i = 0; tmp.Add(site.Cell.First()); site.Cell.Remove(site.Cell.First()); while (!site.Cell.IsEmpty() && i < site.Cell.Count) { VEdge ve = site.Cell.ElementAt(i); VEdge t = tmp.Last(); if (t.End == ve.Start) { tmp.Add(ve); site.Cell.Remove(ve); i = 0; } else if (t.End == ve.End) { VPoint vp = ve.End; ve.End = ve.Start; ve.Start = vp; tmp.Add(ve); site.Cell.Remove(ve); i = 0; } else { i++; } } site.Cell = tmp; List <Point> points = new List <Point>(); foreach (var edge in site.Cell) { points.Add(new Point((int)edge.Start.X, (int)edge.Start.Y)); points.Add(new Point((int)edge.End.X, (int)edge.End.Y)); } Point[] tab = points.ToArray(); Random rand = new Random(seed); Color color = Color.FromArgb(90, site.God.Color.R, site.God.Color.G, site.God.Color.B); g.FillPolygon(new SolidBrush(color), tab); } if (site.City) { if (!site.Capital) { g.FillEllipse(new SolidBrush(Color.Crimson), (float)(site.X - 2), (float)(site.Y - 2), 5f, 5f); } else { g.FillEllipse(new SolidBrush(Color.Yellow), (float)(site.X - 2), (float)(site.Y - 2), 5f, 5f); } } if (delaunay) { foreach (var neighbor in site.Neighbors) { g.DrawLine(new System.Drawing.Pen(Color.Blue), (float)site.X, (float)site.Y, (float)neighbor.X, (float)neighbor.Y); } } } if (voronoi) { foreach (VEdge vedge in vedges) { g.DrawLine(new System.Drawing.Pen(System.Drawing.Color.Black), new System.Drawing.Point((int)vedge.Start.X, (int)vedge.Start.Y), new System.Drawing.Point((int)vedge.End.X, (int)vedge.End.Y)); } } } return(ImageSourceFromBitmap(bmp)); }
public ImageSource GetVoronoiGraph(System.Windows.Point position, bool delaunay = false) { if (mapPerlin == null) { GenPerlinMap(); } Bitmap bmp = new Bitmap(mapPerlin); using (Graphics g = Graphics.FromImage(bmp)) { int seed = -1; Region info = (Region)this.sites.First(); double distMin = this.mapWidth * 2; foreach (Region site in this.sites) { seed++; if (site.Kingdom != null && this.affSite) { List <VEdge> tmp = new List <VEdge>(); int i = 0; tmp.Add(site.Cell.First()); site.Cell.Remove(site.Cell.First()); while (!site.Cell.IsEmpty() && i < site.Cell.Count) { VEdge ve = site.Cell.ElementAt(i); VEdge t = tmp.Last(); if (t.End == ve.Start) { tmp.Add(ve); site.Cell.Remove(ve); i = 0; } else if (t.End == ve.End) { VPoint vp = ve.End; ve.End = ve.Start; ve.Start = vp; tmp.Add(ve); site.Cell.Remove(ve); i = 0; } else { i++; } } site.Cell = tmp; List <Point> points = new List <Point>(); foreach (var edge in site.Cell) { points.Add(new Point((int)edge.Start.X, (int)edge.Start.Y)); points.Add(new Point((int)edge.End.X, (int)edge.End.Y)); } Point[] tab = points.ToArray(); Random rand = new Random(seed); Color color = Color.FromArgb(90, site.Kingdom.Color.R, site.Kingdom.Color.G, site.Kingdom.Color.B); g.FillPolygon(new SolidBrush(color), tab); } if (site.God != null && this.croyance) { List <VEdge> tmp = new List <VEdge>(); int i = 0; tmp.Add(site.Cell.First()); site.Cell.Remove(site.Cell.First()); while (!site.Cell.IsEmpty() && i < site.Cell.Count) { VEdge ve = site.Cell.ElementAt(i); VEdge t = tmp.Last(); if (t.End == ve.Start) { tmp.Add(ve); site.Cell.Remove(ve); i = 0; } else if (t.End == ve.End) { VPoint vp = ve.End; ve.End = ve.Start; ve.Start = vp; tmp.Add(ve); site.Cell.Remove(ve); i = 0; } else { i++; } } site.Cell = tmp; List <Point> points = new List <Point>(); foreach (var edge in site.Cell) { points.Add(new Point((int)edge.Start.X, (int)edge.Start.Y)); points.Add(new Point((int)edge.End.X, (int)edge.End.Y)); } Point[] tab = points.ToArray(); Random rand = new Random(seed); Color color = Color.FromArgb(90, site.God.Color.R, site.God.Color.G, site.God.Color.B); g.FillPolygon(new SolidBrush(color), tab); } double dist = Math.Sqrt(Math.Pow(site.X - position.X, 2) + Math.Pow(site.Y - position.Y, 2)); if (distMin > dist) { info = site; distMin = dist; } if (site.City) { if (!site.Capital) { g.FillEllipse(new SolidBrush(Color.Crimson), (float)(site.X - 2), (float)(site.Y - 2), 5f, 5f); } else { g.FillEllipse(new SolidBrush(Color.Yellow), (float)(site.X - 2), (float)(site.Y - 2), 5f, 5f); } } if (delaunay) { foreach (var neighbor in site.Neighbors) { g.DrawLine(new System.Drawing.Pen(Color.Blue), (float)site.X, (float)site.Y, (float)neighbor.X, (float)neighbor.Y); } } } if (info != null && (this.croyance || this.affSite)) { string str = ""; if (this.affSite) { if (info.Kingdom == null) { str = "Les régions sauvages"; } else { str = info.Kingdom.Name; } } else if (this.croyance) { if (info.God == null) { str = "Non croyant"; } else { str = info.God.ToString(); } } Font font = new Font(System.Drawing.FontFamily.GenericMonospace, 12f, GraphicsUnit.Pixel); var width = str.Length * 7.5f; g.FillRectangle(new SolidBrush(Color.White), (position.X < this.mapWidth - width ? (float)(position.X) : (float)(position.X - width * 2)), (float)(position.Y - 10), width, font.Size + 2); g.DrawString(str, font, new SolidBrush(Color.Black), (position.X < this.mapWidth - width ? (float)(position.X) : (float)(position.X - width * 2)), (float)(position.Y - 10)); } if (voronoi) { foreach (VEdge vedge in vedges) { g.DrawLine(new System.Drawing.Pen(System.Drawing.Color.Black), new System.Drawing.Point((int)vedge.Start.X, (int)vedge.Start.Y), new System.Drawing.Point((int)vedge.End.X, (int)vedge.End.Y)); } } } return(ImageSourceFromBitmap(bmp)); }
/* * implicit parameters: nsites, sqrt_nsites, xmin, xmax, ymin, ymax, deltax, * deltay (can all be estimates). Performance suffers if they are wrong; * better to make nsites, deltax, and deltay too big than too small. (?) */ private bool voronoi_bd() { Site newsite, bot, top, temp, p; Site v; VPoint newintstar = null; int pm; Halfedge lbnd, rbnd, llbnd, rrbnd, bisector; Edge e; PQinitialize(); ELinitialize(); bottomsite = nextone(); newsite = nextone(); while (true) { if (!PQempty()) { newintstar = PQ_min(); } // if the lowest site has a smaller y value than the lowest vector // intersection, // process the site otherwise process the vector intersection if (newsite != null && (PQempty() || newsite.coord.y < newintstar.y || (newsite.coord.y == newintstar.y && newsite.coord.x < newintstar.x))) { /* new site is smallest -this is a site event */ // get the first HalfEdge to the LEFT of the new site lbnd = ELleftbnd((newsite.coord)); // get the first HalfEdge to the RIGHT of the new site rbnd = ELright(lbnd); // if this halfedge has no edge,bot =bottom site (whatever that // is) bot = rightreg(lbnd); // create a new edge that bisects e = bisect(bot, newsite); // create a new HalfEdge, setting its ELpm field to 0 bisector = HEcreate(e, LE); // insert this new bisector edge between the left and right // vectors in a linked list ELinsert(lbnd, bisector); // if the new bisector intersects with the left edge, // remove the left edge's vertex, and put in the new one if ((p = intersect(lbnd, bisector)) != null) { PQdelete(lbnd); PQinsert(lbnd, p, dist(p, newsite)); } lbnd = bisector; // create a new HalfEdge, setting its ELpm field to 1 bisector = HEcreate(e, RE); // insert the new HE to the right of the original bisector // earlier in the IF stmt ELinsert(lbnd, bisector); // if this new bisector intersects with the new HalfEdge if ((p = intersect(bisector, rbnd)) != null) { // push the HE into the ordered linked list of vertices PQinsert(bisector, p, dist(p, newsite)); } newsite = nextone(); } else if (!PQempty()) /* intersection is smallest - this is a vector event */ { // pop the HalfEdge with the lowest vector off the ordered list // of vectors lbnd = PQextractmin(); // get the HalfEdge to the left of the above HE llbnd = ELleft(lbnd); // get the HalfEdge to the right of the above HE rbnd = ELright(lbnd); // get the HalfEdge to the right of the HE to the right of the // lowest HE rrbnd = ELright(rbnd); // get the Site to the left of the left HE which it bisects bot = leftreg(lbnd); // get the Site to the right of the right HE which it bisects top = rightreg(rbnd); v = lbnd.vertex; // get the vertex that caused this event makevertex(v); // set the vertex number - couldn't do this // earlier since we didn't know when it would be processed endpoint(lbnd.ELedge, lbnd.ELpm, v); // set the endpoint of // the left HalfEdge to be this vector endpoint(rbnd.ELedge, rbnd.ELpm, v); // set the endpoint of the right HalfEdge to // be this vector ELdelete(lbnd); // mark the lowest HE for // deletion - can't delete yet because there might be pointers // to it in Hash Map PQdelete(rbnd); // remove all vertex events to do with the right HE ELdelete(rbnd); // mark the right HE for // deletion - can't delete yet because there might be pointers // to it in Hash Map pm = LE; // set the pm variable to zero if (bot.coord.y > top.coord.y) // if the site to the left of the event is higher than the // Site { // to the right of it, then swap them and set the 'pm' // variable to 1 temp = bot; bot = top; top = temp; pm = RE; } e = bisect(bot, top); // create an Edge (or line) // that is between the two Sites. This creates the formula of // the line, and assigns a line number to it bisector = HEcreate(e, pm); // create a HE from the Edge 'e', // and make it point to that edge // with its ELedge field ELinsert(llbnd, bisector); // insert the new bisector to the // right of the left HE endpoint(e, RE - pm, v); // set one endpoint to the new edge // to be the vector point 'v'. // If the site to the left of this bisector is higher than the // right Site, then this endpoint // is put in position 0; otherwise in pos 1 // if left HE and the new bisector intersect, then delete // the left HE, and reinsert it if ((p = intersect(llbnd, bisector)) != null) { PQdelete(llbnd); PQinsert(llbnd, p, dist(p, bot)); } // if right HE and the new bisector intersect, then // reinsert it if ((p = intersect(bisector, rrbnd)) != null) { PQinsert(bisector, p, dist(p, bot)); } } else { break; } } for (lbnd = ELright(ELleftend); lbnd != ELrightend; lbnd = ELright(lbnd)) { e = lbnd.ELedge; clip_line(e); } return(true); }
/* returns true if p is to right of halfedge e */ private bool right_of(Halfedge el, VPoint p) { Edge e; Site topsite; bool right_of_site; bool above, fast; double dxp, dyp, dxs, t1, t2, t3, yl; e = el.ELedge; topsite = e.reg[1]; if (p.x > topsite.coord.x) { right_of_site = true; } else { right_of_site = false; } if (right_of_site && el.ELpm == LE) { return(true); } if (!right_of_site && el.ELpm == RE) { return(false); } if (e.a == 1.0) { dxp = p.x - topsite.coord.x; dyp = p.y - topsite.coord.y; fast = false; if ((!right_of_site & (e.b < 0.0)) | (right_of_site & (e.b >= 0.0))) { above = dyp >= e.b * dxp; fast = above; } else { above = p.x + p.y * e.b > e.c; if (e.b < 0.0) { above = !above; } if (!above) { fast = true; } } if (!fast) { dxs = topsite.coord.x - (e.reg[0]).coord.x; above = e.b * (dxp * dxp - dyp * dyp) < dxs * dyp * (1.0 + 2.0 * dxp / dxs + e.b * e.b); if (e.b < 0) { above = !above; } } } else // e.b == 1.0 { yl = e.c - e.a * p.x; t1 = p.y - yl; t2 = p.x - topsite.coord.x; t3 = yl - topsite.coord.y; above = t1 * t1 > t2 * t2 + t3 * t3; } return(el.ELpm == LE ? above : !above); }
private Halfedge ELleftbnd(VPoint p) { int bucket; Halfedge he; /* Use hash table to get close to desired halfedge */ // use the hash function to find the place in the hash map that this // HalfEdge should be bucket = (int)((p.x - xmin) / deltax * ELhashsize); // make sure that the bucket position is within the range of the hash // array if (bucket < 0) { bucket = 0; } if (bucket >= ELhashsize) { bucket = ELhashsize - 1; } he = ELgethash(bucket); // if the HE isn't found, search backwards and forwards in the hash map // for the first non-null entry if (he == null) { for (int i = 1; i < ELhashsize; i++) { if ((he = ELgethash(bucket - i)) != null) { break; } if ((he = ELgethash(bucket + i)) != null) { break; } } } /* Now search linear list of halfedges for the correct one */ if (he == ELleftend || (he != ELrightend && right_of(he, p))) { // keep going right on the list until either the end is reached, or // you find the 1st edge which the point isn't to the right of do { he = he.ELright; }while (he != ELrightend && right_of(he, p)); he = he.ELleft; } else // if the point is to the left of the HalfEdge, then search left for // the HE just to the left of the point { do { he = he.ELleft; }while (he != ELleftend && !right_of(he, p)); } /* Update hash table and reference counts */ if (bucket > 0 && bucket < ELhashsize - 1) { ELhash[bucket] = he; } return(he); }
private static void AddBoundingBoxEdges(LinkedList <VEdge> edges, double minX, double minY, double maxX, double maxY) { // TODO: Need to clean this up.... var edgesCopy = edges.ToList(); var leftEdges = edgesCopy .Where(edge => edge.Start.X.ApproxEqual(minX) || edge.End.X.ApproxEqual(minX)) .Select(edge => new BoundingBoxInfo { Edge = edge, Vertex = edge.Start.X.ApproxEqual(minX) ? edge.Start : edge.End, Start = edge.Start.X.ApproxEqual(minX) }) .OrderBy(info => info.Vertex.Y) .ToArray(); var topLeftPoint = new VPoint(minX, minY); var topRightPoint = new VPoint(maxX, minY); var bottomLeftPoint = new VPoint(minX, maxY); var bottomRightPoint = new VPoint(maxX, maxY); var startPoint = topLeftPoint; for (var i = 0; i < leftEdges.Length; i++) { var currentEdge = leftEdges[i]; var site = currentEdge.Start ? currentEdge.Edge.Left : currentEdge.Edge.Right; edges.AddLast(AddEdgeForBoundingBox(startPoint, currentEdge.Vertex, site, true)); startPoint = currentEdge.Vertex; if (i < leftEdges.Length - 1) { continue; } site = currentEdge.Start ? currentEdge.Edge.Right : currentEdge.Edge.Left; edges.AddLast(AddEdgeForBoundingBox(startPoint, bottomLeftPoint, site, false)); } var topEdges = edgesCopy .Where(edge => edge.Start.Y.ApproxEqual(minY) || edge.End.Y.ApproxEqual(minY)) .Select(edge => new BoundingBoxInfo { Edge = edge, Vertex = edge.Start.Y.ApproxEqual(minY) ? edge.Start : edge.End, Start = edge.Start.Y.ApproxEqual(minY) }) .OrderBy(info => info.Vertex.X) .ToArray(); startPoint = topLeftPoint; for (var i = 0; i < topEdges.Length; i++) { var currentEdge = topEdges[i]; var site = currentEdge.Start ? currentEdge.Edge.Right : currentEdge.Edge.Left; edges.AddLast(AddEdgeForBoundingBox(startPoint, currentEdge.Vertex, site, false)); startPoint = currentEdge.Vertex; if (i < topEdges.Length - 1) { continue; } site = currentEdge.Start ? currentEdge.Edge.Left : currentEdge.Edge.Right; edges.AddLast(AddEdgeForBoundingBox(startPoint, topRightPoint, site, true)); } var rightEdges = edgesCopy .Where(edge => edge.Start.X.ApproxEqual(maxX) || edge.End.X.ApproxEqual(maxX)) .Select(edge => new BoundingBoxInfo { Edge = edge, Vertex = edge.Start.X.ApproxEqual(maxX) ? edge.Start : edge.End, Start = edge.Start.X.ApproxEqual(maxX) }) .OrderBy(info => info.Vertex.Y) .ToArray(); startPoint = topRightPoint; for (var i = 0; i < rightEdges.Length; i++) { var currentEdge = rightEdges[i]; var site = currentEdge.Start ? currentEdge.Edge.Right : currentEdge.Edge.Left; edges.AddLast(AddEdgeForBoundingBox(startPoint, currentEdge.Vertex, site, false)); startPoint = currentEdge.Vertex; if (i < rightEdges.Length - 1) { continue; } site = currentEdge.Start ? currentEdge.Edge.Left : currentEdge.Edge.Right; edges.AddLast(AddEdgeForBoundingBox(startPoint, bottomRightPoint, site, true)); } var bottomEdges = edgesCopy .Where(edge => edge.Start.Y.ApproxEqual(maxY) || edge.End.Y.ApproxEqual(maxY)) .Select(edge => new BoundingBoxInfo { Edge = edge, Vertex = edge.Start.Y.ApproxEqual(maxY) ? edge.Start : edge.End, Start = edge.Start.Y.ApproxEqual(maxY) }) .OrderBy(info => info.Vertex.X) .ToArray(); startPoint = bottomLeftPoint; for (var i = 0; i < bottomEdges.Length; i++) { var currentEdge = bottomEdges[i]; var site = currentEdge.Start ? currentEdge.Edge.Left : currentEdge.Edge.Right; edges.AddLast(AddEdgeForBoundingBox(startPoint, currentEdge.Vertex, site, false)); startPoint = currentEdge.Vertex; if (i < bottomEdges.Length - 1) { continue; } site = currentEdge.Start ? currentEdge.Edge.Right : currentEdge.Edge.Left; edges.AddLast(AddEdgeForBoundingBox(startPoint, bottomRightPoint, site, true)); } }
public Site() { coord = new VPoint(); }