/// <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); }
private void TestSutherlandHodgman(List <MyVector2> poly, List <MyVector2> clipPoly) { //Normalize to range 0-1 //We have to use all data to normalize List <MyVector2> allPoints = new List <MyVector2>(); allPoints.AddRange(poly); allPoints.AddRange(clipPoly); Normalizer2 normalizer = new Normalizer2(allPoints); List <MyVector2> poly_normalized = normalizer.Normalize(poly); List <MyVector2> clipPoly_normalized = normalizer.Normalize(clipPoly); //Main algorithm List <MyVector2> polygonAfterClipping_Normalized = SutherlandHodgman.ClipPolygon(poly_normalized, clipPoly_normalized); //UnNormalize List <MyVector2> polygonAfterClipping = normalizer.UnNormalize(polygonAfterClipping_Normalized); //2d to 3d List <Vector3> polygonAfterClipping3D = new List <Vector3>(); foreach (MyVector2 v in polygonAfterClipping) { polygonAfterClipping3D.Add(v.ToVector3()); } //Display DisplayPolygon(polygonAfterClipping3D, Color.red); }
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(); }
/// <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); }
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); }
public void ClipRectangle() { ReadOnlySpan <Point> subject = stackalloc Point[4] { new Point(0d, 0d), new Point(2d, 0d), new Point(2d, 2d), new Point(0d, 2d) }; ReadOnlySpan <Point> clipping = stackalloc Point[4] { new Point(1d, 0d), new Point(3d, 0d), new Point(3d, 2d), new Point(1d, 2d) }; ReadOnlySpan <Point> result = stackalloc Point[4] { new Point(1d, 2d), new Point(2d, 2d), new Point(2d, 0d), new Point(1d, 0d) }; var intersect = new SutherlandHodgman().GetIntersectedPolygon(subject, clipping).Span; Assert.Equal(result.Length, intersect.Length); for (var i = 0; i < intersect.Length; i++) { Assert.Equal(result[i], intersect[i]); } }
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(); }
public ActionResult Post([FromBody] PolygonClipRequestPayload request) { if (string.IsNullOrEmpty(request.SourcePolygon)) { return(BadRequest("Missing source polygon")); } if (string.IsNullOrEmpty(request.ClipPolygon)) { return(BadRequest("Missing clipping polygon")); } var source = PathMarkupConverter.Convert(request.SourcePolygon); var clip = PathMarkupConverter.Convert(request.ClipPolygon); var result = new SutherlandHodgman().GetIntersectedPolygon(source, clip); return(Ok(new PolygonResultPayload { ResultPolygon = PathMarkupConverter.Convert(result) })); }
private void TestSutherlandHodgman(List <MyVector2> poly, List <MyVector2> clipPoly) { //Normalize to range 0-1 //We have to use all data to normalize List <MyVector2> allPoints = new List <MyVector2>(); allPoints.AddRange(poly); allPoints.AddRange(clipPoly); AABB2 normalizingBox = new AABB2(allPoints); float dMax = HelpMethods.CalculateDMax(normalizingBox); List <MyVector2> poly_normalized = HelpMethods.Normalize(poly, normalizingBox, dMax); List <MyVector2> clipPoly_normalized = HelpMethods.Normalize(clipPoly, normalizingBox, dMax); //Main algorithm List <MyVector2> polygonAfterClipping_Normalized = SutherlandHodgman.ClipPolygon(poly_normalized, clipPoly_normalized); //UnNormalize List <MyVector2> polygonAfterClipping = HelpMethods.UnNormalize(polygonAfterClipping_Normalized, normalizingBox, dMax); //2d to 3d List <Vector3> polygonAfterClipping3D = new List <Vector3>(); foreach (MyVector2 v in polygonAfterClipping) { polygonAfterClipping3D.Add(v.ToVector3()); } //Display DisplayPolygon(polygonAfterClipping3D, Color.red); }
//////////////////////////////////////////////////////////////////////// //--------------------------------- REVISIONS -------------------------- // Date Name Tracking # Description // --------- ------------------- ------------- ------------------ // 18JUN2009 James Shen Initial Creation //////////////////////////////////////////////////////////////////////// /** * * @param mapDirection * @param X * @param Y * @param Width * @param Height */ private void DrawRouteImage(MapDirection mapDirection, int x, int y, int width, int height) { if (!_routeDrawWaypointOnly) { _sutherlandHodgman = new SutherlandHodgman(_screenBounds); ArrayList polyline = new ArrayList(); int minLevel = NeedShowLevel(mapDirection.Polyline.NumLevels, GetZoom()); for (int i = 0; i < mapDirection.Polyline.GetVertexCount(); i++) { int level = mapDirection.Polyline.GetLevel(i); if (level >= minLevel) { polyline.Add(mapDirection.Polyline.GetVertex(i)); } } ArrayList clippedPts = _sutherlandHodgman.ClipPline(polyline); GeoPoint newPt1; GeoPoint newPt2; GeoPoint drawPt1 = new GeoPoint(0, 0), drawPt2 = new GeoPoint(0, 0); const int steps = 1; int numOfTiles = MAP_TILE_WIDTH / _mapDrawingTileWidth; Rectangle drawArea = new Rectangle(); Rectangle intersectRect = new Rectangle(0, 0, width, height); int xIndex; for (xIndex = 0; xIndex < numOfTiles; xIndex++) { int yIndex; for (yIndex = 0; yIndex < numOfTiles; yIndex++) { bool hasPt1 = false; GeoLatLng pt1 = null; _routeGraphics2D.Clear(Color.White); drawArea.X = xIndex * _mapDrawingTileWidth; drawArea.Y = yIndex * _mapDrawingTileWidth; drawArea.Width = drawArea.Height = _mapDrawingTileWidth; drawArea = intersectRect.Intersection(drawArea); int totalPointSize = clippedPts.Count; if (!drawArea.IsEmpty()) { _routeGraphics2D.SetClip(0, 0, drawArea.Width, drawArea.Height); try { for (int j = 0; j < totalPointSize; j += steps) { GeoLatLng pt = (GeoLatLng)clippedPts[j]; int level = minLevel; if (hasPt1 == false) { if (level >= minLevel) { { { hasPt1 = true; pt1 = pt; continue; } } } } if (hasPt1) { if (level >= minLevel) { GeoLatLng pt2 = pt; newPt1 = FromLatLngToMapPixel(pt1); newPt2 = FromLatLngToMapPixel(pt2); newPt1.X -= x + xIndex * _mapDrawingTileWidth; newPt1.Y -= y + yIndex * _mapDrawingTileWidth; newPt2.X -= x + xIndex * _mapDrawingTileWidth; newPt2.Y -= y + yIndex * _mapDrawingTileWidth; drawPt1.X = (int)newPt1.X; drawPt1.Y = (int)newPt1.Y; drawPt2.X = (int)newPt2.X; drawPt2.Y = (int)newPt2.Y; if ((drawPt1.Distance(drawPt2) > 0)) { _routeGraphics2D.DrawLine(RoutePen, (int)drawPt1.X, (int)drawPt1.Y, (int)drawPt2.X, (int)drawPt2.Y); pt1 = pt2; if (_readListener != null) { _readListener.readProgress(j, totalPointSize); } } } } } } catch (Exception) { } } _routeGraphics.DrawRGB(_routeGraphics2D.GetRGB(), 0, _mapDrawingTileWidth, xIndex * _mapDrawingTileWidth, yIndex * _mapDrawingTileWidth, _mapDrawingTileWidth, _mapDrawingTileWidth, true); } } } else { _routeGraphics.SetColor(TRANSPARENCY); _routeGraphics.FillRect(0, 0, MAP_TILE_WIDTH, MAP_TILE_WIDTH); } }
/// <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; } } } }