Skip to content
Snippets Groups Projects
common.py 35.6 KiB
Newer Older
  • Learn to ignore specific revisions
  • Nutti's avatar
    Nutti committed
    
        # make enter/exit pair
        subject_uvs.reset()
        subject_entering = []
        subject_exiting = []
        clip_entering = []
        clip_exiting = []
        intersect_uv_list = []
        while True:
            pair = get_intersection_pair(intersections, subject_uvs.get())
            if pair:
                sub = subject_uvs.get(1) - subject_uvs.get(-1)
                inter = pair[1] - pair[0]
                cross = sub.x * inter.y - inter.x * sub.y
                if cross < 0:
                    subject_entering.append(subject_uvs.get())
                    clip_exiting.append(subject_uvs.get())
                else:
                    subject_exiting.append(subject_uvs.get())
                    clip_entering.append(subject_uvs.get())
                intersect_uv_list.append(subject_uvs.get())
    
            subject_uvs.next()
            if subject_uvs.get() == subject_uvs.head():
                break
    
        debug_print("===== Enter List =====")
        debug_print(clip_entering)
        debug_print(subject_entering)
        debug_print("===== Exit List =====")
        debug_print(clip_exiting)
        debug_print(subject_exiting)
    
        # for now, can't handle the situation when fulfill all below conditions
        #        * two faces have common edge
        #        * each face is intersected
        #        * Show Mode is "Part"
        #       so for now, ignore this situation
        if len(subject_entering) != len(subject_exiting):
            if mode == 'FACE':
                polygons = [subject_uvs.as_list()]
                return True, polygons
            return False, None
    
        def traverse(current_list, entering, exiting, p, current, other_list):
            result = current_list.find(current)
            if not result:
                return None
            if result != current:
                print("Internal Error")
                return None
    
            if not exiting:
                print("Internal Error: No exiting UV")
                return None
    
    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
    
    
    
    nutti's avatar
    nutti committed
    def get_overlapped_uv_info(bm_list, faces_list, uv_layer_list, mode):
    
    Nutti's avatar
    Nutti committed
        # at first, check island overlapped
    
    nutti's avatar
    nutti committed
        isl = []
        for bm, uv_layer, faces in zip(bm_list, uv_layer_list, faces_list):
            info = get_island_info_from_faces(bm, faces, uv_layer)
            isl.extend([(i, uv_layer) for i in info])
    
    
    Nutti's avatar
    Nutti committed
        overlapped_isl_pairs = []
    
    nutti's avatar
    nutti committed
        overlapped_uv_layer_pairs = []
        for i, (i1, uv_layer_1) in enumerate(isl):
            for i2, uv_layer_2 in isl[i + 1:]:
    
    Nutti's avatar
    Nutti committed
                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])
    
    nutti's avatar
    nutti committed
                overlapped_uv_layer_pairs.append([uv_layer_1, uv_layer_2])
    
    Nutti's avatar
    Nutti committed
    
        # next, check polygon overlapped
        overlapped_uvs = []
    
    nutti's avatar
    nutti committed
        for oip, uvlp in zip(overlapped_isl_pairs, overlapped_uv_layer_pairs):
    
    Nutti's avatar
    Nutti committed
            for clip in oip[0]["faces"]:
                f_clip = clip["face"]
    
    nutti's avatar
    nutti committed
                clip_uvs = [l[uvlp[0]].uv.copy() for l in f_clip.loops]
    
    Nutti's avatar
    Nutti committed
                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
    
    
    nutti's avatar
    nutti committed
                    subject_uvs = [l[uvlp[1]].uv.copy() for l in f_subject.loops]
    
    Nutti's avatar
    Nutti committed
                    # slow operation, apply Weiler-Atherton cliping algorithm
    
    nutti's avatar
    nutti committed
                    result, polygons = __do_weiler_atherton_cliping(clip_uvs,
                                                                    subject_uvs,
                                                                    mode)
    
    Nutti's avatar
    Nutti committed
                    if result:
                        overlapped_uvs.append({"clip_face": f_clip,
                                               "subject_face": f_subject,
    
    nutti's avatar
    nutti committed
                                               "clip_uv_layer": uvlp[0],
                                               "subject_uv_layer": uvlp[1],
    
    Nutti's avatar
    Nutti committed
                                               "subject_uvs": subject_uvs,
                                               "polygons": polygons})
    
        return overlapped_uvs
    
    
    
    nutti's avatar
    nutti committed
    def get_flipped_uv_info(faces_list, uv_layer_list):
    
    Nutti's avatar
    Nutti committed
        flipped_uvs = []
    
    nutti's avatar
    nutti committed
        for faces, uv_layer in zip(faces_list, uv_layer_list):
            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,
                                        "uv_layer": uv_layer,
                                        "uvs": uvs,
                                        "polygons": [polygon.as_list()]})
    
    Nutti's avatar
    Nutti committed
    
        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