/// <summary> /// Get the voronoi cell for the given point using the clip polygon. /// </summary> /// <param name="point"></param> /// <param name="clipPolygon"></param> /// <returns></returns> public Cell GetVoronoiCell(Point point, Vector2[] clipPolygon) { List <Vector2> currentPolygon = GetCircumCenterVectors(point); if (currentPolygon.Count == 0) { return(null); } Cell cell; if (clipPolygon == null) { Vector2 centroid = PolygonUtils.GetMeanVector(currentPolygon.ToArray()); cell = new Cell(currentPolygon.ToArray(), centroid, ToVector(point)); } else { Vector2[] clippedPoints = SutherlandHodgman.GetIntersectedPolygon(currentPolygon.ToArray(), clipPolygon); if (clippedPoints.Length == 0) { UnityEngine.Debug.Log("Clipping algorithm returned non-intersecting polygon. Skipping it."); return(null); } Vector2 centroid = PolygonUtils.GetMeanVector(clippedPoints); // create the cell including polygons and center point cell = new Cell(clippedPoints, centroid, ToVector(point)); } return(cell); }
/// <summary> /// Get the voronoi cell for the given point using the clip polygon. /// </summary> /// <param name="point"></param> /// <param name="clipPolygon"></param> /// <returns></returns> public Cell GetVoronoiCell(Point point, Vector[] clipPolygon) { List <Vector> currentPolygon = GetCircumCenterVectors(point); if (currentPolygon.Count == 0) { return(null); } Cell cell; if (clipPolygon == null) { Vector centroid = PolygonUtils.GetMeanVector(currentPolygon.ToArray()); cell = new Cell(currentPolygon.ToArray(), centroid, ToVector(point)); } else { Vector[] clippedPoints = SutherlandHodgman.GetIntersectedPolygon(currentPolygon.ToArray(), clipPolygon); Vector centroid = PolygonUtils.GetMeanVector(clippedPoints); // create the cell including polygons and center point cell = new Cell(clippedPoints, centroid, ToVector(point)); } return(cell); }
public MainWindow() { InitializeComponent(); SetupButtonTab(); _width = (int)PaintSurface.Width; _height = (int)PaintSurface.Height; _sourceRect = new Int32Rect(0, 0, _width, _height); SetupBitmap(); _sourceBuffer = new byte[_width * _height * (_wb.Format.BitsPerPixel / 8)]; ClearScreen(); Instance = this; RedrawAll(); var points1 = new System.Windows.Point[] { new System.Windows.Point(1, 1), new System.Windows.Point(1, 50), new System.Windows.Point(50, 1) }; var points2 = new System.Windows.Point[] { new System.Windows.Point(10, 10), new System.Windows.Point(10, 50), new System.Windows.Point(50, 10) }; var clip = SutherlandHodgman.GetIntersectedPolygon(points1, points2); List <Point> pointz = new List <Point>() { new Point(3, 0), new Point(0, 3), new Point(3, 6), new Point(6, 3) }; var filling = ScanLine.PolygonFilling(pointz, out var colorTab, true); UpdateDotProducts(); StartMainLoop(); }
private static IList <Coordinate> GetIntersectedPolygon(Point[] points, Point[] clipPoly) { List <Coordinate> p = new List <Coordinate>(); foreach (var point in points) { p.Add(new Coordinate(point.X, point.Y)); } return(SutherlandHodgman.GetIntersectedPolygon(p, clipPoly)); }
/// <summary> /// Create Biome masks for the specified bounds /// </summary> /// <param name="bounds"></param> private void CreateMasks(Bounds bounds) { float outerRadius = GetOuterRadius(bounds); // bounds for clipping Vector2[] clipPolygon = editor.GetBiomeClipPolygon(bounds); float density = editor.extension.biomeSettings.density; List <Vector3> positions = GetPositions(bounds); foreach (Vector3 position in positions) { // skip randomly if (density != 1 && UnityEngine.Random.Range(0f, 1f) >= density) { continue; } Vector3[] hexagon = ShapeCreator.CreateHexagon(position, outerRadius); // clip, convert to vector2 Vector2[] polygonXY = hexagon.Select(item => new Vector2(item.x, item.z)).ToArray(); Vector2[] clippedPoints = SutherlandHodgman.GetIntersectedPolygon(polygonXY, clipPolygon); if (clippedPoints == null || clippedPoints.Length < 3) { continue; } // convert back to vector3 hexagon = clippedPoints.Select(item => new Vector3(item.x, 0, item.y)).ToArray(); int maskId = editor.GetNextMaskId(); List <Vector3> nodes = hexagon.OfType <Vector3>().ToList(); // apply random shape if requested if (editor.extension.shapeSettings.randomShape) { nodes = ShapeCreator.CreateRandomShape(nodes, // editor.extension.shapeSettings.RandomConvexity, // editor.extension.shapeSettings.keepOriginalPoints, // editor.extension.shapeSettings.RandomPointsCount, // editor.extension.shapeSettings.randomAngle, // editor.extension.shapeSettings.douglasPeuckerReductionTolerance); } CreateBiomeMaskArea("Biome Mask " + maskId, "Mask " + maskId, position, nodes); } }
private void CreateBiomeMaskArea(string gameObjectName, string maskName, Bounds bounds) { // modify bounds, reduce its rectangular distribution float minFactor = editor.extension.rectangularPartitionSettings.boundsShiftFactorMin; float maxFactor = editor.extension.rectangularPartitionSettings.boundsShiftFactorMax; bounds = PolygonUtils.ShiftResizeBounds(bounds, minFactor, maxFactor); List <Vector3> nodes; if (editor.extension.shapeSettings.randomShape) { // old mechanism: convex hull // nodes = ShapeCreator.CreateRandomShapeUsingConvexHull(bounds, randomPointCount); // new mechanism: random shape with parameters like convexity nodes = ShapeCreator.CreateRandomShape( ShapeCreator.CreateRectangularBoundsShape(bounds), editor.extension.shapeSettings.RandomConvexity, // editor.extension.shapeSettings.keepOriginalPoints, // editor.extension.shapeSettings.RandomPointsCount, // editor.extension.shapeSettings.randomAngle, // editor.extension.shapeSettings.douglasPeuckerReductionTolerance); } // exact bounds else { nodes = ShapeCreator.CreateRectangularBoundsShape(bounds); } // bounds for clipping Vector2[] clipPolygon = editor.GetBiomeClipPolygon(bounds); // clip, convert to vector2 Vector2[] polygonXY = nodes.Select(item => new Vector2(item.x, item.z)).ToArray(); Vector2[] clippedPoints = SutherlandHodgman.GetIntersectedPolygon(polygonXY, clipPolygon); if (clippedPoints == null || clippedPoints.Length < 3) { return; } // convert back to vector3 nodes = clippedPoints.Select(item => new Vector3(item.x, 0, item.y)).ToList(); // create the biome mask using the nodes CreateBiomeMaskArea(gameObjectName, maskName, bounds, nodes); }
/// <summary> /// Get a list of all polygons per point. /// This contains duplicate edges if multiple points share the same edge. /// The polygons are clipped at the canvas bounds. /// Basically this is the method to use. It gives you all Voronoi polygons exactly on the Canvas /// </summary> /// <returns></returns> private List <Vector[]> GetAllClippedVoronoiPolygons() { // bounding box Vector[] clipPolygon = GetClipPolygon(clipAtBoundsMargin); List <Vector[]> allVoronoiPolygons = new List <Vector[]>(); foreach (Vector[] polygon in graph.GetAllVoronoiPolygons()) { Vector[] intersectedPolygon = SutherlandHodgman.GetIntersectedPolygon(polygon, clipPolygon); allVoronoiPolygons.Add(intersectedPolygon); } return(allVoronoiPolygons); }
/// <summary> /// Clip the specified polygon at the canvas bounds. Consider a margin. /// </summary> /// <param name="points"></param> /// <returns></returns> private Vector[] ClipAtBounds(Vector[] currentPolygon) { // ensure there are data if (currentPolygon.Length == 0) { return(currentPolygon); } // clip polygon, bounding box Vector[] clipPolygon = GetClipPolygon(clipAtBoundsMargin); Vector[] intersectedPolygon = SutherlandHodgman.GetIntersectedPolygon(currentPolygon, clipPolygon); return(intersectedPolygon); }
private void IntersectAllPolygonsWithAnimationPolygon() { Polygons.RemoveAll(x => x.Points.Count < 3); for (int i = 0; i < Polygons.Count; i++) { if (Polygons[i] == animationPolygon) { continue; } var intersectedPoints = SutherlandHodgman.GetIntersectedPolygon(Polygons[i].Points.ToArray(), animationPolygon.Points.ToArray()); Polygon intersectedPolygn = new Polygon(_drawing); intersectedPolygn.AddVerticle(intersectedPoints); intersectedPolygn.FillingColor = Polygons[i].FillingColor; intersectedPolygn.FillEnabled = true; intersectedPolygn.DrawPolygon(true); } }
private void CompositionTargetOnRendering(object sender, EventArgs e) { if (!_running) { return; } foreach (var colorPolygon in _generated) { colorPolygon.Clear(); colorPolygon.Vertices = colorPolygon.Vertices.Select(v => new Vertex(0, new Point(v.Point.X + _speed, v.Point.Y))).ToList(); // colorPolygon.ShiftInterior(_speed); colorPolygon.Shift.X += _speed; } if (_clearCounter++ % 60 == 0) { ClearGenerated(); } ClearClippedOnScreen(); _clipped.Clear(); foreach (var subject in _polygons) { foreach (var clip in _generated) { var temppoly = SutherlandHodgman.GetIntersectedPolygon( subject.Vertices.Select(p => new System.Windows.Point(p.Point.X, p.Point.Y)).ToArray(), clip.Vertices.Select(p => new System.Windows.Point(p.Point.X, p.Point.Y)).ToArray()); if (temppoly.Length != 0) { var poly = temppoly.Select(p => new Point((int)p.X, (int)p.Y)).ToList(); var filling = ScanLine.PolygonFilling(poly, out Color[,] xd); var polygon = new ClippedPolygon(filling, clip); _clipped.Add(polygon); } } } RedrawAll(); }
/// <summary> /// 切割矢量并输出成bitmap /// </summary> /// <param name="featureCollection"></param> /// <param name="outputDir"></param> public void Output(FeatureCollection featureCollection, string outputDir) { var _tileDictionary = _vectorPyramid.TileDictionary; int _tileSize = _vectorPyramid.Projection.TileSize; // foreach (int zoom in _tileDictionary.Keys) { var tileCollection = _tileDictionary[zoom]; foreach (var tile in tileCollection) { try { // Bitmap bmp = new Bitmap(_tileSize, _tileSize); Graphics g = Graphics.FromImage(bmp); Pen pen = new Pen(Color.Black, 3); // for (int i = 0; i < featureCollection.Count; i++) { IFeature f = featureCollection[i]; //点 if (f.Geometry.OgcGeometryType == OgcGeometryType.Point) { Coordinate point = f.Geometry.Coordinate; if (tile.Bound.PointInPolygon(point)) { //2.2.1 计算点的像素坐标 Coordinate pixel = _vectorPyramid.Projection.LatlngToPoint(point, zoom); // double deltaX = pixel.X / _tileSize - tile.X; double deltaY = pixel.Y / _tileSize - tile.Y; int x = Convert.ToInt32(deltaX * _tileSize); int y = Convert.ToInt32(deltaY * _tileSize); g.DrawLine(pen, x, x, x, y); } continue; } //线 else if (f.Geometry.OgcGeometryType == OgcGeometryType.LineString) { //2.1瓦片裁剪道路 List <Coordinate> clipLine = CohenSutherland.GetIntersectedPolyline(f.Geometry.Coordinates, tile.Bound); if (clipLine.Count == 0) { continue; } int x0 = -1000, y0 = -1000; //2.2 绘制clipLine foreach (Coordinate point in clipLine) { //2.2.1 计算点的像素坐标 Coordinate pixel = _vectorPyramid.Projection.LatlngToPoint(point, zoom); // double deltaX = pixel.X / _tileSize - tile.X; double deltaY = pixel.Y / _tileSize - tile.Y; int x = Convert.ToInt32(deltaX * _tileSize); int y = Convert.ToInt32(deltaY * _tileSize); if (x0 == -1000 && y0 == -1000) { x0 = x; y0 = y; continue; } else { g.DrawLine(pen, x0, y0, x, y); x0 = x; y0 = y; } } } //面 else if (f.Geometry.OgcGeometryType == OgcGeometryType.Polygon) { List <Coordinate> clipPolygon = SutherlandHodgman.GetIntersectedPolygon(f.Geometry.Coordinates, tile.Bound); if (clipPolygon.Count < 3) { continue; } int x0 = -1000, y0 = -1000; //2.2 绘制clipLine foreach (Coordinate point in clipPolygon) { //2.2.1 计算点的像素坐标 Coordinate pixel = _vectorPyramid.Projection.LatlngToPoint(point, zoom); // double deltaX = pixel.X / _tileSize - tile.X; double deltaY = pixel.Y / _tileSize - tile.Y; int x = Convert.ToInt32(deltaX * _tileSize); int y = Convert.ToInt32(deltaY * _tileSize); if (x0 == -1000 && y0 == -1000) { x0 = x; y0 = y; continue; } else { g.DrawLine(pen, x0, y0, x, y); x0 = x; y0 = y; } } } } //2.3 保存bmp到指定路径 if (!System.IO.Directory.Exists(outputDir + @"\" + zoom)) { System.IO.Directory.CreateDirectory(outputDir + @"\" + zoom); } //根据geometry id存储,获取不到geometry的id,所以只能自定内部序号 bmp.Save(outputDir + @"\" + zoom + @"\" + tile.X + "_" + tile.Y + "_" + tile.Z + ".jpg"); } catch { continue; } } } }