def calc_vert_tangents(self):
        """self.loop_tris.bmのBORDERフラグが立っている頂点のtangentを計算。
        :return: キーがBMVert, 値が[tangent, tangent(min), tangent(max)]の
            辞書を返す。tangentはself.align_edgesが偽の場合に、tangent(min)と
            tangent(max)はself.align_edgesが真の場合に利用する。
            fallbackはVector((0, 0, 0))とする。
        :rtype: dict[BMVert, list[Vector]]
        """
        WIRE = self.WIRE
        BORDER = self.BORDER

        loop_tris = self.loop_tris
        vert_dict = loop_tris.vert_dict()

        vert_tangents = {}  # eve: Vector

        for eve in loop_tris.bm.verts:
            if not loop_tris.vflags[eve] & BORDER:
                continue

            # eveに接続する二頂点(vert_next, vert_prev)を求める
            eve_next, eve_prev = [eed.other_vert(eve) for eed in eve.link_edges if loop_tris.eflags[eed] & BORDER]

            # tangent (used when self.align_edges is False)
            tris = []
            for tri in vert_dict[eve]:
                efa = tri[0].face
                if not efa.hide:
                    # if not self.use_outside_calculation and efa.select or \
                    #    self.use_outside_calculation and not efa.select:
                    #     tris.append(tri)
                    if (
                        self.tangent_calculation in ("selected", "individual")
                        and efa.select
                        or self.tangent_calculation == "deselected"
                        and not efa.select
                    ):
                        tris.append(tri)
            tangent = LoopTris.vert_tangent(eve, eve_prev, eve_next, tris, fallback=Vector((0, 0, 0)))

            # tangent_min, tangent_max (used when self.align_edges is True)
            edges = []
            for eed in eve.link_edges:
                if eed.hide or loop_tris.eflags[eed] & (WIRE | BORDER):
                    continue
                # if not self.use_outside_calculation and eed.select or \
                #    self.use_outside_calculation and not eed.select:
                #     edges.append(eed)
                if (
                    self.tangent_calculation in ("selected", "individual")
                    and eed.select
                    or self.tangent_calculation == "deselected"
                    and not eed.select
                ):
                    edges.append(eed)
            tangent_min_max = []
            if len(edges) == 1:
                eed = edges[0]
                vec = eed.other_vert(eve).co - eve.co
                if vec.length > 0:
                    vec.normalize()
                    vec1 = eve_prev.co - eve.co
                    if vec1.length > 0:
                        vec1.normalize()
                        f1 = vec1.cross(vec).length
                        if f1 > EPS:
                            tangent_min_max.append(vec / f1)
                    vec2 = eve_next.co - eve.co
                    if vec2.length > 0:
                        vec2.normalize()
                        f2 = vec2.cross(vec).length
                        if f2 > EPS:
                            tangent_min_max.append(vec / f2)
            tangent_min_max.sort(key=lambda v: v.length)

            if len(tangent_min_max) == 0:
                tangents = [tangent] * 3
            elif len(tangent_min_max) == 1:
                tangents = [tangent] + tangent_min_max * 2
            else:
                tangents = [tangent] + tangent_min_max
            vert_tangents[eve] = tangents

        return vert_tangents