public static List <Line> setConcaveHull(double concavity, int scaleFactor) { /* Run setConvHull before! * Concavity is a value used to restrict the concave angles * It can go from -1 (no concavity) to 1 (extreme concavity) * Avoid concavity == 1 if you don't want 0ยบ angles * */ bool aLineWasDividedInTheIteration; hull_concave_edges.AddRange(hull_edges); do { aLineWasDividedInTheIteration = false; for (int linePositionInHull = 0; linePositionInHull < hull_concave_edges.Count && !aLineWasDividedInTheIteration; linePositionInHull++) { Line line = hull_concave_edges[linePositionInHull]; List <Node> nearbyPoints = HullFunctions.getNearbyPoints(line, unused_nodes, scaleFactor); List <Line> dividedLine = HullFunctions.getDividedLine(line, nearbyPoints, hull_concave_edges, concavity); if (dividedLine.Count > 0) // Line divided! { aLineWasDividedInTheIteration = true; unused_nodes.Remove(unused_nodes.Where(n => n.id == dividedLine[0].nodes[1].id).FirstOrDefault()); // Middlepoint no longer free hull_concave_edges.AddRange(dividedLine); hull_concave_edges.RemoveAt(linePositionInHull); // Divided line no longer exists } } hull_concave_edges = hull_concave_edges.OrderByDescending(a => Line.getLength(a.nodes[0], a.nodes[1])).ToList(); } while (aLineWasDividedInTheIteration); return(hull_concave_edges); }
public static void setConcaveHull(decimal concavity, int scaleFactor, bool isSquareGrid) { /* Run setConvHull before! * Concavity is a value used to restrict the concave angles * it can go from -1 to 1 (it wont crash if you go further) * */ Hull.scaleFactor = scaleFactor; hull_concave_edges = new List <Line>(hull_edges.OrderByDescending(a => Line.getLength(a.nodes[0], a.nodes[1])).ToList()); Line selected_edge; List <Line> aux = new List <Line>();; int list_original_size; int count = 0; bool listIsModified = false; do { listIsModified = false; count = 0; list_original_size = hull_concave_edges.Count; while (count < list_original_size) { selected_edge = hull_concave_edges[0]; hull_concave_edges.RemoveAt(0); aux = new List <Line>(); if (!selected_edge.isChecked) { List <Node> nearby_points = HullFunctions.getNearbyPoints(selected_edge, unused_nodes, Hull.scaleFactor); aux.AddRange(HullFunctions.setConcave(selected_edge, nearby_points, hull_concave_edges, concavity, isSquareGrid)); listIsModified = listIsModified || (aux.Count > 1); if (aux.Count > 1) { foreach (Node node in aux[0].nodes) { if (unused_nodes.Find(a => a.id == node.id) != null) { unused_nodes.Remove(unused_nodes.Where(a => a.id == node.id).First()); } } } else { aux[0].isChecked = true; } } else { aux.Add(selected_edge); } hull_concave_edges.AddRange(aux); count++; } hull_concave_edges = hull_concave_edges.OrderByDescending(a => Line.getLength(a.nodes[0], a.nodes[1])).ToList(); list_original_size = hull_concave_edges.Count; } while (listIsModified); }
public static bool tangentToHull(Line line_treated, Node node, decimal cos1, decimal cos2, List <Line> concave_hull) { /* A new middlepoint could (rarely) make a segment that's tangent to the hull. * This method detects these situations * I suggest turning this method of if you are not using square grids or if you have a high dot density * */ bool isTangent = false; decimal current_cos1; decimal current_cos2; double edge_length; List <int> nodes_searched = new List <int>(); Line line; Node node_in_hull; int count_line = 0; int count_node = 0; edge_length = Line.getLength(node, line_treated.nodes[0]) + Line.getLength(node, line_treated.nodes[1]); while (!isTangent && count_line < concave_hull.Count) { line = concave_hull[count_line]; while (!isTangent && count_node < 2) { node_in_hull = line.nodes[count_node]; if (!nodes_searched.Contains(node_in_hull.id)) { if (node_in_hull.id != line_treated.nodes[0].id && node_in_hull.id != line_treated.nodes[1].id) { current_cos1 = getCos(node_in_hull, line_treated.nodes[0], line_treated.nodes[1]); current_cos2 = getCos(node_in_hull, line_treated.nodes[1], line_treated.nodes[0]); if (current_cos1 == cos1 || current_cos2 == cos2) { isTangent = (Line.getLength(node_in_hull, line_treated.nodes[0]) + Line.getLength(node_in_hull, line_treated.nodes[1]) < edge_length); } } } nodes_searched.Add(node_in_hull.id); count_node++; } count_node = 0; count_line++; } return(isTangent); }