//first takes any incorrect (concave, self-intersecting, unclosed etc) manually entered border of cluster and //trasforms it to intermediate convex hull IH. //then depending on coordinates of badges in IH builds final convex hull FH (containing badges fuzzily inside IH). void buildInitialCluster(Polygon drawnBorder) { if (drawnBorder.Points.Count <= 1) { //cannot build convex hull from 1 point return; } //create corrected input polygon var convexHull = ConvexHull.FindConvexPolygon(drawnBorder.Points.ToList()).ToList(); //no badges, cluster is not created var contents = GetBadgeList(convexHull); if (contents.Count() == 0) { return; } _offset = new Point(0, 0); //initial building of cluster always changes contents for (int i = 0; i < contents.Count(); i++) { contents[i].SetBusy(); _onClusterUncluster(GetCluster(), contents[i], true, i == contents.Count() - 1); } }
//given list of badges which comprise cluster, we build convex hull and then smooth border public void PlayBuildSmoothCurve() { var BadgesCorners = ShapeUtils.buildBadgeCorners(_endpoint.GetClusterables()); if (BadgesCorners.Count <= 2) { //rebuilding cluster after unclustering last badge. //the cluster will soon be removed (by server event) return; } convexHull.Points = ConvexHull.FindConvexPolygon(BadgesCorners); var convexPoints = convexHull.Points; _topLeft = new Point(convexPoints.Min(pt => pt.X), convexPoints.Min(pt => pt.Y)); //build bezier curve var pathFigure = new PathFigure(); Point[] firstControlPoints = null; Point[] secondControlPoints = null; ovp.BezierSpline.GetCurveControlPoints(convexPoints.ToArray(), out firstControlPoints, out secondControlPoints); pathFigure.StartPoint = convexPoints.ElementAt(0); for (int i = 0; i < convexPoints.Count - 1; i++) { pathFigure.Segments.Add(new BezierSegment(firstControlPoints[i], secondControlPoints[i], convexPoints.ElementAt(i + 1), true)); } //closing segment if (convexPoints.Count == 3) { Point[] firstLast = new Point[] { convexPoints[2], convexPoints[0], convexPoints[1] }; ovp.BezierSpline.GetCurveControlPoints(firstLast, out firstControlPoints, out secondControlPoints); pathFigure.Segments.Add(new BezierSegment(firstControlPoints.First(), secondControlPoints.First(), convexPoints.First(), true)); } else { Point[] firstLast = new Point[] { convexPoints[convexPoints.Count - 2], convexPoints[convexPoints.Count - 1], convexPoints[0], convexPoints[1] }; ovp.BezierSpline.GetCurveControlPoints(firstLast, out firstControlPoints, out secondControlPoints); pathFigure.Segments.Add(new BezierSegment(firstControlPoints[1], secondControlPoints[1], convexPoints[0], true)); } var pathGeom = new PathGeometry(); pathGeom.Figures.Add(pathFigure); bezierBorder.Data = pathGeom; _offset = new Point(0, 0); if (_endpoint.GetClusterables().Count() > 0) { clusterCreated = true; if (cleanerTimer != null) { cleanerTimer.Stop(); cleanerTimer = null; } } SetBounds(); }