Пример #1
0
        public static bool Build(Medial_branch root, Topographer topo, List <Point2F> samples, double general_tolerance, Point2F startpoint, double min_dist_to_wall, bool startpoint_is_a_hint)
        {
            List <Line2F> medial_axis_segments = get_medial_axis_segments(topo, samples, general_tolerance);

            Logger.log("analyzing segments");

            Segpool pool = new Segpool(medial_axis_segments.Count, general_tolerance);

            Point2F tree_start;

            if (startpoint.IsUndefined)
            {
                tree_start = prepare_segments_w_auto_startpoint(topo, medial_axis_segments, pool, min_dist_to_wall);
            }
            else if (startpoint_is_a_hint)
            {
                tree_start = prepare_segments_w_hinted_starpoint(topo, medial_axis_segments, pool, min_dist_to_wall, general_tolerance, startpoint);
            }
            else
            {
                tree_start = prepare_segments_w_manual_starpoint(topo, medial_axis_segments, pool, min_dist_to_wall, general_tolerance, startpoint);
            }

            if (tree_start.IsUndefined)
            {
                Logger.warn("failed to choose tree start point");
                return(false);
            }

            Logger.log("done analyzing segments");
            Logger.log("got {0} hashes", pool.N_hashes);

            if (!(startpoint.IsUndefined || startpoint_is_a_hint))
            {
                root.Add_point(startpoint);
            }

            root.Add_point(tree_start);

            build_tree(root, pool, general_tolerance);
            return(true);
        }
Пример #2
0
        private static void build_branch(Medial_branch me, Segpool pool, double min_branch_len)
        {
            Point2F        running_end = me.End;
            List <Point2F> followers;

            while (true)
            {
                followers = pool.Pull_follow_points(running_end);

                if (followers.Count != 1)
                {
                    break;
                }

                running_end = followers[0];
                me.Add_point(running_end);         // continuation
            }

            if (followers.Count == 0)
            {
                return;                       // end of branch, go out
            }
            foreach (Point2F pt in followers)
            {
                Medial_branch b = me.Spawn_child();
                b.Add_point(running_end);
                b.Add_point(pt);
                build_branch(b, pool, min_branch_len);

                if (b.Deep_distance > min_branch_len) // attach only 'long enough'
                {
                    b.Attach_to_parent();
                }
                else
                {
                    Logger.log("skipping short branch");
                }
            }
            me.Postprocess();
        }
Пример #3
0
 private static void build_tree(Medial_branch root, Segpool pool, double min_branch_len)
 {
     // this will build tree recursively
     build_branch(root, pool, min_branch_len);
 }
Пример #4
0
        // with the manual startpoint, which is a hint
        private static Point2F prepare_segments_w_hinted_starpoint(Topographer topo, List <Line2F> segments, Segpool pool, double min_dist_to_wall, double general_tolerance, Point2F startpoint)
        {
            // same as automatic, but seek the segment with the closest end to startpoint
            double  min_dist   = double.MaxValue;
            Point2F tree_start = Point2F.Undefined;

            foreach (Line2F seg in segments)
            {
                double r1 = topo.Get_dist_to_wall(seg.p1);
                double r2 = topo.Get_dist_to_wall(seg.p2);

                if (r1 >= min_dist_to_wall)
                {
                    pool.Add(seg, false);
                    double dist = startpoint.DistanceTo(seg.p1);
                    if (dist < min_dist)
                    {
                        min_dist   = dist;
                        tree_start = seg.p1;
                    }
                }
                if (r2 >= min_dist_to_wall)
                {
                    pool.Add(seg, true);
                    double dist = startpoint.DistanceTo(seg.p2);
                    if (dist < min_dist)
                    {
                        min_dist   = dist;
                        tree_start = seg.p2;
                    }
                }
            }

            return(tree_start);
        }
Пример #5
0
        // with the manual startpoint
        private static Point2F prepare_segments_w_manual_starpoint(Topographer topo, List <Line2F> segments, Segpool pool, double min_dist_to_wall, double general_tolerance, Point2F startpoint)
        {
            // same as automatic, but seek the segment with the closest end to startpoint
            if (!topo.Is_line_inside_region(new Line2F(startpoint, startpoint), general_tolerance))
            {
                Logger.warn("startpoint is outside the pocket");
                return(Point2F.Undefined);
            }

            if (topo.Get_dist_to_wall(startpoint) < min_dist_to_wall)
            {
                Logger.warn("startpoint radius < tool radius");
                return(Point2F.Undefined);
            }

            double  min_dist   = double.MaxValue;
            Point2F tree_start = Point2F.Undefined;

            foreach (Line2F seg in segments)
            {
                double r1 = topo.Get_dist_to_wall(seg.p1);
                double r2 = topo.Get_dist_to_wall(seg.p2);

                if (r1 >= min_dist_to_wall)
                {
                    pool.Add(seg, false);
                    double dist = startpoint.DistanceTo(seg.p1);
                    if (dist < min_dist && topo.Is_line_inside_region(new Line2F(startpoint, seg.p1), general_tolerance))
                    {
                        min_dist   = dist;
                        tree_start = seg.p1;
                    }
                }
                if (r2 >= min_dist_to_wall)
                {
                    pool.Add(seg, true);
                    double dist = startpoint.DistanceTo(seg.p2);
                    if (dist < min_dist && topo.Is_line_inside_region(new Line2F(startpoint, seg.p2), general_tolerance))
                    {
                        min_dist   = dist;
                        tree_start = seg.p2;
                    }
                }
            }

            return(tree_start);
        }
Пример #6
0
        private static Point2F prepare_segments_w_auto_startpoint(Topographer topo, List <Line2F> segments, Segpool pool, double min_dist_to_wall)
        {
            // segments are analyzed for mic radius from both ends. passed segmens are inserted in segpool
            // hashed by one or both endpoints. if endpoint is not hashed, segment wouldn't be followed
            // from that side, preventing formation of bad tree.
            // segments are connected later in a greedy fashion, hopefully forming a medial axis covering all
            // pocket.
            // start segment is the one with the largest mic

            double  max_r      = double.MinValue;
            Point2F tree_start = Point2F.Undefined;

            foreach (Line2F seg in segments)
            {
                double r1 = topo.Get_dist_to_wall(seg.p1);
                double r2 = topo.Get_dist_to_wall(seg.p2);

                if (r1 >= min_dist_to_wall)
                {
                    pool.Add(seg, false);
                    if (r1 > max_r)
                    {
                        max_r      = r1;
                        tree_start = seg.p1;
                    }
                }
                if (r2 >= min_dist_to_wall)
                {
                    pool.Add(seg, true);
                    if (r2 > max_r)
                    {
                        max_r      = r2;
                        tree_start = seg.p2;
                    }
                }
            }

            return(tree_start);
        }