Esempio n. 1
0
def try_close(outline2, distance_th):
    if len(outline2) <= 2 or outline2.is_closed:
        return outline2
    elif distance_squared(outline2[0], outline2[-1]) <= distance_th:
        return Outline2(points=outline2.points[:-1],
                        inside_map=outline2.inside_map)
    else:
        return outline2
Esempio n. 2
0
def merge_outlines(outline2_a, outline2_b, distance_sq_th):
    assert isinstance(outline2_a, Outline2)
    assert len(outline2_a) > 0
    assert isinstance(outline2_b, Outline2)
    assert len(outline2_b) > 0
    assert distance_squared(outline2_a[-1], outline2_b[0]) < distance_sq_th

    return Outline2(points=outline2_a.points[:-1] + outline2_b.points,
                    inside_map=outline2_a.inside_map + outline2_b.inside_map)
Esempio n. 3
0
def make_consistent(outline2):
    if not outline2.is_closed:
        return outline2
    min_pt_idx = min(range(len(outline2)), key=lambda i: outline2.points[i])
    return Outline2(points=_rotate_first(outline2.points, min_pt_idx),
                    inside_map=_rotate_first(outline2.inside_map, min_pt_idx))
Esempio n. 4
0
def compute_profile2(drawing,
                     distance_th=0.5,
                     has_rot_axis=True,
                     regular_y=False):
    assert BASE_INNER_PROFILE_ID in drawing
    assert BASE_OUTER_PROFILE_ID in drawing
    if has_rot_axis and ROTATION_AXIS_ID not in drawing:
        raise DrawingError('Missing rotation axis')

    outlines = []
    # To gaurantee consistant output, always sort the outlines by name
    for name, old_outline in sorted(drawing.outlines.items()):
        assert isinstance(old_outline, Outline)
        if 'handle' in name or name == ROTATION_AXIS_ID:
            continue
        elif 'fracture' in name:
            o_type = Outline2.NEITHER
        elif 'inner_base' in name:
            o_type = Outline2.INSIDE
        elif 'outer_base' in name:
            o_type = Outline2.OUTSIDE
        else:
            raise DrawingError('Unknown segment %s' % name)
        outlines.append(
            Outline2(points=old_outline.points,
                     inside_map=[o_type] * (len(old_outline) - 1)))

    # Try merging all pairs of outlines that can be merged
    while len(outlines) > 1:
        n = len(outlines)

        # Find the pair of outlines with the lowest merge distance
        i, j = min(((i, j) for i in range(n) for j in range(i + 1, n)),
                   key=lambda pair: min_merge_distance(outlines[pair[0]],
                                                       outlines[pair[1]]))

        outline_a = outlines[i]
        outline_b = outlines[j]
        combined = try_combine_outlines(outline_a, outline_b, distance_th)

        if combined:
            # Delete larger index first
            del outlines[j]
            del outlines[i]
            outlines.append(combined)
        else:
            break

    for i, o in enumerate(outlines):
        outlines[i] = try_close(o, distance_th)

    if len(outlines) > 1:
        import ipdb
        ipdb.set_trace()

    if has_rot_axis:
        axis_x = drawing[ROTATION_AXIS_ID].points[0][0]
    else:
        axis_x = 0

    y_mul = +1 if regular_y else -1

    # Now:
    # 1. Align all outlines so that rotation axis is at X = 0.
    # 2. Try close every outline if it's already a tight circle
    outlines = [
        try_close(o.transform(lambda p: (p[0] - axis_x, y_mul * p[1])),
                  distance_th) for o in outlines
    ]

    # Finally return the result
    return Profile2(outlines=outlines)