// this should be more efficient when there are holes... public double DistanceSquared(Vector2d p, out int iHoleIndex, out int iNearSeg, out double fNearSegT) { iNearSeg = iHoleIndex = -1; fNearSegT = double.MaxValue; double dist = outer.DistanceSquared(p, out iNearSeg, out fNearSegT); for (int i = 0; i < Holes.Count; ++i) { int seg; double segt; double holedist = Holes[i].DistanceSquared(p, out seg, out segt); if (holedist < dist) { dist = holedist; iHoleIndex = i; iNearSeg = seg; fNearSegT = segt; } } return(dist); }
/// <summary> /// Constrained laplacian smoothing of input polygon, alpha X iterations. /// vertices are only allowed to move at most max_dist from constraint /// if bAllowShrink == false, vertices are kept outside input polygon /// if bAllowGrow == false, vertices are kept inside input polygon /// /// max_dist is measured from vertex[i] to original_vertex[i], unless /// you set bPerVertexDistances = false, then distance to original polygon /// is used (which is much more expensive) /// /// [TODO] this is pretty hacky...could be better in lots of ways... /// /// </summary> public static void LaplacianSmoothConstrained(Polygon2d poly, double alpha, int iterations, double max_dist, bool bAllowShrink, bool bAllowGrow, bool bPerVertexDistances = true) { Polygon2d origPoly = new Polygon2d(poly); int N = poly.VertexCount; Vector2d[] newV = new Vector2d[poly.VertexCount]; double max_dist_sqr = max_dist * max_dist; double beta = 1.0 - alpha; for (int ii = 0; ii < iterations; ++ii) { for (int i = 0; i < N; ++i) { Vector2d curpos = poly[i]; Vector2d smoothpos = (poly[(i + N - 1) % N] + poly[(i + 1) % N]) * 0.5; bool do_smooth = true; if (bAllowShrink == false || bAllowGrow == false) { bool is_inside = origPoly.Contains(smoothpos); if (is_inside == true) { do_smooth = bAllowShrink; } else { do_smooth = bAllowGrow; } } // [RMS] this is old code...I think not correct? //bool contained = true; //if (bAllowShrink == false || bAllowGrow == false) // contained = origPoly.Contains(smoothpos); //bool do_smooth = true; //if (bAllowShrink && contained == false) // do_smooth = false; //if (bAllowGrow && contained == true) // do_smooth = false; if (do_smooth) { Vector2d newpos = beta * curpos + alpha * smoothpos; if (bPerVertexDistances) { while (origPoly[i].DistanceSquared(newpos) > max_dist_sqr) { newpos = (newpos + curpos) * 0.5; } } else { while (origPoly.DistanceSquared(newpos) > max_dist_sqr) { newpos = (newpos + curpos) * 0.5; } } newV[i] = newpos; } else { newV[i] = curpos; } } for (int i = 0; i < N; ++i) { poly[i] = newV[i]; } } }