Skip to content
Snippets Groups Projects
common.py 33.1 KiB
Newer Older
  • Learn to ignore specific revisions
  • Nutti's avatar
    Nutti committed
            # enter
            if entering.count(current) >= 1:
                entering.remove(current)
    
            current_list.find_and_next(current)
            current = current_list.get()
    
    
            prev = None
            error = False
    
    Nutti's avatar
    Nutti committed
            while exiting.count(current) == 0:
                p.append(current.copy())
                current_list.find_and_next(current)
                current = current_list.get()
    
                if prev == current:
                    error = True
                    break
                prev = current
    
            if error:
                print("Internal Error: Infinite loop")
                return None
    
    Nutti's avatar
    Nutti committed
    
            # exit
            p.append(current.copy())
            exiting.remove(current)
    
            other_list.find_and_set(current)
            return other_list.get()
    
        # Traverse
        polygons = []
        current_uv_list = subject_uvs
        other_uv_list = clip_uvs
        current_entering = subject_entering
        current_exiting = subject_exiting
    
        poly = []
        current_uv = current_entering[0]
    
        while True:
            current_uv = traverse(current_uv_list, current_entering,
                                  current_exiting, poly, current_uv, other_uv_list)
    
    
            if current_uv is None:
                break
    
    
    Nutti's avatar
    Nutti committed
            if current_uv_list == subject_uvs:
                current_uv_list = clip_uvs
                other_uv_list = subject_uvs
                current_entering = clip_entering
                current_exiting = clip_exiting
                debug_print("-- Next: Clip --")
            else:
                current_uv_list = subject_uvs
                other_uv_list = clip_uvs
                current_entering = subject_entering
                current_exiting = subject_exiting
                debug_print("-- Next: Subject --")
    
            debug_print(clip_entering)
            debug_print(clip_exiting)
            debug_print(subject_entering)
            debug_print(subject_exiting)
    
            if not clip_entering and not clip_exiting \
                    and not subject_entering and not subject_exiting:
                break
    
        polygons.append(poly)
    
        debug_print("===== Polygons Overlapped Partially =====")
        debug_print(polygons)
    
        return True, polygons
    
    
    def __is_polygon_flipped(points):
        area = 0.0
        for i in range(len(points)):
            uv1 = points.get(i)
            uv2 = points.get(i + 1)
            a = uv1.x * uv2.y - uv1.y * uv2.x
            area = area + a
        if area < 0:
            # clock-wise
            return True
        return False
    
    
    def __is_point_in_polygon(point, subject_points):
        count = 0
        for i in range(len(subject_points)):
            uv_start1 = subject_points.get(i)
            uv_end1 = subject_points.get(i + 1)
            uv_start2 = point
            uv_end2 = Vector((1000000.0, point.y))
            intersected, _ = __is_segment_intersect(uv_start1, uv_end1,
                                                    uv_start2, uv_end2)
            if intersected:
                count = count + 1
    
        return count % 2
    
    
    def __is_points_in_polygon(points, subject_points):
        for i in range(len(points)):
            internal = __is_point_in_polygon(points.get(i), subject_points)
            if not internal:
                return False
    
        return True
    
    
    def get_overlapped_uv_info(bm, faces, uv_layer, mode):
        # at first, check island overlapped
        isl = get_island_info_from_faces(bm, faces, uv_layer)
        overlapped_isl_pairs = []
        for i, i1 in enumerate(isl):
            for i2 in isl[i + 1:]:
                if (i1["max"].x < i2["min"].x) or (i2["max"].x < i1["min"].x) or \
                   (i1["max"].y < i2["min"].y) or (i2["max"].y < i1["min"].y):
                    continue
                overlapped_isl_pairs.append([i1, i2])
    
        # next, check polygon overlapped
        overlapped_uvs = []
        for oip in overlapped_isl_pairs:
            for clip in oip[0]["faces"]:
                f_clip = clip["face"]
                for subject in oip[1]["faces"]:
                    f_subject = subject["face"]
    
                    # fast operation, apply bounding box algorithm
                    if (clip["max_uv"].x < subject["min_uv"].x) or \
                       (subject["max_uv"].x < clip["min_uv"].x) or \
                       (clip["max_uv"].y < subject["min_uv"].y) or \
                       (subject["max_uv"].y < clip["min_uv"].y):
                        continue
    
                    # slow operation, apply Weiler-Atherton cliping algorithm
                    result, polygons = __do_weiler_atherton_cliping(f_clip,
                                                                    f_subject,
                                                                    uv_layer, mode)
                    if result:
                        subject_uvs = [l[uv_layer].uv.copy()
                                       for l in f_subject.loops]
                        overlapped_uvs.append({"clip_face": f_clip,
                                               "subject_face": f_subject,
                                               "subject_uvs": subject_uvs,
                                               "polygons": polygons})
    
        return overlapped_uvs
    
    
    def get_flipped_uv_info(faces, uv_layer):
        flipped_uvs = []
        for f in faces:
            polygon = RingBuffer([l[uv_layer].uv.copy() for l in f.loops])
            if __is_polygon_flipped(polygon):
                uvs = [l[uv_layer].uv.copy() for l in f.loops]
                flipped_uvs.append({"face": f, "uvs": uvs,
                                    "polygons": [polygon.as_list()]})
    
        return flipped_uvs
    
    
    def __is_polygon_same(points1, points2):
        if len(points1) != len(points2):
            return False
    
        pts1 = points1.as_list()
        pts2 = points2.as_list()
    
        for p1 in pts1:
            for p2 in pts2:
                diff = p2 - p1
                if diff.length < 0.0000001:
                    pts2.remove(p2)
                    break
            else:
                return False
    
        return True