コード例 #1
0
ファイル: __init__.py プロジェクト: wagnerf42/Jimn
 def _compute_toplevel_tour(self):
     """
     find cycle starting at origin and
     passing through one point of each toplevel pocket.
     return list of 2d points.
     this will also sort all children by order of visit of the tour
     and change each cycle starting point as the visited point.
     """
     origin = Point([0, 0])
     graph = Graph()
     children = {}  # record to which child each point belongs
     for child in self.children:
         end = nearest_point(child.old_pocket, origin)
         children[end] = child
         graph.add_edge_between(origin, child.old_pocket,
                                Segment([origin, end]))
     for child1, child2 in combinations(self.children, 2):
         start, end = nearest_points(child1.old_pocket, child2.old_pocket)
         children[start] = child1
         children[end] = child2
         graph.add_edge_between(child1.old_pocket, child2.old_pocket,
                                Segment([start, end]))
     cycle = tsp(graph)
     tour = self._convert_cycle_to_tour(cycle, children, origin)
     return tour
コード例 #2
0
    def remove_loops(self):
        """
        iterate on edge, remove small loops (un-millable zones).
        """
        left = []
        for segment1, arc, segment2 in self.arcs():
            if arc.reversed_direction:
                i = segment1.intersection_with_segment(segment2)
                if i is None:
                    left.append(arc.endpoints[0])
                    left.append(arc)
                    left.append(arc.endpoints[1])
                else:
                    left.append(i)
            else:
                left.append(arc.endpoints[0])
                left.append(arc)
                left.append(arc.endpoints[1])

        simpler_edge = []
        position = left[-1]
        for part in left:
            if isinstance(part, Arc):
                simpler_edge.append(part)
                position = part.endpoints[1]
            else:
                if position != part:
                    simpler_edge.append(Segment([position, part]))

                position = part
        self.edge = simpler_edge
コード例 #3
0
    def _odd_segments_on_line(self, line_hash):
        """
        sweeps through line of aligned segments.
        keeping the ones we want
        """
        # associate #starting - #ending segments to each point
        self.counters = defaultdict(int)
        segments = self.lines[line_hash]
        self._compute_points_and_counters(segments)
        # now iterate through each point
        # we record on how many segments we currently are
        previously_on = 0
        # we record where interesting segment started
        previous_point = None

        odd_segments = []

        for point in self.sorted_points:
            now_on = previously_on
            now_on += self.counters[point]
            if previously_on % 2 == 1:
                if now_on % 2 == 0:
                    odd_segments.append(Segment([previous_point, point]))
            else:
                previous_point = point

            previously_on = now_on

        if __debug__:
            if is_module_debugged(__name__):
                tycat(self.segments, odd_segments)
        return odd_segments
コード例 #4
0
    def join_raw_segments(self, raw_segments):
        """
        reconnect all parallel segments.
        """

        for neighbouring_tuples in all_two_elements(raw_segments):
            first_segment, second_segment = [p[0] for p in neighbouring_tuples]
            end = first_segment.endpoints[1]
            start = second_segment.endpoints[0]
            if end.is_almost(start):
                first_segment = Segment([first_segment.endpoints[0], start])
            else:
                # original point connecting the original segments
                center_point = neighbouring_tuples[0][1].endpoints[1]
                # add arc
                try:
                    binding = Arc(self.radius, [end, start], center_point)
                    binding.adjust_center()
                    binding.correct_endpoints_order()
                except:
                    print("failed joining segments")
                    tycat(self.polygon, center_point, first_segment,
                          second_segment)
                    raise

                self.edge.append(first_segment)
                self.edge.append(binding)

        if __debug__:
            if is_module_debugged(__name__):
                print("joined segments")
                tycat(self.polygon, self.edge)
コード例 #5
0
    def tycat(self):
        """
        graphical display for debugging
        """
        # compute intersections
        intersections = []
        for small_intersections in self.intersections.values():
            intersections.extend(small_intersections)
        intersections = list(set(intersections))

        # compute current vertical line
        bbox = BoundingBox.empty_box(2)
        for path in self.paths:
            bbox.update(path.get_bounding_box())
        ymin, ymax = bbox.limits(1)
        height = ymax - ymin
        line_y_min = ymin - height / 20
        line_y_max = ymax + height / 20
        current_x = self.current_point.coordinates[0]
        vertical_line = Segment(
            [Point([current_x, line_y_min]),
             Point([current_x, line_y_max])])

        # display figure
        tycat(self.paths, intersections, [self.current_point, vertical_line],
              *self.crossed_paths)

        print(list(self.key(p) for p in self.crossed_paths))
コード例 #6
0
 def complete_graph(cls, points):
     """
     builds complete graph from set of points.
     """
     graph = cls()
     for points in combinations(points, 2):
         graph.add_edge(Segment(points))
     return graph
コード例 #7
0
def overlapping_run(size):
    """
    one run, of given size.
    return time taken.
    """
    paths = [
        Segment([Point([0, i]), Point([1, i + 0.5])]) for i in range(size)
    ]
    return run(paths)
コード例 #8
0
ファイル: __init__.py プロジェクト: wagnerf42/Jimn
    def _merge_toplevel(self, toplevel_tour):
        """
        tour all points in tour.
        at each point (except first)
        we go down in subtree and back up to continue touring.
        """
        final_paths = []
        for i in range(len(toplevel_tour) - 1):
            start = toplevel_tour[i]
            end = toplevel_tour[i + 1]
            if not start.is_almost(end):
                final_paths.append(Segment([start, end]))
            final_paths.append(VerticalPath(-1))
            final_paths.extend(self.children[i].content.elementary_paths)
            final_paths.append(VerticalPath(1))

        # back to origin
        final_paths.append(Segment([toplevel_tour[-1], toplevel_tour[0]]))
        return Path(final_paths)
コード例 #9
0
def non_overlapping_run(size):
    """
    one run, of given size.
    return time taken.
    """
    paths = [
        Segment([Point([2 * i, 0]), Point([2 * i + 1, 0])])
        for i in range(size)
    ]
    return run(paths)
コード例 #10
0
ファイル: internal_edges.py プロジェクト: wagnerf42/Jimn
def _horizontal_edges(aligned_vertices):
    """
    iterate through all horizontal edges (containing segments)
    between given horizontally aligned vertices.
    """
    for index in range(len(aligned_vertices) - 1):
        vertices = [
            aligned_vertices[index],
            aligned_vertices[(index + 1) % len(aligned_vertices)]
        ]
        objects = [v.bound_object for v in vertices]
        yield Edge(*vertices, real_path=Segment(objects))
コード例 #11
0
 def horizontal_intersections_at(self, intersecting_y, xmin, xmax):
     """
     intersections with horizontal line at given y.
     returns array of points.
     """
     segment = Segment(
         [Point([xmin, intersecting_y]),
          Point([xmax, intersecting_y])])
     intersections = self.intersections_with_segment(segment)
     intersections = [
         Point([i.get_x(), intersecting_y]) for i in intersections
     ]
     return intersections
コード例 #12
0
def quadratic(size):
    """
    n^2 brute force algorithm
    """
    paths = [
        Segment([Point([2 * i, 0]), Point([2 * i + 1, 0])])
        for i in range(size)
    ]
    start_time = clock()
    for p_1, p_2 in combinations(paths, r=2):
        p_1.intersections_with(p_2)
    end_time = clock()
    return end_time - start_time
コード例 #13
0
ファイル: path_merger.py プロジェクト: wagnerf42/Jimn
def merge_path(outer_path, inner_path, position):
    """
    merge inner path inside outer path at given position.
    Note that since positions contains array indices you
    need to merge starting from last path.
    """
    paths = outer_path.elementary_paths
    outer_point = position.outer_position.point
    inner_point = position.inner_position.point
    if __debug__:
        if is_module_debugged(__name__):
            print("merging at", position.outer_position.index)
            tycat(outer_path, inner_path,
                  position.outer_position.elementary_path)
    arrival_path = paths[position.outer_position.index]
    assert arrival_path.contains(outer_point), "no merging here"

    sub_path = []
    before, after = arrival_path.split_around(outer_point)
    if before is not None:
        sub_path.append(before)

    if not outer_point.is_almost(inner_point):
        sub_path.append(Segment([outer_point, inner_point]))

    sub_path.append(VerticalPath(-1))
    sub_path.extend(inner_path.elementary_paths)
    sub_path.append(VerticalPath(1))

    if not outer_point.is_almost(inner_point):
        sub_path.append(Segment([inner_point, outer_point]))

    if after is not None:
        sub_path.append(after)

    paths[position.outer_position.index:position.outer_position.index] = \
        sub_path
    outer_path.set_elementary_paths(paths)
コード例 #14
0
def border_2d(stl_model, margin):
    """
    return 2d enclosing (starting at origin) for given model and margin.
    """
    # build four points
    xmin, ymin = 0, 0
    xmax, ymax = stl_model.dimensions(margin)
    points = []
    points.append(Point([xmin, ymin]))
    points.append(Point([xmin, ymax]))
    points.append(Point([xmax, ymax]))
    points.append(Point([xmax, ymin]))

    return [Segment([p, q]) for p, q in all_two_elements(points)]
コード例 #15
0
 def displace(cls, path, distance):
     """
     displace given path by given distance on outer side.
     """
     if isinstance(path, Segment):
         parallel_segment = path.parallel_segment(distance, -1)
         hashed_segment = Segment(
             [ROUNDER2D.hash_point(p) for p in parallel_segment.endpoints])
         return cls(hashed_segment, path)
     else:
         if path.reversed_direction:
             new_radius = 2 * path.radius
             new_points = [p * 2 - path.center for p in path.endpoints]
             hashed_points = [ROUNDER2D.hash_point(p) for p in new_points]
             inflated_path = Arc(new_radius, hashed_points, path.center,
                                 True)
         else:
             inflated_path = ROUNDER2D.hash_point(path.center)
         return cls(inflated_path, path)
コード例 #16
0
    def project(self, point):
        """
        find where point on stored path projects itself on origin.
        """
        if isinstance(self.origin, Point):
            result = self.origin
        elif isinstance(self.origin, Segment):
            result = self.origin.point_projection(point)
        else:
            intersections = self.origin.intersections_with_segment(
                Segment([self.origin.center, point]))
            assert len(intersections) == 1
            result = intersections[0]

        if __debug__:
            if is_module_debugged(__name__):
                print("project from envelope back to original path")
                tycat(self.path, self.origin, point, result)

        return result
コード例 #17
0
def test(seconds=None):
    """
    intersect a bunch of random segments and display result.
    """
    display = True
    if seconds is None:
        display = False
        seconds = clock()

    seed(float(seconds))

    paths = [
        Segment([
            ROUNDER2D.hash_point(Point([random(), random()])),
            ROUNDER2D.hash_point(Point([random(), random()]))
        ]) for _ in range(10)
    ]
    for _ in range(0):
        center = ROUNDER2D.hash_point(Point([random(), random()]))
        radius = 0
        while radius < 0.02:
            radius = random() / 4
        points = [
            center + ROUNDER2D.hash_point(Point([cos(a), sin(a)]) * radius)
            for a in (random() * 10, random() * 10)
        ]

        paths.append(Arc(radius, points, center).correct_endpoints_order())

    # print(",\n        ".join([str(s) for s in paths]))
    if display:
        tycat(paths)
    try:
        intersections = compute_intersections(paths)
    except:
        print("seed", seconds)
        tycat(paths)
        raise

    intersections.append(paths)
    return intersections
コード例 #18
0
    def offset(self):
        """
        extend polygon's edges by moving parallel to them
        and reconnect pieces.
        """
        raw_segments = []
        for segment in self.polygon.segments():
            parallel_segment = segment.parallel_segment(self.radius)
            hashed_segment = Segment(
                [ROUNDER2D.hash_point(p) for p in parallel_segment.endpoints])
            raw_segments.append((hashed_segment, segment))

        if __debug__:
            if is_module_debugged(__name__):
                print("unjoined raw segments")
                segments = [t[0] for t in raw_segments]
                tycat(self.polygon, segments)

        try:
            self.join_raw_segments(raw_segments)
        except:
            print("failed joining edges in offsetter")
            segments = [t[0] for t in raw_segments]
            tycat(self.polygon, segments)
            raise

        try:
            # for performance reasons we can remove now the small loop pockets
            # created by sharp angles.
            # they would be removed anyway later on but it is much better
            # to remove them now so they do not appear in the O(n^2) algorithm
            # used later on
            self.remove_loops()
        except:
            print("failed removing loops")
            tycat(self.polygon, self.edge)
            raise

        return self.edge
コード例 #19
0
ファイル: tsp.py プロジェクト: wagnerf42/Jimn
def _skip_seen_vertices(cycle):
    """
    change cycle so that we do not pass twice at same vertex
    (except for completing the cycle).
    achieves that by shortcutting to next point using a segment.
    CAREFUL: vertices are not updated in the process.
    """
    seen_vertices = {}
    start = cycle[0].vertices[0]
    current_vertex = start
    seen_vertices[current_vertex] = True
    resulting_cycle = []
    for edge in cycle:
        next_vertex = edge.vertices[1]
        if next_vertex not in seen_vertices:
            if current_vertex == edge.vertices[0]:
                resulting_cycle.append(edge)
            else:
                objects = [
                    v.bound_object for v in (current_vertex, next_vertex)
                ]
                if isinstance(objects[0], Point) \
                        and isinstance(objects[0], Point):
                    point1, point2 = objects
                else:
                    point1, point2 = nearest_points(objects[0], objects[1])

                resulting_cycle.append(
                    Edge(current_vertex, next_vertex, Segment([point1, point2]))
                )
            current_vertex = next_vertex
            seen_vertices[current_vertex] = True

    # add last segment to go back at start
    resulting_cycle.append(cycle[-1])
    return resulting_cycle
コード例 #20
0
#!/usr/bin/env python3

from jimn.point import Point
from jimn.segment import Segment
from jimn.displayable import tycat

print("**************************")
print("*testing segments overlap*")
print("**************************")

print("non aligned")

s1 = Segment([Point([0, 3]), Point([0, 6])])
s2 = Segment([Point([1, 3]), Point([0, 6])])
tycat(s1, s2)

assert not s1.overlaps(s2)

print("aligned, no overlap")

s1 = Segment([Point([0, 0]), Point([3, 3])])
s2 = Segment([Point([4, 4]), Point([6, 6])])
tycat(s1, s2)

assert not s1.overlaps(s2)

print("overlap, no one disappears")

s1 = Segment([Point([0, 0]), Point([3, 3])])
s2 = Segment([Point([2, 2]), Point([6, 6])])
tycat(s1, s2)
コード例 #21
0
#!/usr/bin/env python3

from jimn.point import Point
from jimn.segment import Segment
from jimn.polygon import Polygon
from jimn.pocket import Pocket
from jimn.envelope import Envelope
from jimn.arc import Arc
from jimn.displayable import tycat
from jimn.displayable import tycat_start, tycat_end

print("testing intersection")

s = Polygon.square(0, 0, 8)
s = s.orient(False)
path_in = Pocket(list(s.segments()))

path_out = Segment([Point([-3, 3]), Point([12, 5])])

e1 = Envelope(path_in, 1)
e2 = Envelope(path_out, 1)

tycat(e1, e2)

points = e2.junction_points(e1)
tycat(e1, e2, points)
コード例 #22
0
 def segments(self):
     """
     iterate through all segments.
     """
     for points in all_two_elements(self.points):
         yield Segment(points)
コード例 #23
0
ファイル: angles.py プロジェクト: wagnerf42/Jimn
#!/usr/bin/env python3

from jimn.point import Point
from jimn.segment import Segment
from jimn.displayable import tycat
from math import cos, sin, pi

points = [
    Point([cos((i * 2 * pi) / 8), sin(i * (2 * pi) / 8)]) for i in range(8)
]
tycat(*points)
origin = Point([0, 0])
for p in points:
    print(origin.angle_with(p))

for p in points:
    s = Segment([origin, p])
    tycat(points, s)
    print("key angle is:", s.key_angle())
    print("********************")
コード例 #24
0
arcs = (Arc(3, [Point([1, 2]), Point([4, -1])],
            Point([4,
                   2])), Arc(3, [Point([3, 3]), Point([6, 0])], Point([6, 3])),
        Arc(3, [Point([4, 3]), Point([7, 0])],
            Point([7,
                   3])), Arc(2, [Point([0, 1]), Point([2, 3])], Point([0, 3])))

print("*** trying intersection with arcs ***")
for i, a in enumerate(arcs):
    print(labels[i])
    intersection = a1.intersections_with_arc(a)
    tycat(a1, a, intersection)

segments = (
    Segment([Point([-1, 2]), Point([3, 1])]),
    Segment([Point([3.2, 3]), Point([0.2, 0])]),
    Segment([Point([5.2, 3]), Point([2.2, 0])]),
    Segment([Point([-1, 0]), Point([3, 0])]),
)
s_labels = (
    "single intersection",
    "double intersection",
    "no intersection",
    "tangent",
)
print("*** trying intersection with segments ***")
for i, s in enumerate(segments):
    print(s_labels[i])
    intersections = a1.intersections_with_segment(s)
    tycat(a1, s, intersections)
コード例 #25
0
def main():
    s1 = Segment([Point([0, 0]), Point([1, 1])])
    s2 = Segment([Point([0, 0]), Point([1, -1])])
    s3 = Segment([Point([0.5, -2]), Point([0.5, 2])])
    compute_intersections([s1, s2, s3])
コード例 #26
0
ファイル: pockets_inclusions.py プロジェクト: wagnerf42/Jimn
including = Polygon.square(-1, 4, 3)
including_pocket = Pocket(list(including.segments()))

not_including = [
    Point([-2.0, 3.0]),
    Point([-2.0, 2.0]),
    Point([9.0, 2.0]),
    Point([9.0, 10.0]),
    Point([-2.0, 10.0]),
    Point([-2.0, 9.0]),
    Point([8.0, 9.0]),
    Point([8.0, 3.0]),
]

not_including_pocket = Pocket(
    [Segment([a, b]) for a, b in all_two_elements(not_including)])

vertically_aligned = [
    Point([-1, 3.5]),
    Point([2, 3.5]),
    Point([4, 5.5]),
    Point([2, 7.5]),
    Point([-1, 7.5]),
    Point([-4, 5.5]),
]

va_pocket = Pocket(
    [Segment([a, b]) for a, b in all_two_elements(vertically_aligned)])

if tested_pocket.is_included_in(including_pocket):
    print("red is included in green (ok)")