コード例 #1
0
    def __init__(self, polygon: geometry_utils.Polygon):
        """Create a new LMark. If the points don't form a valid LMark, raises a
        WrongShapeError."""
        if len(polygon) != 6:
            raise WrongShapeError("Incorrect number of points.")

        if not geometry_utils.all_approx_square(polygon):
            raise WrongShapeError("Corners are not square.")

        clockwise_polygon = geometry_utils.polygon_to_clockwise(polygon)
        side_lengths = geometry_utils.calc_side_lengths(clockwise_polygon)
        longest_sides_indexes = list_utils.find_greatest_value_indexes(
            side_lengths, n=2)

        if not list_utils.is_adjacent_indexes(side_lengths,
                                              *longest_sides_indexes):
            raise WrongShapeError("Longest sides are not adjacent.")

        # The longest sides should be about twice the length of the other sides
        unit_lengths = math_utils.divide_some(side_lengths,
                                              longest_sides_indexes, 2)
        if not math_utils.all_approx_equal(unit_lengths):
            raise WrongShapeError(
                "Longest sides are not twice the length of the other sides.")

        self.polygon = list_utils.arrange_index_to_first(
            clockwise_polygon,
            list_utils.determine_which_is_next(polygon,
                                               *longest_sides_indexes))
        self.unit_length = math_utils.mean(unit_lengths)
コード例 #2
0
def get_corner(square: Polygon, corner: Corner) -> Point:
    """Gets the point representing the given corner of the square. Square should
    be pretty close to vertical - horizontal. """
    xs = [p.x for p in square]
    highest_xs = sorted(list_utils.find_greatest_value_indexes(xs, 2))
    side_points = [
        p for i, p in enumerate(square)
        if (corner.value[1] == 1 and i in highest_xs) or (
            corner.value[1] == 0 and i not in highest_xs)
    ]
    side_ys = [p.y for p in side_points]
    [highest_y] = list_utils.find_greatest_value_indexes(side_ys, 1)
    corner_point = side_points[highest_y] if (
        corner.value[0] == 0) else side_points[list_utils.next_index(
            side_points, highest_y)]
    return corner_point
コード例 #3
0
ファイル: grid_reading.py プロジェクト: iansan5653/open-mcr
def calculate_bubble_fill_threshold(
        field_fill_percents: tp.Dict[grid_info.Field, tp.List[tp.List[float]]],
        answer_fill_percents: tp.List[tp.List[tp.List[float]]],
        form_variant: grid_info.FormVariant,
        save_path: tp.Optional[pathlib.PurePath] = None) -> float:
    """Dynamically calculate the threshold to use for determining if a bubble is
    filled or unfilled.

    This is a time consuming function so it should only be called once per page.
    It works by getting the fill percentages of all the values in all the
    fields, sorting them, and finding the largest increase in fill percent
    between all the values in the highest 1/4 (assumes all the filled bubbles
    are less than 1/4 of all the bubbles). It then returns the average of the
    two values that were subtracted to make the largest increase.

    If `save_path` is provided, saves debugging data to this location as
    "threshold_values.txt".
    """
    fill_percents_lists = list(
        field_fill_percents.values()) + answer_fill_percents
    fill_percents = [np.array(l).flatten() for l in fill_percents_lists]
    sorted_and_flattened = np.sort(np.concatenate(fill_percents))
    last_chunk = sorted_and_flattened[-round(sorted_and_flattened.size / 5):]
    differences = [
        last_chunk[i + 1] - last_chunk[i] for i in range(last_chunk.size - 1)
    ]
    biggest_diff_index = list_utils.find_greatest_value_indexes(
        differences, 1)[0]
    result = (last_chunk[biggest_diff_index] +
              last_chunk[biggest_diff_index + 1]) / 2
    if save_path:
        with open(str(save_path / "threshold_values.txt"), "w+") as file:
            file.writelines([str(sorted_and_flattened), "\n\n", str(result)])
    return result
コード例 #4
0
def calculate_bubble_fill_threshold(
        grid: Grid,
        save_path: typing.Optional[pathlib.PurePath] = None) -> float:
    """Dynamically calculate the threshold to use for determining if a bubble is
    filled or unfilled.

    This is a time consuming function so it should only be called once per page.
    It works by getting the fill percentages of all the values in all the name
    fields, sorting them, and finding the largest increase in fill percent
    between all the values in the highest 1/4 (assumes all the filled bubbles
    are less than 1/4 of all the bubbles). It then returns the average of the
    two values that were subtracted to make the largest increase.

    If `save_path` is provided, saves debugging data to this location as
    "threshold_values.txt".
    """
    # This function makes the following assumptions:
    # A. At least one bubble in first, last, or middle name is full.
    # B. Less than a tenth of the bubbles in first, last, and middle name are
    #    full. For this to be untrue, an average of 2.6 bubbles per field would
    #    be filled which doesn't make sense for anyone to do.
    # If these are not true, the values for the entire sheet will be useless.
    # However, these are most likely safe assumptions.
    fill_percents = [
        np.array(
            get_group_from_info(grid_info.fields_info[field],
                                grid).get_all_fill_percents()).flatten()
        for field in grid_info.Field
    ]
    sorted_and_flattened = np.sort(np.concatenate(fill_percents))
    last_chunk = sorted_and_flattened[-round(sorted_and_flattened.size / 10):]
    differences = [
        last_chunk[i + 1] - last_chunk[i] for i in range(last_chunk.size - 1)
    ]
    biggest_diff_index = list_utils.find_greatest_value_indexes(
        differences, 1)[0]
    result = (last_chunk[biggest_diff_index] +
              last_chunk[biggest_diff_index + 1]) / 2
    if save_path:
        with open(str(save_path / "threshold_values.txt"), "w+") as file:
            file.writelines([str(sorted_and_flattened), "\n\n", str(result)])
    return result