private List <TopologyIntersection> FindAllIntersections(Face2D target, List <ICuttableEdge> edges2cut) { Intersector intersector = new Intersector(); List <TopologyIntersection> res_list = new List <TopologyIntersection>(); for (int loop_idx = 0; loop_idx < target.Loops.Count; ++loop_idx) { var loop = target.Loops[loop_idx]; for (int target_edge_idx = 0; target_edge_idx < loop.Count; ++target_edge_idx) { List <TopologyIntersection> sorted_is = new List <TopologyIntersection>(); for (int tool_edge_idx = 0; tool_edge_idx < edges2cut.Count; ++tool_edge_idx) { var intersections = intersector.Intersect(loop[target_edge_idx], edges2cut[tool_edge_idx]); foreach (var intersection in intersections) { TopologyIntersection res = new TopologyIntersection( loop_idx, target_edge_idx, tool_edge_idx, intersection); sorted_is.Add(res); } } sorted_is.Sort(new TopologyIntersectionCompare_ByTarget()); res_list.AddRange(sorted_is); } } return(res_list); }
List <ICuttableEdge> MakeLoop(TopologyIntersection start_from, BopMap map) { var res = new List <ICuttableEdge>(); TopologyIntersection last = start_from; int deadloop = 0; do { if (deadloop++ > DeadloopMaxIters) { Debug.LogError("deadloop"); throw new UnityException("deadloop"); } LoopSegment seg = MakeLoopSegment(last, map); last = seg.end; res.AddRange(seg.edges); } while (last != start_from); // TODO: filter degen loops float total_len = 0; foreach (var edge in res) { total_len += edge.GetLen(); } // strict filter. such loops are useless for camera return(res.Count == 0 || total_len < 1.0e-2 ? null : res); }
LoopSegment MakeLoopSegment(TopologyIntersection start_from, BopMap map) { if (start_from.ToolEdgeEnters) { return(MakeLoopSegment(start_from, map, true, new EdgeIter(map.tool_edges, start_from.ToolEdgeIdx))); } else { return(MakeLoopSegment(start_from, map, false, new EdgeIter(map.target[start_from.LoopIdx], start_from.TargetEdgeIdx))); } }
private ICuttableEdge CutEdgeWithIntersections(ICuttableEdge edge, bool is_tool, TopologyIntersection start, TopologyIntersection end) { ICuttableEdge res = edge; if (start != null) { res = res.Cut((is_tool ? start.Geom.cut_param : start.Geom.face_edge_param).ToFloat, false); } if (end != null) { float cut_param_end = (is_tool ? end.Geom.cut_param : end.Geom.face_edge_param).ToFloat; if (start != null) { EvalRes end_pt = edge.Eval(cut_param_end); cut_param_end = res.GetClosestPoint(end_pt.pt).normalized_t; } res = res.Cut(cut_param_end, true); } return(res); }
private List <TopologyIntersection> FilterIntersections(IList <TopologyIntersection> intersections, Face2D target, IList <ICuttableEdge> tool) { // TODO: kill it with fire! No, but seriously, refactor this. // check all face loop intersections for topological consistency. input should already be sorted. if (intersections.Count == 0) { return(new List <TopologyIntersection>()); } IDictionary <ICuttableEdge, List <TopologyIntersection> > edge2intersections = new Dictionary <ICuttableEdge, List <TopologyIntersection> >(); int last_loop_idx = intersections[0].LoopIdx; bool last_enters = intersections[0].ToolEdgeEnters; bool first_in_loop_enters = last_enters; /* * { * int cur_loop_first_edge_idx = 0; * * // 1. Go through every loop and move tool param if ambigious * for ( int i = 1; i <= intersections.Count; ++i ) * { * TopologyIntersection intersection = null; * TopologyIntersection prev = intersections[i - 1]; * * if ( i == intersections.Count ) * { * intersection = intersections[cur_loop_first_edge_idx]; * } * else * { * intersection = intersections[i]; * int cur_loop = intersection.LoopIdx; * * if ( cur_loop != last_loop_idx ) * { * intersection = intersections[cur_loop_first_edge_idx]; * cur_loop_first_edge_idx = i; * last_loop_idx = cur_loop; * } * else * { * intersection = intersections[i]; * } * } * if ( ( intersection.ToolEdgeIdx == prev.ToolEdgeIdx ) * && ( ( prev.TargetEdgeIdx + 1 ) % target.Loops[prev.LoopIdx].Count == intersection.TargetEdgeIdx ) * && ( prev.ToolEdgeEnters != intersection.ToolEdgeEnters ) ) * { * ICuttableEdge first_edge = target.Loops[prev.LoopIdx][prev.TargetEdgeIdx]; * ICuttableEdge second_edge = target.Loops[intersection.LoopIdx][intersection.TargetEdgeIdx]; * bool tool_is_order = Utils.TestLeftHemiplane( second_edge.Eval( 0 ).dir, first_edge.Eval( 1 ).dir ) == prev.ToolEdgeEnters; * if ( tool_is_order != ( prev.Geom.cut_param < intersection.Geom.cut_param ) ) * { * float temp = prev.Geom.cut_param; * prev.SetCutParam( intersection.Geom.cut_param ); * intersection.SetCutParam( temp ); * } * } * } * }*/ last_loop_idx = intersections[0].LoopIdx; last_enters = intersections[0].ToolEdgeEnters; first_in_loop_enters = last_enters; edge2intersections[tool[intersections[0].ToolEdgeIdx]] = new List <TopologyIntersection> { intersections[0] }; for (int i = 1; i < intersections.Count; ++i) { TopologyIntersection intersection = intersections[i]; int cur_loop = intersection.LoopIdx; bool tool_edge_enters = intersection.ToolEdgeEnters; if (cur_loop != last_loop_idx) { if (tool_edge_enters == first_in_loop_enters) // inconsistent { intersection.Valid = false; } first_in_loop_enters = tool_edge_enters; last_loop_idx = cur_loop; } else if (tool_edge_enters == last_enters) // inconsistent { intersection.Valid = false; } if (intersection.Valid) { if (!edge2intersections.ContainsKey(tool[intersection.ToolEdgeIdx])) { edge2intersections[tool[intersection.ToolEdgeIdx]] = new List <TopologyIntersection>(); } edge2intersections[tool[intersection.ToolEdgeIdx]].Add(intersection); } last_enters = tool_edge_enters; } // check last loop if (last_enters == first_in_loop_enters) { intersections[intersections.Count - 1].Valid = false; } // now filter by tool bool first_init = true; TopologyIntersection first_tool_is = null; foreach (var edge in tool) { if (!edge2intersections.ContainsKey(edge)) { continue; } edge2intersections[edge].Sort(new TopologyIntersectionCompare_ByTool()); foreach (var intersection in edge2intersections[edge]) { if (!intersection.Valid) { continue; } if (first_init) { first_in_loop_enters = last_enters = intersection.ToolEdgeEnters; first_init = false; first_tool_is = intersection; } else { bool tool_enters = intersection.ToolEdgeEnters; if (tool_enters == last_enters) // inconsistent { intersection.Valid = false; } last_enters = tool_enters; } } } if (last_enters == first_in_loop_enters && first_tool_is != null) { first_tool_is.Valid = false; } var res = new List <TopologyIntersection> { Capacity = intersections.Count }; foreach (var i in intersections) { if (i.Valid) { res.Add(i); } } return(res); }
LoopSegment MakeLoopSegment(TopologyIntersection start_from, BopMap map, bool tool_seg, IEnumerator <ICuttableEdge> edge_iterator) { LoopSegment seg; seg.start = null; var seg_edges = new List <ICuttableEdge>(); seg.end = null; edge_iterator.Reset(); int deadloop = 0; do { var cur_edge = edge_iterator.Current; var cur_edge_intersections = map.edge2intersections[cur_edge]; TopologyIntersection start = null; TopologyIntersection end = null; if (cur_edge_intersections != null && cur_edge_intersections.Count > 0) { if (cur_edge_intersections.Contains(start_from) && seg.start == null) { seg.start = start_from; start = start_from; } if (!(start != null && cur_edge_intersections.Count == 1)) { bool stop_at_next_is = start == null; foreach (var intersection in cur_edge_intersections) { if (stop_at_next_is) { end = intersection; break; } else { stop_at_next_is = start.Equals(intersection); } } } } if (start != null || end != null) { cur_edge = CutEdgeWithIntersections(cur_edge, tool_seg, start, end); } if (cur_edge.GetLen() > 1.0e-3) { seg_edges.Add(cur_edge); } if (end != null) { seg.end = end; break; } if (deadloop++ > DeadloopMaxIters) { Debug.Log("deadloop"); throw new UnityException("deadloop"); } } while (edge_iterator.MoveNext()); seg.edges = seg_edges; seg.start.Valid = false; seg.end.Valid = false; return(seg); }