Beispiel #1
0
    def slide_update(self, context, eventd, settings):
        x, y = eventd['mouse']
        region = context.region
        region = eventd['region']
        r3d = eventd['r3d']
        hit = common_utilities.ray_cast_region2d_bvh(region, r3d, (x, y),
                                                     self.trg_bvh, self.trg_mx,
                                                     settings)[1]
        if hit[2] is None: return

        pt = invert_matrix(self.trg_mx) * hit[0]

        def dist(v_index):
            v = self.trg_bme.verts[v_index]
            l = (self.trg_mx * v.co) - pt
            return l.length

        v_ind = min(self.loopslide.vert_loop_vs,
                    key=dist)  #<  The closest edgeloop point to the mouse
        n = self.loopslide.vert_loop_vs.index(v_ind)
        v_pt = self.trg_bme.verts[v_ind].co

        p_right, pct_right = intersect_point_line(
            pt, v_pt, v_pt + self.loopslide.edge_loop_right[n])
        p_left, pct_left = intersect_point_line(
            pt, v_pt, v_pt + self.loopslide.edge_loop_left[n])

        if pct_right > 0:
            self.loopslide.pct = min(1, pct_right)
            self.loopslide.right = True
        else:
            self.loopslide.right = False
            self.loopslide.pct = min(1, pct_left)

        self.loopslide.calc_snaps(self.trg_bme, snap=False)
Beispiel #2
0
def xsect_spline(sp_a, sp_b, _hubs, precision):
    pt_a_prev = pt_b_prev = None
    EPS_SPLINE = min(sp_a.length, sp_b.length) / precision
    pt_a_prev = sp_a.points[0]
    for a, pt_a in enumerate(sp_a.points[1:]):
        pt_b_prev = sp_b.points[0]
        for b, pt_b in enumerate(sp_b.points[1:]):

            # Now we have 2 edges
            # print(pt_a, pt_a_prev, pt_b, pt_b_prev)
            xsect = intersect_line_line(pt_a, pt_a_prev, pt_b, pt_b_prev)
            if xsect is not None:
                if (xsect[0] - xsect[1]).length <= EPS_SPLINE:
                    f = intersect_point_line(xsect[1], pt_a, pt_a_prev)[1]
                    # if f >= 0.0-EPS_SPLINE and f <= 1.0+EPS_SPLINE:
                    # for some reason doesnt work so well, same below
                    if f >= 0.0 and f <= 1.0:
                        f = intersect_point_line(xsect[0], pt_b, pt_b_prev)[1]
                        # if f >= 0.0-EPS_SPLINE and f <= 1.0+EPS_SPLINE:
                        if f >= 0.0 and f <= 1.0:
                            # This wont happen often
                            co = xsect[0].lerp(xsect[1], 0.5)
                            hub = get_hub(co, _hubs, EPS_SPLINE)

                            sp_a.hubs.append((a, hub))
                            sp_b.hubs.append((b, hub))

            pt_b_prev = pt_b

        pt_a_prev = pt_a
    def slide_update(self,context,eventd,settings):
        x,y = eventd['mouse']
        region = context.region
        region = eventd['region']
        r3d = eventd['r3d']
        hit = common_utilities.ray_cast_region2d_bvh(region, r3d, (x,y), self.trg_bvh, self.trg_mx, settings)[1]
        if hit[2] is None: return

        pt = invert_matrix(self.trg_mx) * hit[0]
        def dist(v_index):
            v = self.trg_bme.verts[v_index]
            l = (self.trg_mx * v.co) - pt
            return l.length

        v_ind = min(self.loopslide.vert_loop_vs, key = dist)  #<  The closest edgeloop point to the mouse
        n = self.loopslide.vert_loop_vs.index(v_ind)
        v_pt = self.trg_bme.verts[v_ind].co
        
        p_right, pct_right = intersect_point_line(pt, v_pt, v_pt + self.loopslide.edge_loop_right[n])
        p_left, pct_left = intersect_point_line(pt, v_pt, v_pt + self.loopslide.edge_loop_left[n])

        if pct_right > 0:
            self.loopslide.pct = min(1, pct_right)
            self.loopslide.right = True
        else:
            self.loopslide.right = False
            self.loopslide.pct = min(1, pct_left)

        self.loopslide.calc_snaps(self.trg_bme, snap = False)
Beispiel #4
0
def xsect_spline(sp_a, sp_b, _hubs, precision):
    pt_a_prev = pt_b_prev = None
    EPS_SPLINE = min(sp_a.length, sp_b.length) / precision
    pt_a_prev = sp_a.points[0]
    for a, pt_a in enumerate(sp_a.points[1:]):
        pt_b_prev = sp_b.points[0]
        for b, pt_b in enumerate(sp_b.points[1:]):

            # Now we have 2 edges
            # print(pt_a, pt_a_prev, pt_b, pt_b_prev)
            xsect = intersect_line_line(pt_a, pt_a_prev, pt_b, pt_b_prev)
            if xsect is not None:
                if (xsect[0] - xsect[1]).length <= EPS_SPLINE:
                    f = intersect_point_line(xsect[1], pt_a, pt_a_prev)[1]
                    # if f >= 0.0-EPS_SPLINE and f <= 1.0+EPS_SPLINE:
                        # for some reason doesnt work so well, same below
                    if f >= 0.0 and f <= 1.0:
                        f = intersect_point_line(xsect[0], pt_b, pt_b_prev)[1]
                        # if f >= 0.0-EPS_SPLINE and f <= 1.0+EPS_SPLINE:
                        if f >= 0.0 and f <= 1.0:
                            # This wont happen often
                            co = xsect[0].lerp(xsect[1], 0.5)
                            hub = get_hub(co, _hubs, EPS_SPLINE)

                            sp_a.hubs.append((a, hub))
                            sp_b.hubs.append((b, hub))

            pt_b_prev = pt_b

        pt_a_prev = pt_a
Beispiel #5
0
        def intersect_line(self, l1, l2, reverse=False):
            """ Spectial kind of intersection, works in 3d on the plane
                defimed by the points normal and the line.
            """

            from mathutils.geometry import (
                intersect_point_line, )

            if reverse:
                p_first = self.points[-1]
                no = -self.points[-1].no
                point_iter = reversed(self.points[:-1])
            else:
                p_first = self.points[0]
                no = self.points[0].no
                point_iter = self.points[1:]

            # calculate the line right angles to the line
            bi_no = (no - no.project(l2 - l1)).normalized()

            bi_l1 = p_first.co
            bi_l2 = p_first.co + bi_no

            for p_apex in point_iter:
                ix, fac = intersect_point_line(p_apex.co, bi_l1, bi_l2)

                if fac < 0.0001:

                    if reverse:
                        p_apex_other = p_apex.next
                    else:
                        p_apex_other = p_apex.prev

                    # find the exact point on the line between the apex and
                    # the middle
                    p_test_1 = intersect_point_line(p_apex.co, l1, l2)[0]
                    p_test_2 = intersect_point_line(p_apex_other.co, l1, l2)[0]

                    w1 = (p_test_1 - p_apex.co).length
                    w2 = (p_test_2 - p_apex_other.co).length

                    #assert(w1 + w2 != 0)
                    try:
                        fac = w1 / (w1 + w2)
                    except ZeroDivisionError:
                        fac = 0.5
                    assert (fac >= 0.0 and fac <= 1.0)

                    p_apex_co = p_apex.co.lerp(p_apex_other.co, fac)
                    p_apex_no = p_apex.no.lerp(p_apex_other.no, fac)
                    p_apex_no.normalize()

                    # visualize_line(p_mid.to_3d(), corner.to_3d())
                    # visualize_line(p_apex.co.to_3d(), p_apex_co.to_3d())

                    return p_apex_co, p_apex_no, p_apex

            # intersection not found
            return None, None, None
    def hover_non_man(self, context, x, y):
        region = context.region
        rv3d = context.region_data
        coord = x, y
        self.mouse = Vector((x, y))

        loc3d_reg2D = view3d_utils.location_3d_to_region_2d

        view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord)
        ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord)
        ray_target = ray_origin + (view_vector * 1000)
        mx = self.cut_ob.matrix_world
        imx = mx.inverted()
        loc, no, face_ind = self.cut_ob.ray_cast(imx * ray_origin,
                                                 imx * ray_target)

        if len(self.non_man_points):
            co3d, index, dist = self.kd.find(mx * loc)

            #get the actual non man vert from original list
            close_bmvert = self.bme.verts[self.non_man_bmverts[
                index]]  #stupid mapping, unreadable, terrible, fix this, because can't keep a list of actual bmverts
            close_eds = [
                ed for ed in close_bmvert.link_edges if not ed.is_manifold
            ]
            if len(close_eds) == 2:
                bm0 = close_eds[0].other_vert(close_bmvert)
                bm1 = close_eds[1].other_vert(close_bmvert)

                a0 = bm0.co
                b = close_bmvert.co
                a1 = bm1.co

                inter_0, d0 = intersect_point_line(loc, a0, b)
                inter_1, d1 = intersect_point_line(loc, a1, b)

                screen_0 = loc3d_reg2D(region, rv3d, mx * inter_0)
                screen_1 = loc3d_reg2D(region, rv3d, mx * inter_1)
                screen_v = loc3d_reg2D(region, rv3d, mx * b)

                screen_d0 = (self.mouse - screen_0).length
                screen_d1 = (self.mouse - screen_1).length
                screen_dv = (self.mouse - screen_v).length

                if 0 < d0 <= 1 and screen_d0 < 30:
                    self.hovered = ['NON_MAN_ED', (close_eds[0], mx * inter_0)]
                    return
                elif 0 < d1 <= 1 and screen_d1 < 30:
                    self.hovered = ['NON_MAN_ED', (close_eds[1], mx * inter_1)]
                    return
                elif screen_dv < 30:
                    if abs(d0) < abs(d1):
                        self.hovered = ['NON_MAN_VERT', (close_eds[0], mx * b)]
                        return
                    else:
                        self.hovered = ['NON_MAN_VERT', (close_eds[1], mx * b)]
                        return
    def make_corner_alt(self, bm, verts, fac=0.5):
        face = get_face_with_verts(verts)
        if face is not None and len(face.edges) == 6:

            done = False
            loop_a = None
            loop_b = None
            for vert in verts:
                face_loops = get_face_loops_for_vert(vert, face)
                for loop in face_loops:
                    if loop.vert in verts:
                        loop_a = loop

                        if loop.link_loop_next.link_loop_next.vert in verts:
                            loop_b = loop.link_loop_next

                            done = True
                            break
                if done:
                    break

            if loop_a is not None and loop_b is not None:
                edge_a = loop_a.link_loop_prev.link_loop_prev.edge
                edge_b = loop_b.link_loop_next.link_loop_next.edge
                vert_a = loop_a.vert
                vert_b = loop_b.edge.other_vert(loop_b.vert)

                edge_a_point, _ = intersect_point_line(vert_b.co,
                                                       edge_a.verts[0].co,
                                                       edge_a.verts[1].co)
                edge_b_point, _ = intersect_point_line(vert_a.co,
                                                       edge_b.verts[0].co,
                                                       edge_b.verts[1].co)

                isect_point = intersect_line_line(edge_a_point, vert_b.co,
                                                  edge_b_point, vert_a.co)
                if isect_point is not None:
                    center_vert_co = isect_point[0]
                    shared_vert = get_vertex_shared_by_edges(
                        [loop_a.edge, loop_b.edge])
                    connect_vert = get_vertex_shared_by_edges([edge_a, edge_b])
                    center_vert_co = center_vert_co.lerp(connect_vert.co, fac)

                    # Make the corner geometry
                    center_vert: BMVert = bmesh.ops.create_vert(
                        bm, co=center_vert_co)["vert"][0]

                    bm.faces.ensure_lookup_table()
                    bm.edges.ensure_lookup_table()
                    bm.verts.ensure_lookup_table()

                    new_edge_a = bm.edges.new([vert_a, center_vert])
                    new_edge_b = bm.edges.new([vert_b, center_vert])
                    new_edge_c = bm.edges.new([center_vert, connect_vert])

                    bmesh.utils.face_split_edgenet(
                        face, [new_edge_a, new_edge_b, new_edge_c])
 def get_closest_intersection_point_to_center(self, closest_intersection_point, intersection_point, line_coord):
     line_coord_vec = ((line_coord[0], line_coord[1]), (line_coord[2], line_coord[3]))
     intersect_point_proximity = intersect_point_line((intersection_point[0], intersection_point[1]), line_coord_vec[0], line_coord_vec[1])[1]
     closest_intersection_point_proximity = intersect_point_line((closest_intersection_point[0], closest_intersection_point[1]), line_coord_vec[0], line_coord_vec[1])[1]
     if intersect_point_proximity > closest_intersection_point_proximity:
         return closest_intersection_point
     elif intersect_point_proximity < closest_intersection_point_proximity:
         return intersection_point
     else:
         return closest_intersection_point
    def hover_non_man(self,context,x,y):
        region = context.region
        rv3d = context.region_data
        coord = x, y
        self.mouse = Vector((x, y))
        
        loc3d_reg2D = view3d_utils.location_3d_to_region_2d
        
        view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord)
        ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord)
        ray_target = ray_origin + (view_vector * 1000)
        mx = self.cut_ob.matrix_world
        imx = mx.inverted()
        loc, no, face_ind = self.cut_ob.ray_cast(imx * ray_origin, imx * ray_target)
        
        if len(self.non_man_points):
            co3d, index, dist = self.kd.find(mx * loc)

            #get the actual non man vert from original list
            close_bmvert = self.bme.verts[self.non_man_bmverts[index]] #stupid mapping, unreadable, terrible, fix this, because can't keep a list of actual bmverts
            close_eds = [ed for ed in close_bmvert.link_edges if not ed.is_manifold]
            if len(close_eds) == 2:
                bm0 = close_eds[0].other_vert(close_bmvert)
                bm1 = close_eds[1].other_vert(close_bmvert)
            
                a0 = bm0.co
                b   = close_bmvert.co
                a1  = bm1.co 
                
                inter_0, d0 = intersect_point_line(loc, a0, b)
                inter_1, d1 = intersect_point_line(loc, a1, b)
                
                screen_0 = loc3d_reg2D(region, rv3d, mx * inter_0)
                screen_1 = loc3d_reg2D(region, rv3d, mx * inter_1)
                screen_v = loc3d_reg2D(region, rv3d, mx * b)
                
                screen_d0 = (self.mouse - screen_0).length
                screen_d1 = (self.mouse - screen_1).length
                screen_dv = (self.mouse - screen_v).length
                
                if 0 < d0 <= 1 and screen_d0 < 30:
                    self.hovered = ['NON_MAN_ED', (close_eds[0], mx*inter_0)]
                    return
                elif 0 < d1 <= 1 and screen_d1 < 30:
                    self.hovered = ['NON_MAN_ED', (close_eds[1], mx*inter_1)]
                    return
                elif screen_dv < 30:
                    if abs(d0) < abs(d1):
                        self.hovered = ['NON_MAN_VERT', (close_eds[0], mx*b)]
                        return
                    else:
                        self.hovered = ['NON_MAN_VERT', (close_eds[1], mx*b)]
                        return
def f_1(me, list_0, arg, context, ob_act):

    cb = context.scene.pt_custom_props.b
    cen1 = context.scene.pt_custom_props.en1

    dict_0 = {}
    dict_1 = {}

    if arg == 'x':
        lp1 = Vector((0, 0, 0))
        lp2 = Vector((1, 0, 0))
    elif arg == 'y':
        lp1 = Vector((0, 0, 0))
        lp2 = Vector((0, 1, 0))
    elif arg == 'z':
        lp1 = Vector((0, 0, 0))
        lp2 = Vector((0, 0, 1))

    if cb == False:
        for vi in list_0:
            v = (me.vertices[vi].co).copy()
            if cen1 == 'opt0':
                p3 = intersect_point_line( v, lp1, lp2)[0]
            elif cen1 == 'opt1':
                p1 = ob_act.matrix_world * v
                p2 = intersect_point_line( p1, lp1, lp2)[0]
                p3 = (ob_act.matrix_world).inverted() * p2

            dict_0[vi] = p3

        for j in dict_0:
            me.vertices[j].co = dict_0[j]

    elif cb == True:
        for vi in list_0:
            v = (me.vertices[vi].co).copy()
            if cen1 == 'opt0':
                p3 = intersect_point_line( v, lp1, lp2)[0]
            elif cen1 == 'opt1':
                p1 = ob_act.matrix_world * v
                p2 = intersect_point_line( p1, lp1, lp2)[0]
                p3 = (ob_act.matrix_world).inverted() * p2

            me.vertices.add(1)
            me.vertices[-1].co = p3
            me.vertices[-1].select = False
            dict_1[vi] = me.vertices[-1].index

        edge_copy_(me, dict_1)
        faces_copy_(me, dict_1)
Beispiel #11
0
    def MatchPairByPerpendicular(self, context, sObj, sID, dObj, dID):
        #当互相垂直角度不为90度时,使用这个
        #我们现在已有一条公共边与两个可能与垂直与公共边的面异面的点,如果两点到公共边上的最小距离坐标很近,说明两个三角形是镜像关系;
        #这是MatchPair的升级版,但是最好先用MatchPair得到公共边,容易理解

        #通过RotateO的判断,我们已经将三对[0-1-2]的[1-2]进行了公共边处理,所以,0是可能是与垂直与公共边的面异面的点。
        #所以,几乎可以忽视部分传入参数,eg : ID

        if len(sID) != 3 or len(dID) != 3:
            self.report(
                {'WARNING'},
                'Perpendicular Error in MatchPairByPerpendicular Function!!!')
            return

        #两点
        wm = sObj.matrix_world.copy()
        sP0 = wm * (sObj.data.vertices[self.vts[0][sID[0]]].co.copy())
        wm = dObj.matrix_world.copy()
        dP0 = wm * (dObj.data.vertices[self.vts[self.objs.index(dObj)][
            dID[0]]].co.copy())

        #两点是否重合
        if (dP0 - sP0).magnitude < 0.000001:
            return

        #公共边
        wm = sObj.matrix_world.copy()
        sP1 = wm * (sObj.data.vertices[self.vts[0][sID[1]]].co.copy())
        sP2 = wm * (sObj.data.vertices[self.vts[0][sID[2]]].co.copy())

        #映射点,求矢量-角度
        from mathutils import geometry
        sP4 = geometry.intersect_point_line(sP0, sP1, sP2)[0]
        dP4 = geometry.intersect_point_line(dP0, sP1, sP2)[0]
        v1, v2 = (sP4 - sP0).normalized(), (dP4 - dP0).normalized()

        #角度相关
        angle = v1.angle(v2)
        if angle < 0.000001:
            return

        cross = v1.cross(v2)

        if self.BoolRotate1Flip == True:
            angle += pi
        angle *= -1

        bpy.ops.transform.rotate(value=angle, axis=cross)
        return
Beispiel #12
0
def intersect(pt,bone) :
    intersection = intersect_point_line(pt,bone['head'],bone['tail'])

    point_on_line = (pt-intersection[0]).length < 0.001

    #print('point_on_line',point_on_line)
    #distance = True
    is_in_range = False
    if intersection[1]<=0.5 :
        distance = (pt-bone['head']).length
        #print(distance)
        if intersection[1]>=0 :
            is_in_range = True
        else :
            is_in_range = distance > -1.5

    elif intersection[1]>0.5 :
        distance = (pt-bone['tail']).length

        #print(distance)
        if intersection[1]<=1 :
            is_in_range = True
        else :
            is_in_range = distance < 2.5

    #print('is_in_range',is_in_range)
    #print(bone)
    #print('intersection',intersection)
    #print('point_on_line',point_on_line)

    #print('is_in_range',is_in_range)


    if point_on_line and is_in_range:
        return intersection[1]
def e_no_(bme, indx, p, p1):
    tmp1 = (bme.verts[indx].co).copy()
    tmp1[0] += 0.1
    tmp1[1] += 0.1
    tmp1[2] += 0.1
    ip1 = intersect_point_line(tmp1, p, p1)[0]
    return tmp1 - ip1
def get_closest_edge(bm, point, dist):
    r_edge = None
    for edge in bm.edges:
        v1 = edge.verts[0].co
        v2 = edge.verts[1].co
        # Test the BVH (AABB) first
        for i in range(3):
            if v1[i] <= v2[i]:
                isect = v1[i] - dist <= point[i] <= v2[i] + dist
            else:
                isect = v2[i] - dist <= point[i] <= v1[i] + dist

            if not isect:
                break
        else:
            ret = intersect_point_line(point, v1, v2)

            if ret[1] < 0.0:
                tmp = v1
            elif ret[1] > 1.0:
                tmp = v2
            else:
                tmp = ret[0]

            new_dist = (point - tmp).length
            if new_dist <= dist:
                dist = new_dist
                r_edge = edge

    return r_edge
Beispiel #15
0
 def distance_point_edge(pt, edge):
     line_p1 = edge.verts[0].co
     line_p2 = edge.verts[1].co
     ret = intersect_point_line(pt, line_p1, line_p2)
     closest_point_on_line = ret[0]
     distance_vector = closest_point_on_line - pt
     return distance_vector.length
Beispiel #16
0
def e_no_(bme, indx, p, p1):
    tmp1 = (bme.verts[indx].co).copy()
    tmp1[0] += 0.1
    tmp1[1] += 0.1
    tmp1[2] += 0.1
    ip1 = intersect_point_line(tmp1, p, p1)[0]
    return tmp1 - ip1
    def handle_mouse_move(self, mouse_pos_2d, mouse_pos_3d, event, context):

        if self.is_extruding():

            dir = self.get_dir()
            region = context.region
            rv3d = context.space_data.region_3d

            mxy = event.mouse_region_x, event.mouse_region_y
            mpos_3d = region_2d_to_location_3d(region, rv3d, mxy,
                                               self._vertices[0])

            isect_pt, length = intersect_point_line(mpos_3d, self._vertices[0],
                                                    self._vertices[0] + dir)

            self._extrusion = length

            self.extrude_vertices(context)
            return True

        if self._vertex_moving is not None:
            self._vertices[self._vertex_moving] = mouse_pos_3d
            return True

        if self.is_created() and self._is_moving:
            diff = mouse_pos_3d - self._move_offset
            self._vertices = [vertex + diff for vertex in self._vertices]
            self._vertices_extruded = [
                vertex + diff for vertex in self._vertices_extruded
            ]
            self._move_offset = mouse_pos_3d
            return True

        return False
Beispiel #18
0
def intersect(pt, bone):
    intersection = intersect_point_line(pt, bone['head'], bone['tail'])

    point_on_line = (pt - intersection[0]).length < 0.001

    #print('point_on_line',point_on_line)
    #distance = True
    is_in_range = False
    if intersection[1] <= 0.5:
        distance = (pt - bone['head']).length
        #print(distance)
        if intersection[1] >= 0:
            is_in_range = True
        else:
            is_in_range = distance > -1.5

    elif intersection[1] > 0.5:
        distance = (pt - bone['tail']).length

        #print(distance)
        if intersection[1] <= 1:
            is_in_range = True
        else:
            is_in_range = distance < 2.5

    #print('is_in_range',is_in_range)
    #print(bone)
    #print('intersection',intersection)
    #print('point_on_line',point_on_line)

    #print('is_in_range',is_in_range)

    if point_on_line and is_in_range:
        return intersection[1]
Beispiel #19
0
def get_closest_edge(bm, point, dist):
    r_edge = None
    for edge in bm.edges:
        v1 = edge.verts[0].co
        v2 = edge.verts[1].co
        # Test the BVH (AABB) first
        for i in range(3):
            if v1[i] <= v2[i]:
                isect = v1[i] - dist <= point[i] <= v2[i] + dist
            else:
                isect = v2[i] - dist <= point[i] <= v1[i] + dist

            if not isect:
                break
        else:
            ret = intersect_point_line(point, v1, v2)

            if ret[1] < 0.0:
                tmp = v1
            elif ret[1] > 1.0:
                tmp = v2
            else:
                tmp = ret[0]

            new_dist = (point - tmp).length
            if new_dist <= dist:
                dist = new_dist
                r_edge = edge

    return r_edge
    def active_element(self, context, x, y):
        active_head = self.head.mouse_over(x, y)
        active_tail = self.tail.mouse_over(x, y)

        mouse_loc = Vector((x, y, 0))
        head_loc = Vector((self.head.x, self.head.y, 0))
        tail_loc = Vector((self.tail.x, self.tail.y, 0))
        intersect = intersect_point_line(mouse_loc, head_loc, tail_loc)

        dist = (intersect[0] - mouse_loc).length_squared
        bound = intersect[1]
        active_self = (dist < 100) and (bound < 1) and (bound > 0)  # TODO:  make this a sensitivity setting

        if active_head and active_tail and active_self:  # they are all clustered together
            print("returning head but tail too")
            return self.head

        elif active_tail:
            print("returning tail")
            return self.tail

        elif active_head:
            print("returning head")
            return self.head

        elif active_self:
            print("returning line")
            return self

        else:
            print("returning None")
            return None
Beispiel #21
0
    def slide_snap(self, context, hitobj, hitlocation, hitindex):
        '''
        slide snap to edges of all edit mode objects
        '''

        # get hitface from the cached bmesh
        hitbm = self.snap_bms[hitobj.name]
        hitface = hitbm.faces[hitindex]

        # hit location in hitobj's local space
        hitmx = hitobj.matrix_world
        hit = hitmx.inverted() @ hitlocation

        # get closest edge
        edge = min([(e, (hit - intersect_point_line(hit, e.verts[0].co, e.verts[1].co)[0]).length, (hit - get_center_between_verts(*e.verts)).length) for e in hitface.edges], key=lambda x: (x[1] * x[2]) / x[0].calc_length())[0]

        # set snap coords for view3d drawing
        self.snap_coords = [hitmx @ v.co for v in edge.verts]

        # get snap coords in active's local space
        snap_coords = [self.mx.inverted_safe() @ co for co in self.snap_coords]

        # init proximity and ortho coords for view3d drawing
        self.snap_proximity_coords = []
        self.snap_ortho_coords = []

        # get intersection of individual slide dirs and snap coords
        for v, data in self.verts.items():
            init_co = data['co']
            target = data['target']

            snap_dir = (snap_coords[0] - snap_coords[1]).normalized()
            slide_dir = (init_co - target.co).normalized()

            # check for parallel and almost parallel snap edges, do nothing in this case
            if abs(slide_dir.dot(snap_dir)) > 0.999:
                v.co = init_co

            # with a smaller dot product, interseect_line_line will produce a guaranteed hit
            else:
                i = intersect_line_line(init_co, target.co, *snap_coords)

                v.co = i[1 if self.is_diverging else 0] if i else init_co

                # add coords to draw the slide 'edges'
                if v.co != target.co:
                    self.coords.extend([v.co, target.co])

                # add proximity coords
                if i[1] != snap_coords[0]:
                    self.snap_proximity_coords.extend([i[1], snap_coords[0]])

                # add ortho coords
                if v.co != i[1]:
                    self.snap_ortho_coords.extend([v.co, i[1]])


        self.bm.normal_update()
        bmesh.update_edit_mesh(self.active.data)
    def active_element(self,context,x,y):
        active_head = self.head.mouse_over(x, y)
        active_tail = self.tail.mouse_over(x, y)
        active_tan = self.plane_tan.mouse_over(x, y)
        
        mouse_loc = Vector((x,y,0))
        head_loc = Vector((self.head.x, self.head.y, 0))
        tail_loc = Vector((self.tail.x, self.tail.y, 0))
        intersect = intersect_point_line(mouse_loc, head_loc, tail_loc)
        
        dist = (intersect[0] - mouse_loc).length_squared
        bound = intersect[1]
        active_self = (dist < 100) and (bound < 1) and (bound > 0) #TODO:  make this a sensitivity setting
        
        if active_head and active_tail and active_self: #they are all clustered together
            #print('returning head but tail too')
            return self.head
        
        elif active_tail:
            #print('returning tail')
            return self.tail
        
        elif active_head:
            #print('returning head')
            return self.head
        
        elif active_tan:
            return self.plane_tan
        
        elif active_self:
            #print('returning line')
            return self
        
        else:
            #print('returning None')
            return None
#cut line, a user interactive 2d line which represents a plane in 3d splace
    #head (type conrol point)
    #tail (type control points)
    #target mesh
    #view_direction (crossed with line to make plane normal for slicing)
    
    #draw method
    
    #new control point project method
    
    #mouse hover line calc
    
    
#retopo object, surface
    #colelction of cut lines
    #collection of countours to loft
    
    #n rings (crosses borrowed from looptools)
    #n follows (borrowed from looptools and or bsurfaces)
    
    #method contours from cutlines
    
    #method bridge contours
Beispiel #23
0
def is_in_segment(v1, v2, point, tolerance=1e-6):
    closest, percent = intersect_point_line(point, v1, v2)
    if not (0 <= percent <= 1):
        return False
    distance = (point - closest).length
    if distance > tolerance:
        return False
    return True
 def MatchPairByPerpendicular(self, context, sObj, sID, dObj, dID):
     #当互相垂直角度不为90度时,使用这个
     #我们现在已有一条公共边与两个可能与垂直与公共边的面异面的点,如果两点到公共边上的最小距离坐标很近,说明两个三角形是镜像关系;
     #这是MatchPair的升级版,但是最好先用MatchPair得到公共边,容易理解
     
     #通过RotateO的判断,我们已经将三对[0-1-2]的[1-2]进行了公共边处理,所以,0是可能是与垂直与公共边的面异面的点。
     #所以,几乎可以忽视部分传入参数,eg : ID
     
     if len(sID) != 3 or len(dID) != 3:
         self.report( {'WARNING'}, 'Perpendicular Error in MatchPairByPerpendicular Function!!!' )
         return
         
     #两点
     wm = sObj.matrix_world.copy()
     sP0 = wm * (sObj.data.vertices[self.vts[0][sID[0]]].co.copy())
     wm = dObj.matrix_world.copy()
     dP0 = wm * (dObj.data.vertices[self.vts[self.objs.index(dObj)][dID[0]]].co.copy())
     
     #两点是否重合
     if (dP0 - sP0).magnitude < 0.000001:
         return
     
     #公共边
     wm = sObj.matrix_world.copy()
     sP1 = wm * (sObj.data.vertices[self.vts[0][sID[1]]].co.copy())
     sP2 = wm * (sObj.data.vertices[self.vts[0][sID[2]]].co.copy())
     
     #映射点,求矢量-角度
     from mathutils import geometry
     sP4 = geometry.intersect_point_line(sP0, sP1, sP2)[0]
     dP4 = geometry.intersect_point_line(dP0, sP1, sP2)[0]
     v1, v2 = (sP4 - sP0).normalized(), (dP4 - dP0).normalized()
     
     #角度相关
     angle = v1.angle(v2)
     if angle < 0.000001:
         return
         
     cross = v1.cross(v2)
     
     if self.BoolRotate1Flip == True:
         angle += pi
     angle *= -1
         
     bpy.ops.transform.rotate(value=angle, axis=cross)
     return
Beispiel #25
0
    def get_data_from_edge_ring(self):
        edge = self.current_edge

        edge_ring = self.current_ring
        flipped = self.flipped

        found_loop = False
        first_ring_edge = edge_ring[0]
        shortest_edge_len = float('INF')

        edge_start_pos = None
        edge_end_pos = None

        is_tri_fan_loop = False
        if edge_ring[0].edge.index == edge_ring[-1].edge.index:
            edge_ring.pop()
            is_tri_fan_loop = True

        for loop in edge_ring:
            if loop is None:
                break

            vert = loop.vert
            vert_other = loop.edge.other_vert(vert)

            dir_len = (vert_other.co - vert.co).length_squared

            if dir_len < shortest_edge_len:
                shortest_edge_len = dir_len

            vert_coords = None
            if loop.edge.index == edge.index:
                vert_coords = [vert.co.copy(), vert_other.co.copy()]

            if vert_coords is not None:
                if flipped:
                    vert_coords.reverse()

                edge_start_pos = vert_coords[0]
                edge_end_pos = vert_coords[1]

                _, percent = intersect_point_line(self.current_position,
                                                  vert_coords[0],
                                                  vert_coords[1])

                self.offset = percent

            if (loop.link_loop_radial_next.link_loop_next.link_loop_next.index
                    == first_ring_edge.index) and not loop.edge.is_boundary:
                found_loop = True
            else:
                found_loop = False

        distance = (self.current_position - edge_start_pos).length
        shortest_edge_len = shortest_edge_len**0.5
        is_loop = found_loop or is_tri_fan_loop

        return distance, shortest_edge_len, edge_start_pos, edge_end_pos, is_loop
def distance_point_segment(point, v1, v2):
    '''Compute distance of a point from a line segment.'''
    x, d = geometry.intersect_point_line(point, v1, v2)
    if d <= 0:
        return v1, (point - v1).magnitude
    elif d >= 1.0:
        return v2, (point - v2).magnitude
    else:
        return x, (point - x).magnitude
Beispiel #27
0
def compute_distance(point, line, line_end, tolerance):
    '''call to the mathuutils function'''
    inter_p = intersect_point_line(point, line, line_end)
    dist = (inter_p[0] - point).length
    segment_percent = inter_p[1]
    is_in_line = dist < tolerance
    closest_in_segment = 0 <= segment_percent <= 1
    is_in_segment = is_in_line and closest_in_segment
    return dist, is_in_segment, is_in_line, list(inter_p[0]), closest_in_segment
def distance_point_segment(point, v1, v2):
    '''Compute distance of a point from a line segment.'''
    x, d = geometry.intersect_point_line(point, v1, v2)
    if d <= 0:
        return v1, (point - v1).magnitude
    elif d >= 1.0:
        return v2, (point - v2).magnitude
    else:
        return x, (point - x).magnitude
def compute_distance(point, line, line_end, tolerance):
    '''call to the mathuutils function'''
    inter_p = intersect_point_line(point, line, line_end)
    dist = (inter_p[0] - point).length
    segment_percent = inter_p[1]
    is_in_line = dist < tolerance
    closest_in_segment = 0 <= segment_percent <= 1
    is_in_segment = is_in_line and closest_in_segment
    return dist, is_in_segment, is_in_line, list(inter_p[0]), closest_in_segment
        def make_corner_straight(bm, verts, p1, p2):
            v1 = verts[0]
            v2 = verts[1]

            face = get_face_with_verts(verts)
            if face is not None and len(face.edges) == 6:

                done = False
                loop_a = None
                loop_b = None
                for vert in verts:
                    face_loops = get_face_loops_for_vert(vert, face)
                    for loop in face_loops:
                        if loop.vert in verts:
                            loop_a = loop

                            if loop.link_loop_next.link_loop_next.vert in verts:
                                loop_b = loop.link_loop_next

                                done = True
                                break
                    if done:
                        break

                if loop_a is not None and loop_b is not None:
                    edge_a = loop_a.link_loop_prev.link_loop_prev.edge
                    edge_b = loop_b.link_loop_next.link_loop_next.edge

                    isect_point = intersect_line_line(p1, p2,
                                                      edge_b.verts[0].co,
                                                      edge_b.verts[1].co)
                    if isect_point is not None:
                        isect_point = isect_point[0]
                    else:
                        isect_point = intersect_line_line(
                            p1, p2, edge_a.verts[0].co, edge_a.verts[1].co)[0]

                    center_vert_co, _ = intersect_point_line(
                        v2.co, isect_point, v1.co)  #p1.lerp(p2, 0.5)

                    # Make the corner geometry
                    center_vert: BMVert = bm.verts.new(
                        center_vert_co
                    )  #bmesh.ops.create_vert(bm, co=center_vert_co)["vert"][0]
                    connect_vert = get_vertex_shared_by_edges([edge_a, edge_b])

                    new_edge_a = bm.edges.new([verts[0], center_vert])
                    new_edge_b = bm.edges.new([verts[1], center_vert])
                    new_edge_c = bm.edges.new([center_vert, connect_vert])

                    bmesh.utils.face_split_edgenet(
                        face, [new_edge_a, new_edge_b, new_edge_c])

                    bm.faces.ensure_lookup_table()
                    bm.edges.ensure_lookup_table()
                    bm.verts.ensure_lookup_table()
Beispiel #31
0
 def update_radius(self, context, event):
     pt = self.get_pos3d(context)
     c = self.arc.c
     left = self.line_0.lerp(1)
     p, t = intersect_point_line(pt, c, left)
     radius = (left - p).length
     if event.alt:
         radius = round(radius, 1)
     self.set_value(context, self.datablock, self.glprovider.prop2_name,
                    radius)
Beispiel #32
0
    def straighten(self, bm, verts, v_start, v_end):
        # move all verts but the start and end verts on the vector described by the two
        verts.remove(v_start)
        verts.remove(v_end)

        for v in verts:
            co, _ = geometry.intersect_point_line(v.co, v_start.co, v_end.co)
            v.co = co

        bm.normal_update()
Beispiel #33
0
def get_selection_radius():

	ob = bpy.context.active_object

	radius = 0.0
	
	# no use continueing if nothing is selected
	if contains_selected_item(ob.data.polygons):
	
		# Find the center of the selection
		cent = mathutils.Vector()
		nr = 0
		nonVerts = []
		selVerts = []
		for p in ob.data.polygons:
			if p.select:
				for v in p.vertices:
					nr += 1
					cent += v.co
			else:
				nonVerts.extend(p.vertices)
				
		cent /= nr
		
		chk = 0
		
		# Now that we know the center.. we can figure out how close the nearest point on an outer edge is
		for e in get_selected_edges():
		
			nonSection = [v for v in e.vertices if v in nonVerts]
			if len(nonSection):
			
				v0 = ob.data.vertices[e.vertices[0]].co
				v1 = ob.data.vertices[e.vertices[1]].co
				
				# If there's more than 1 vert of this edge on the outside... we need the edge length to be long enough too!
				if len(nonSection) > 1:
					edge = v0 - v1
					edgeRad = edge.length * 0.5
					
					if edgeRad < radius or not chk:
						radius = edgeRad
						chk += 1
				
				int = geometry.intersect_point_line(cent, v0, v1)
				
				rad = cent - int[0]
				l = rad.length
				
				if l < radius or not chk:
					radius = l
					chk += 1
					
	return radius
Beispiel #34
0
def calculate_UV(U, V, fx, fy, ft):
    for i in range(0, U.shape[0]):
        for j in range(0, U.shape[1]):
            if fx[i][j] != 0 and fy[i][j] != 0 and ft[i][j] != 0:
                line = ((-1 * ft[i][j] / fx[i][j], 0),
                        (0, -1 * ft[i][j] / fy[i][j]))
                point = (0, 0)
                a, __ = intersect_point_line(point, line[0], line[1])
                U[i][j] = a[0]
                V[i][j] = a[1]
    return U, V
Beispiel #35
0
 def update(self, context, event):
     # 0  1  2
     # |_____|
     #
     pt = self.get_pos3d(context)
     pt, t = intersect_point_line(pt, self.line_0.p, self.line_2.p)
     length = (self.line_0.p - pt).length
     if event.alt:
         length = round(length, 1)
     self.set_value(context, self.datablock, self.glprovider.prop1_name,
                    length)
Beispiel #36
0
    def grad_f_ed(ed, p, last_face):

        #walk around non manifold edges
        if len(ed.link_faces) == 1:
            minv = min(ed.verts, key = geos.get)
            return minv.co, minv, None


        f = [fc for fc in ed.link_faces if fc !=last_face][0]
        g = gradient_face(f, geos)
        L = f.calc_perimeter()


        #test for vert intersection
        for v in f.verts:
            v_inter, pct = intersect_point_line(v.co, p, p-L*g)

            delta = v.co - v_inter
            if delta.length < epsilon:
                print('intersect vert')
                return v.co, v, None

        tests = [e for e in f.edges if e != ed]

        for e in tests:

            v0, v1 = intersect_line_line(e.verts[0].co, e.verts[1].co, p, p-L*g)

            V = v0 - e.verts[0].co
            edV = e.verts[1].co - e.verts[0].co
            Vi = v0 - p

            if V.length - edV.length > epsilon:
                #print('intersects outside segment')
                continue
            elif V.dot(edV) < 0:
                #print('intersects behind')
                continue

            elif Vi.dot(g) > 0:  #remember we watnt to travel DOWN the gradient

                #print('shoots out the face, not across the face')
                continue

            else:

                #print('regular face edge crossing')
                return v0, e, f

        #we didn't intersect across an edge, or on a vert,
        #therefore, we should travel ALONG the edge

        vret = min(ed.verts, key = geos.get)
        return vret.co, vret, None
def makeBonesCollinearFromBoneHeadToBoneTail(armatureName, boneArray):
    initial_mode = bpy.context.object.mode
    armature_ob = bpy.context.scene.objects[armatureName]
    bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
    armature_ob.select = True
    bpy.context.scene.objects.active = armature_ob
    #
    bpy.ops.object.mode_set(mode='EDIT', toggle=False)
    #
    fromBone = armature_ob.data.edit_bones[boneArray[0]]
    toBone = armature_ob.data.edit_bones[boneArray[-1]]
    line = (fromBone.head, toBone.tail)
    for bone in boneArray:
        if bone == fromBone.name:
            point = armature_ob.data.edit_bones[bone].tail
            intersect = intersect_point_line(point, line[0], line[1])
            localCo = intersect[0]
            armature_ob.data.edit_bones[bone].tail = localCo
        if bone == toBone.name:
            point = armature_ob.data.edit_bones[bone].head
            intersect = intersect_point_line(point, line[0], line[1])
            localCo = intersect[0]
            armature_ob.data.edit_bones[bone].head = localCo
        else:
            point = armature_ob.data.edit_bones[bone].head
            intersect = intersect_point_line(point, line[0], line[1])
            localCo = intersect[0]
            armature_ob.data.edit_bones[bone].head = localCo
            #
            point = armature_ob.data.edit_bones[bone].tail
            intersect = intersect_point_line(point, line[0], line[1])
            localCo = intersect[0]
            armature_ob.data.edit_bones[bone].tail = localCo
    #
    for index, bone in enumerate(boneArray):
        if bone == toBone.name:
            continue
        else:
            armature_ob.data.edit_bones[
                bone].tail = armature_ob.data.edit_bones[boneArray[index +
                                                                   1]].head
Beispiel #38
0
def get_closest_point_on_line(point, line):
    """
    Given a point get the closest point to the line segment

    Args:
        point ([tuple]): [description]
        line ([list]): [list of list [[x1,y1],[x2,y2]]]]

    Returns:
        [type]: [description]
    """
    return intersect_point_line(point, *line)
Beispiel #39
0
    def grad_f_ed(ed, p, last_face):

        # walk around non manifold edges
        if len(ed.link_faces) == 1:
            minv = min(ed.verts, key=geos.get)
            return minv.co, minv, None

        f = [fc for fc in ed.link_faces if fc != last_face][0]
        g = gradient_face(f, geos)
        L = f.calc_perimeter()

        # test for vert intersection
        for v in f.verts:
            v_inter, pct = intersect_point_line(v.co, p, p - L * g)

            delta = v.co - v_inter
            if delta.length < epsilon:
                print("intersect vert")
                return v.co, v, None

        tests = [e for e in f.edges if e != ed]

        for e in tests:

            v0, v1 = intersect_line_line(e.verts[0].co, e.verts[1].co, p, p - L * g)

            V = v0 - e.verts[0].co
            edV = e.verts[1].co - e.verts[0].co
            Vi = v0 - p

            if V.length - edV.length > epsilon:
                # print('intersects outside segment')
                continue
            elif V.dot(edV) < 0:
                # print('intersects behind')
                continue

            elif Vi.dot(g) > 0:  # remember we watnt to travel DOWN the gradient

                # print('shoots out the face, not across the face')
                continue

            else:

                # print('regular face edge crossing')
                return v0, e, f

        # we didn't intersect across an edge, or on a vert,
        # therefore, we should travel ALONG the edge

        vret = min(ed.verts, key=geos.get)
        return vret.co, vret, None
Beispiel #40
0
def region_2d_to_location_3d(region, rv3d, coord, depth_location):
    """
    Return a 3d location from the region relative 2d coords, aligned with
    *depth_location*.

    :arg region: region of the 3D viewport, typically bpy.context.region.
    :type region: :class:`bpy.types.Region`
    :arg rv3d: 3D region data, typically bpy.context.space_data.region_3d.
    :type rv3d: :class:`bpy.types.RegionView3D`
    :arg coord: 2d coordinates relative to the region;
       (event.mouse_region_x, event.mouse_region_y) for example.
    :type coord: 2d vector
    :arg depth_location: the returned vectors depth is aligned with this since
       there is no defined depth with a 2d region input.
    :type depth_location: 3d vector
    :return: normalized 3d vector.
    :rtype: :class:`mathutils.Vector`
    """
    from mathutils import Vector
    from mathutils.geometry import intersect_point_line

    persmat = rv3d.perspective_matrix.copy()
    viewinv = rv3d.view_matrix.inverted()
    coord_vec = region_2d_to_vector_3d(region, rv3d, coord)
    depth_location = Vector(depth_location)

    if rv3d.is_perspective:
        from mathutils.geometry import intersect_line_plane

        origin_start = viewinv.translation.copy()
        origin_end = origin_start + coord_vec
        view_vec = viewinv.col[2].copy()
        return intersect_line_plane(
            origin_start,
            origin_end,
            depth_location,
            view_vec,
            1,
        )
    else:
        dx = (2.0 * coord[0] / region.width) - 1.0
        dy = (2.0 * coord[1] / region.height) - 1.0
        persinv = persmat.inverted()
        viewinv = rv3d.view_matrix.inverted()
        origin_start = ((persinv.col[0].xyz * dx) + (persinv.col[1].xyz * dy) +
                        viewinv.translation)
        origin_end = origin_start + coord_vec
        return intersect_point_line(
            depth_location,
            origin_start,
            origin_end,
        )[0]
def getIKValues(armatureName, bone, boneEnd):
    armature_ob = bpy.context.scene.objects[armatureName]
    #armature_data = armature_ob.data
    bpy.ops.object.mode_set(mode='EDIT', toggle=False)
    eb_bone = armature_ob.data.edit_bones[bone]
    eb_boneEnd = armature_ob.data.edit_bones[boneEnd]
    line = (eb_bone.head, eb_bone.tail)
    point = eb_boneEnd.head
    intersect = intersect_point_line(point, line[0], line[1])
    distance = (intersect[0] - eb_bone.head).length
    ikEffector = Vector((distance, 0, 0))
    ikHandle = armature_ob.matrix_world * intersect[0]
    bpy.ops.object.mode_set(mode='OBJECT', toggle=False)
    return ikEffector, ikHandle
Beispiel #42
0
def region_2d_to_location_3d(region, rv3d, coord, depth_location):
    """
    Return a 3d location from the region relative 2d coords, aligned with
    *depth_location*.

    :arg region: region of the 3D viewport, typically bpy.context.region.
    :type region: :class:`bpy.types.Region`
    :arg rv3d: 3D region data, typically bpy.context.space_data.region_3d.
    :type rv3d: :class:`bpy.types.RegionView3D`
    :arg coord: 2d coordinates relative to the region;
       (event.mouse_region_x, event.mouse_region_y) for example.
    :type coord: 2d vector
    :arg depth_location: the returned vectors depth is aligned with this since
       there is no defined depth with a 2d region input.
    :type depth_location: 3d vector
    :return: normalized 3d vector.
    :rtype: :class:`mathutils.Vector`
    """
    from mathutils import Vector
    from mathutils.geometry import intersect_point_line

    persmat = rv3d.perspective_matrix.copy()
    viewinv = rv3d.view_matrix.inverted()
    coord_vec = region_2d_to_vector_3d(region, rv3d, coord)
    depth_location = Vector(depth_location)

    if rv3d.is_perspective:
        from mathutils.geometry import intersect_line_plane

        origin_start = viewinv.translation.copy()
        origin_end = origin_start + coord_vec
        view_vec = viewinv.col[2].copy()
        return intersect_line_plane(origin_start,
                                    origin_end,
                                    depth_location,
                                    view_vec, 1,
                                    )
    else:
        dx = (2.0 * coord[0] / region.width) - 1.0
        dy = (2.0 * coord[1] / region.height) - 1.0
        persinv = persmat.inverted()
        viewinv = rv3d.view_matrix.inverted()
        origin_start = ((persinv.col[0].xyz * dx) +
                        (persinv.col[1].xyz * dy) +
                         viewinv.translation)
        origin_end = origin_start + coord_vec
        return intersect_point_line(depth_location,
                                    origin_start,
                                    origin_end,
                                    )[0]
Beispiel #43
0
def point_on_edge(p, edge):
    """Find Point on Edge.

    Args:
        p:        vector
        edge:     tuple containing 2 vectors.

    Returns:
        True if point p happens to lie on the edge, False otherwise.
    """

    pt, _percent = intersect_point_line(p, *edge)
    on_line = (pt - p).length < 1.0e-5
    return on_line and (0.0 <= _percent <= 1.0)
Beispiel #44
0
    def hover(self, context, x, y):
        '''
        hovering happens in screen space, 20 pixels thresh for points, 30 for edges
        '''
        self.mouse = Vector((x, y))
        if len(self.pts) == 0:
            return

        def dist(v):
            diff = v - Vector((x, y))
            return diff.length

        loc3d_reg2D = view3d_utils.location_3d_to_region_2d
        screen_pts = [
            loc3d_reg2D(context.region, context.space_data.region_3d, pt)
            for pt in self.pts
        ]
        closest_point = min(screen_pts, key=dist)

        if (closest_point - Vector((x, y))).length < 20:
            self.hovered = ['POINT', screen_pts.index(closest_point)]
            return

        if len(self.pts) < 2:
            self.hovered = [None, -1]
            return

        for i in range(0, len(self.pts)):
            a = loc3d_reg2D(context.region, context.space_data.region_3d,
                            self.pts[i])
            next = (i + 1) % len(self.pts)
            b = loc3d_reg2D(context.region, context.space_data.region_3d,
                            self.pts[next])

            if b == 0 and not self.cyclic:
                self.hovered = [None, -1]
                return

            if a and b:
                intersect = intersect_point_line(
                    Vector((x, y)).to_3d(), a.to_3d(), b.to_3d())
                if intersect:
                    dist = (intersect[0].to_2d() - Vector(
                        (x, y))).length_squared
                    bound = intersect[1]
                    if (dist < 900) and (bound < 1) and (bound > 0):
                        self.hovered = ['EDGE', i]
                        return

        self.hovered = [None, -1]
Beispiel #45
0
        def bezier_error(self, error_max=-1.0, test_count=8):
            from mathutils.geometry import interpolate_bezier

            test_points = interpolate_bezier(self.points[0].co,
                                             self.handle_left,
                                             self.handle_right,
                                             self.points[-1].co,
                                             test_count,
                                             )

            from mathutils.geometry import intersect_point_line

            error = 0.0

            # this is a rough method measuring the error but should be ok
            # TODO. dont test against every single point.
            for co in test_points:
                # initial values
                co_best = self.points[0].co

                length_best = (co - co_best).length
                for p in self.points[1:]:
                    # dist to point
                    length = (co - p.co).length
                    if length < length_best:
                        length_best = length
                        co_best = p.co

                    p_ix, fac = intersect_point_line(co, p.co, p.prev.co)
                    p_ix = p_ix
                    if fac >= 0.0 and fac <= 1.0:
                        length = (co - p_ix).length
                        if length < length_best:
                            length_best = length
                            co_best = p_ix

                error += length_best / test_count

                if error_max != -1.0 and error > error_max:
                    return True

            if error_max != -1.0:
                return False
            else:
                return error
Beispiel #46
0
    def hover(self,context,x,y):
        '''
        hovering happens in screen space, 20 pixels thresh for points, 30 for edges
        '''
        self.mouse = Vector((x, y))
        if len(self.pts) == 0:
            return

        def dist(v):
            diff = v - Vector((x,y))
            return diff.length
        
        loc3d_reg2D = view3d_utils.location_3d_to_region_2d
        screen_pts =  [loc3d_reg2D(context.region, context.space_data.region_3d, pt) for pt in self.pts]
        closest_point = min(screen_pts, key = dist)
        
        if (closest_point - Vector((x,y))).length  < 20:
            self.hovered = ['POINT',screen_pts.index(closest_point)]
            return

        if len(self.pts) < 2: 
            self.hovered = [None, -1]
            return
                    
        for i in range(0,len(self.pts)):   
            a  = loc3d_reg2D(context.region, context.space_data.region_3d,self.pts[i])
            next = (i + 1) % len(self.pts)
            b = loc3d_reg2D(context.region, context.space_data.region_3d,self.pts[next])
            
            if b == 0 and not self.cyclic:
                self.hovered = [None, -1]
                return
            
            if a and b:
                intersect = intersect_point_line(Vector((x,y)).to_3d(), a.to_3d(),b.to_3d()) 
                if intersect:
                    dist = (intersect[0].to_2d() - Vector((x,y))).length_squared
                    bound = intersect[1]
                    if (dist < 900) and (bound < 1) and (bound > 0):
                        self.hovered = ['EDGE',i]
                        return
                    
        self.hovered = [None, -1]
def f_4(me, list_e, list_0):

    dict_1 = {vi: [] for vi in list_0}

    for i in list_e:
        lp1 = (me.vertices[i[0]].co).copy()
        lp2 = (me.vertices[i[1]].co).copy()
        for vi in list_0:
            v = (me.vertices[vi].co).copy()
        
            p1 = intersect_point_line( v, lp1, lp2)[0]
        
            me.vertices.add(1)
            me.vertices[-1].co = p1
            me.vertices[-1].select = False
            dict_1[vi].append(me.vertices[-1].index)

    n = len(list_e)
    edge_copy_1(me, dict_1, n)
    faces_copy_1(me, dict_1, n)
Beispiel #48
0
    def start_grad_f(f, p):

        g = gradient_face(f, geos)
        L = f.calc_perimeter()

        # test for vert intersection
        for v in f.verts:
            v_inter, pct = intersect_point_line(v.co, p, p - L * g)

            delta = v.co - v_inter
            if delta.length < epsilon:
                print("intersects vert")
                return v, v.co, None

        for e in f.edges:

            v0, v1 = intersect_line_line(e.verts[0].co, e.verts[1].co, p, p - L * g)

            V = v0 - e.verts[0].co
            edV = e.verts[1].co - e.verts[0].co
            Vi = v0 - p

            if V.length - edV.length > epsilon:
                # print('intersects outside segment')
                continue
            elif V.dot(edV) < 0:
                # print('intersects behind')
                continue

            elif Vi.dot(g) > 0:  # remember we watnt to travel DOWN the gradient
                # print('shoots out the face, not across the face')
                continue
            else:
                # print('regular face edge crossing')
                return v0, e, f

        # we didn't intersect across an edge, or on a vert,
        # therefore, we should travel ALONG the edge

        vret = min(f.verts, key=geos.get)
        return vret.co, vret, None
def perp_vector_point_line(pt1, pt2, ptn):
    '''
    Vector bwettn pointn and line between point1
    and point2
    args:
        pt1, and pt1 are Vectors representing line segment
    
    return Vector
    
    pt1 ------------------- pt
            ^
            |
            |
            |<-----this vector
            |
            ptn
    '''
    pt_on_line = intersect_point_line(ptn, pt1, pt2)[0]
    alt_vect = pt_on_line - ptn
    
    return alt_vect
 def testGroundCell(self):   
     #test distance of closest point on poly to cell center,
     #if it is in range, cell becomes groundcell
     #if neighbors opposite to each other both are groundcells, cell itself
     #becomes groundcell too
     
     #print ("In testGroundCell") 
     if self.grid.grounds == None:
         return None
            
     for ground in self.grid.grounds:
       #  print ("GROUND/EDGE: ", ground, ground.edges)
         for edge in ground.edges:
             closest = geometry.intersect_point_line(Vector(self.center), 
                       Vector(edge[0]), Vector(edge[1]))
             vec = closest[0]
             percentage = closest[1]
            # print(vec.to_tuple(), self.center, self.gridPos)
             if self.isInside(vec.to_tuple(), percentage) and not self.isGroundCell:
                 print("Found Ground Cell: ", self.gridPos, vec, percentage)
                 self.isGroundCell = True                        
 def execute(self, context):
     edit_mode_out()
     ob_act = context.active_object
     me = ob_act.data
     list_0 = [v.index for v in me.vertices if v.select]
     
     if len(va_buf.list_v) != 2:
         self.report({'INFO'}, 'Two guide vertices must be stored in memory.')
         edit_mode_in()
         return {'CANCELLED'}
     elif len(va_buf.list_v) > 1:
         if len(list_0) == 0:
             self.report({'INFO'}, 'No vertices selected')
             edit_mode_in()
             return {'CANCELLED'}
         elif len(list_0) != 0:
             p1 = (me.vertices[va_buf.list_v[0]].co).copy()
             p2 = (me.vertices[va_buf.list_v[1]].co).copy()
             for i in list_0:
                 v = (me.vertices[i].co).copy()
                 me.vertices[i].co = intersect_point_line( v, p1, p2)[0]
     edit_mode_in()
     return {'FINISHED'}
def com_line_cross_test(com1, com2, pt, no, factor = 2):
    '''
    test used to make sure a cut is reasoably between
    2 other cuts
    
    higher factor requires better aligned cuts
    '''
    
    v = intersect_line_plane(com1,com2,pt,no)
    if v:
        #if the distance between the intersection is less than
        #than 1/factor the distance between the current pair
        #than this pair is invalide because there is a loop
        #in between
        check = intersect_point_line(v,com1,com2)
        invalid_length = (com2 - com1).length/factor  #length beyond which an intersection is invalid
        test_length = (v - pt).length
        
        #this makes sure the plane is between A and B
        #meaning the test plane is between the two COM's
        in_between = check[1] >= 0 and check[1] <= 1
        
        if in_between and test_length < invalid_length:
            return True
Beispiel #53
0
def distance_point_line(pt, line_p1, line_p2):
    int_co = intersect_point_line(pt, line_p1, line_p2)
    distance_vector = int_co[0] - pt
    return distance_vector
Beispiel #54
0
    def process(self):
        verts = self.inputs['Vertices'].sv_get()

        if self.inputs['PolyEdge'].is_linked:
            poly_edge = self.inputs['PolyEdge'].sv_get()
            poly_in = True
        else:
            poly_in = False
            poly_edge = repeat_last([[]])

        verts_out = []
        poly_edge_out = []
        item_order = []

        poly_output = poly_in and self.outputs['PolyEdge'].is_linked
        order_output = self.outputs['Item order'].is_linked
        vert_output = self.outputs['Vertices'].is_linked

        if not any((vert_output, order_output, poly_output)):
            return

        if self.mode == 'XYZ':
            # should be user settable
            op_order = [(0, False),
                        (1, False),
                        (2, False)]

            for v, p in zip(verts, poly_edge):
                s_v = ((e[0], e[1], e[2], i) for i, e in enumerate(v))

                for item_index, rev in op_order:
                    s_v = sorted(s_v, key=itemgetter(item_index), reverse=rev)

                verts_out.append([v[:3] for v in s_v])

                if poly_output:
                    v_index = {item[-1]: j for j, item in enumerate(s_v)}
                    poly_edge_out.append([list(map(lambda n:v_index[n], pe)) for pe in p])
                if order_output:
                    item_order.append([i[-1] for i in s_v])

        if self.mode == 'DIST':
            if self.inputs['Base Point'].is_linked:
                base_points = self.inputs['Base Point'].sv_get()
                bp_iter = repeat_last(base_points[0])
            else:
                bp = [(0, 0, 0)]
                bp_iter = repeat_last(bp)

            for v, p, v_base in zip(verts, poly_edge, bp_iter):
                s_v = sorted(((v_c, i) for i, v_c in enumerate(v)), key=lambda v: distK(v[0], v_base))
                verts_out.append([vert[0] for vert in s_v])

                if poly_output:
                    v_index = {item[-1]: j for j, item in enumerate(s_v)}
                    poly_edge_out.append([list(map(lambda n:v_index[n], pe)) for pe in p])
                if order_output:
                    item_order.append([i[-1] for i in s_v])

        if self.mode == 'AXIS':
            if self.inputs['Mat'].is_linked:
                mat = Matrix_generate(self.inputs['Mat'].sv_get())
            else:
                mat = [Matrix. Identity(4)]
            mat_iter = repeat_last(mat)

            def f(axis, q):
                if axis.dot(q.axis) > 0:
                    return q.angle
                else:
                    return -q.angle

            for v, p, m in zip(Vector_generate(verts), poly_edge, mat_iter):
                axis = m * Vector((0, 0, 1))
                axis_norm = m * Vector((1, 0, 0))
                base_point = m * Vector((0, 0, 0))
                intersect_d = [intersect_point_line(v_c, base_point, axis) for v_c in v]
                rotate_d = [f(axis, (axis_norm + v_l[0]).rotation_difference(v_c)) for v_c, v_l in zip(v, intersect_d)]
                s_v = ((data[0][1], data[1], i) for i, data in enumerate(zip(intersect_d, rotate_d)))
                s_v = sorted(s_v, key=itemgetter(0, 1))

                verts_out.append([v[i[-1]].to_tuple() for i in s_v])

                if poly_output:
                    v_index = {item[-1]: j for j, item in enumerate(s_v)}
                    poly_edge_out.append([list(map(lambda n:v_index[n], pe)) for pe in p])
                if order_output:
                    item_order.append([i[-1] for i in s_v])

        if self.mode == 'USER':
            if self.inputs['Index Data'].is_linked:
                index = self.inputs['Index Data'].sv_get()
            else:
                return

            for v, p, i in zip(verts, poly_edge, index):

                s_v = sorted([(data[0], data[1], i) for i, data in enumerate(zip(i, v))], key=itemgetter(0))

                verts_out.append([obj[1] for obj in s_v])

                if poly_output:
                    v_index = {item[-1]: j for j, item in enumerate(s_v)}
                    poly_edge_out.append([[v_index[k] for k in pe] for pe in p])
                if order_output:
                    item_order.append([i[-1] for i in s_v])

        if self.mode == 'CONNEX':
            if self.inputs['PolyEdge'].is_linked:
                edges = self.inputs['PolyEdge'].sv_get()
                for v, p in zip(verts, edges):
                    pols = []
                    if len(p[0]) > 2:
                        pols = [p[:]]
                        p = pols_edges([p], True)[0]

                    vect_new, pol_edge_new, index_new = sort_vertices_by_connexions(v, p, self.limit_mode)
                    if len(pols) > 0:
                        new_pols = []
                        for pol in pols[0]:
                            new_pol = []
                            for i in pol:
                                new_pol.append(index_new.index(i))
                            new_pols.append(new_pol)
                        pol_edge_new = [new_pols]

                    verts_out.append(vect_new)
                    poly_edge_out.append(pol_edge_new)
                    item_order.append(index_new)

        if vert_output:
            self.outputs['Vertices'].sv_set(verts_out)
        if poly_output:
            self.outputs['PolyEdge'].sv_set(poly_edge_out)
        if order_output:
            self.outputs['Item order'].sv_set(item_order)
def handleManipulator(objs, target):
	# start move
	if logic.mouse.events[events.LEFTMOUSE] == inputActivated and target and target.name in ["x", "y", "z", "widget"]:
		logic.moving = target
		centerPos = logic.viewCamObject.getScreenPosition(logic.scene.objects["widget"])
		logic.mousePosOffset = [logic.mouse.position[0]-centerPos[0], logic.mouse.position[1]-centerPos[1]]
		logic.undo.append("Moved")

	elif logic.mouse.events[events.LEFTMOUSE] == inputActivated and target and target.name in ["rx", "ry", "rz"]:
		logic.rotating = target
		logic.undo.append("Rotated")
		logic.rotatingAmount = [0,0,0]


	# while moving widget
	elif logic.mouse.events[events.LEFTMOUSE] == inputActive and logic.moving:

		# setup variables for ray/ray intersect
		# compute camera pos
		camPos = logic.viewCamObject.worldPosition
		v1 = Vector(camPos)

		# if 'win' in releaseOS:
		# 	print("h")		#http://projects.blender.org/tracker/index.php?func=detail&aid=33943&group_id=9&atid=306

		# compute camera ray end pos
		offsettedPos = [logic.mouse.position[0]-logic.mousePosOffset[0], logic.mouse.position[1]-logic.mousePosOffset[1]]
		vec = logic.viewCamObject.getScreenVect(*offsettedPos)
		camProjPos = list(camPos[:])
		camProjPos[0] -= vec[0] * 500
		camProjPos[1] -= vec[1] * 500
		camProjPos[2] -= vec[2] * 500
		v2 = Vector(camProjPos)

		# compute widget pos
		widgetPos = logic.widgetObject.worldPosition
		v3 = Vector(widgetPos)

		# compute widget ray end pos
		mat = logic.widgetObject.worldTransform

		if logic.moving.name == 'x':
			transMat = Matrix.Translation(Vector((500,0,0)))
		elif logic.moving.name == 'y':
			transMat = Matrix.Translation(Vector((0,500,0)))
		elif logic.moving.name == 'z':
			transMat = Matrix.Translation(Vector((0,0,500)))
		else:
			transMat = Matrix.Translation(Vector((0,0,0)))

		# merge orientation/scaling with new translation
		extendedMat = mat*transMat
		v4 = extendedMat.translation

		# compute ray/ray interset, return list of tuples
		# ...for the closest point on each line to each other
		result = geometry.intersect_line_line(v1, v2, v3, v4)
		try:
			widgetTargetPos = result[1]									# this is where the widget should be
		except:
			pass

		# special case for moving center widget
		if logic.moving.name == 'widget':
			result = geometry.intersect_point_line(widgetPos, v1, v2)
			widgetTargetPos = list(result[0])

		# apply transform
		logic.pivotObject.worldPosition = widgetTargetPos
		logic.widgetObject.worldPosition = widgetTargetPos

	# while rotating widget
	elif logic.mouse.events[events.LEFTMOUSE] == inputActive and logic.rotating:
		rot = list(logic.widgetObject.worldOrientation.to_euler()[0:3])
		x = logic.mousePosDelta[0] * 10.0
		y = logic.mousePosDelta[1] * 10.0

		# flip axis
		camAlignment = 1
		widgetAlignment = 1

		# compute screenspace mouse position relative to widget centre
		# i.e. which quadrant the mouse is relative to the widget centre
		widgetPosXY = list(logic.viewCamObject.getScreenPosition(logic.widgetObject))
		mousePosXY = logic.mouse.position
		diffXY = (widgetPosXY[0]-mousePosXY[0], widgetPosXY[1]-mousePosXY[1])

		if logic.rotating.name == "rx":
			if logic.viewCamObject.worldPosition[0] > 0:
				camAlignment = -1
			if diffXY[1] < 0:
				widgetAlignment = -1
			rot[0] += x*camAlignment*widgetAlignment
			if diffXY[0] < 0:
				widgetAlignment = 1
			else:
				widgetAlignment = -1
			rot[0] += y*camAlignment*widgetAlignment

		elif logic.rotating.name == "ry":
			if logic.viewCamObject.worldPosition[1] > 0:
				camAlignment = -1
			if diffXY[1] < 0:
				widgetAlignment = -1
			rot[1] += x * camAlignment*widgetAlignment
			if diffXY[0] < 0:
				widgetAlignment = 1
			else:
				widgetAlignment = -1
			rot[1] += y * camAlignment*widgetAlignment

		elif logic.rotating.name == "rz":
			rot[2] += x * camAlignment * widgetAlignment


		# integrate over time (for the duration of the mouse interaction)
		logic.rotatingAmount[0] += rot[0]
		logic.rotatingAmount[1] += rot[1]
		logic.rotatingAmount[2] += rot[2]

		#apply transform
		logic.pivotObject.worldOrientation = rot
		logic.widgetObject.worldOrientation = rot

	# finish
	elif logic.mouse.events[events.LEFTMOUSE] == inputDeactivated and (logic.moving or logic.rotating or logic.mouseLock == 0):
		if logic.moving:
			logic.pluggable.edit.moved.notify()
		if logic.rotating:
			logic.pluggable.edit.rotated.notify()


		# set manipulation flags to false
		logic.moving = False
		logic.rotating = False

		# saves all keyframe for current slide
		# do before removing parents
		logic.mvb.slides[logic.mvb.activeSlide].capture()

		# unlink obj(s) to pivot
		for obj in logic.pivotObject.children:
			obj.removeParent()

		logic.rotatingAmount = [0,0,0]


	# set mouseLock state
	if logic.moving or logic.rotating:
		logic.mouseLock = 2
	else:
		logic.mouseLock = 0
    def modal(self, context, event):
        if context.area:
            context.area.tag_redraw()
            
        if event.ctrl and event.type == 'Z' and event.value == 'PRESS':
            bpy.ops.ed.undo()
            self.vector_constrain = None
            self.list_verts_co = []
            self.list_verts = []
            self.list_edges = []
            self.list_faces = []
            self.obj = bpy.context.active_object
            self.obj_matrix = self.obj.matrix_world.copy()
            self.bm = bmesh.from_edit_mesh(self.obj.data)
            return {'RUNNING_MODAL'}

        if event.type == 'MOUSEMOVE' or self.bool_update:
            if self.rv3d.view_matrix != self.rotMat:
                self.rotMat = self.rv3d.view_matrix.copy()
                self.bool_update = True
            else:
                self.bool_update = False

            if self.bm.select_history:
                self.geom = self.bm.select_history[0]
            else: #See IndexError or AttributeError:
                self.geom = None

            x, y = (event.mouse_region_x, event.mouse_region_y)
            if self.geom:
                self.geom.select = False
                self.bm.select_history.clear()

            bpy.ops.view3d.select(location=(x, y))

            if self.list_verts != []:
                previous_vert = self.list_verts[-1]
            else:
                previous_vert = None
            
            
            outer_verts = self.outer_verts and not self.keytab

            snap_utilities(self, 
                context, 
                self.obj_matrix,
                self.geom,
                self.bool_update,
                (x, y),
                outer_verts = self.outer_verts,
                constrain = self.vector_constrain,
                previous_vert = previous_vert,
                ignore_obj = self.obj,
                increment = self.incremental,
                )
            
            if self.snap_to_grid and self.type == 'OUT':
                loc = self.location/self.rd
                self.location = Vector((round(loc.x),
                                        round(loc.y),
                                        round(loc.z)))*self.rd

            if self.keyf8 and self.list_verts_co:
                lloc = self.list_verts_co[-1]
                orig, view_vec = region_2d_to_orig_and_view_vector(self.region, self.rv3d, (x, y))
                location = intersect_point_line(lloc, orig, (orig+view_vec))
                vec = (location[0] - lloc)
                ax, ay, az = abs(vec.x),abs(vec.y),abs(vec.z)
                vec.x = ax > ay > az or ax > az > ay
                vec.y = ay > ax > az or ay > az > ax
                vec.z = az > ay > ax or az > ax > ay
                if vec == Vector():
                    self.vector_constrain = None
                else:
                    vc = lloc+vec
                    try:
                        if vc != self.vector_constrain[1]:
                            type = 'X' if vec.x else 'Y' if vec.y else 'Z' if vec.z else 'shift'
                            self.vector_constrain = [lloc, vc, type]
                    except:
                        type = 'X' if vec.x else 'Y' if vec.y else 'Z' if vec.z else 'shift'
                        self.vector_constrain = [lloc, vc, type]

        elif event.value == 'PRESS':
            if event.type in self.constrain_keys:
                self.bool_update = True
                if self.vector_constrain and self.vector_constrain[2] == event.type:
                    self.vector_constrain = ()

                else:
                    if event.shift:
                        if isinstance(self.geom, bmesh.types.BMEdge):
                            if self.list_verts:
                                loc = self.list_verts_co[-1]
                                self.vector_constrain = (loc, loc + self.list_verts_co[-1] - self.list_verts_co[0], event.type)
                            else:
                                self.vector_constrain = [self.obj_matrix * v.co for v in self.geom.verts]+[event.type]
                    else:
                        if self.list_verts:
                            loc = self.list_verts_co[-1]
                        else:
                            loc = self.location
                        self.vector_constrain = [loc, loc + self.constrain_keys[event.type]]+[event.type]

            if self.list_verts_co and (event.ascii in CharMap.ascii or event.type in CharMap.type):
                CharMap.modal(self, context, event)
                #print(self.length_entered)
                
            elif event.type == 'LEFTMOUSE':
                # SNAP 2D
                snap_3d = self.location
                Lsnap_3d = self.obj_matrix.inverted()*snap_3d
                Snap_2d = location_3d_to_region_2d(self.region, self.rv3d, snap_3d)
                if self.vector_constrain and isinstance(self.geom, bmesh.types.BMVert): # SELECT FIRST
                    bpy.ops.view3d.select(location=(int(Snap_2d[0]), int(Snap_2d[1])))
                    try:
                        geom2 = self.bm.select_history[0]
                    except: # IndexError or AttributeError:
                        geom2 = None
                else:
                    geom2 = self.geom
                self.vector_constrain = None
                self.list_verts_co = draw_line(self, self.obj, self.bm, geom2, Lsnap_3d)
                bpy.ops.ed.undo_push(message="Undo draw line*")

            elif event.type == 'TAB':
                self.keytab = self.keytab == False
                if self.keytab:            
                    context.tool_settings.mesh_select_mode = (False, False, True)
                else:
                    context.tool_settings.mesh_select_mode = (True, True, True)

            elif event.type == 'F8':
                self.vector_constrain = None
                self.keyf8 = self.keyf8 == False

        elif event.value == 'RELEASE':
            if event.type in {'RET', 'NUMPAD_ENTER'}:
                if self.length_entered != "" and self.list_verts_co:
                    try:
                        text_value = bpy.utils.units.to_value(self.unit_system, 'LENGTH', self.length_entered)
                        vector = (self.location-self.list_verts_co[-1]).normalized()
                        location = (self.list_verts_co[-1]+(vector*text_value))
                        G_location = self.obj_matrix.inverted()*location
                        self.list_verts_co = draw_line(self, self.obj, self.bm, self.geom, G_location)
                        self.length_entered = ""
                        self.vector_constrain = None

                    except:# ValueError:
                        self.report({'INFO'}, "Operation not supported yet")

            elif event.type in {'RIGHTMOUSE', 'ESC'}:
                if self.list_verts_co == [] or event.type == 'ESC':                
                    bpy.types.SpaceView3D.draw_handler_remove(self._handle, 'WINDOW')
                    context.tool_settings.mesh_select_mode = self.select_mode
                    context.area.header_text_set()
                    context.user_preferences.view.use_rotate_around_active = self.use_rotate_around_active
                    if not self.is_editmode:
                        bpy.ops.object.editmode_toggle()
                    return {'FINISHED'}
                else:
                    self.vector_constrain = None
                    self.list_verts = []
                    self.list_verts_co = []
                    self.list_faces = []
                    
        a = ""        
        if self.list_verts_co:
            if self.length_entered:
                pos = self.line_pos
                a = 'length: '+ self.length_entered[:pos] + '|' + self.length_entered[pos:]
            else:
                length = self.len
                length = convert_distance(length, self.uinfo)
                a = 'length: '+ length
        context.area.header_text_set("hit: %.3f %.3f %.3f %s" % (self.location[0], self.location[1], self.location[2], a))

        self.modal_navigation(context, event)
        return {'RUNNING_MODAL'}
def snap_utilities(self,
    context,
    obj_matrix_world,
    bm_geom,
    bool_update,
    mcursor,
    outer_verts = False,
    constrain = None,
    previous_vert = None,
    ignore_obj = None,
    increment = 0.0):

    rv3d = context.region_data
    region = context.region
    is_increment = False

    if not hasattr(self, 'snap_cache'):
        self.snap_cache = True
        self.type = 'OUT'
        self.bvert = None
        self.bedge = None
        self.bface = None
        self.hit = False
        self.out_obj = None

    if bool_update:
        #self.bvert = None
        self.bedge = None
        #self.bface = None

    if isinstance(bm_geom, bmesh.types.BMVert):
        self.type = 'VERT'

        if self.bvert != bm_geom:
            self.bvert = bm_geom
            self.vert = obj_matrix_world * self.bvert.co
            #self.Pvert = location_3d_to_region_2d(region, rv3d, self.vert)
        
        if constrain:
            #self.location = (self.vert-self.const).project(vector_constrain) + self.const
            location = intersect_point_line(self.vert, constrain[0], constrain[1])
            #factor = location[1]
            self.location = location[0]
        else:
            self.location = self.vert

    elif isinstance(bm_geom, bmesh.types.BMEdge):
        if self.bedge != bm_geom:
            self.bedge = bm_geom
            self.vert0 = obj_matrix_world*self.bedge.verts[0].co
            self.vert1 = obj_matrix_world*self.bedge.verts[1].co
            self.po_cent = (self.vert0+self.vert1)/2
            self.Pcent = location_3d_to_region_2d(region, rv3d, self.po_cent)
            self.Pvert0 = location_3d_to_region_2d(region, rv3d, self.vert0)
            self.Pvert1 = location_3d_to_region_2d(region, rv3d, self.vert1)
        
            if previous_vert and previous_vert not in self.bedge.verts:
                    pvert_co = obj_matrix_world*previous_vert.co
                    point_perpendicular = intersect_point_line(pvert_co, self.vert0, self.vert1)
                    self.po_perp = point_perpendicular[0]
                    #factor = point_perpendicular[1] 
                    self.Pperp = location_3d_to_region_2d(region, rv3d, self.po_perp)

        if constrain:
            location = intersect_line_line(constrain[0], constrain[1], self.vert0, self.vert1)
            if location == None:
                is_increment = True
                orig, view_vector = region_2d_to_orig_and_view_vector(region, rv3d, mcursor)
                end = orig + view_vector
                location = intersect_line_line(constrain[0], constrain[1], orig, end)
            self.location = location[0]
        
        elif hasattr(self, 'Pperp') and abs(self.Pperp[0]-mcursor[0]) < 10 and abs(self.Pperp[1]-mcursor[1]) < 10:
            self.type = 'PERPENDICULAR'
            self.location = self.po_perp

        elif abs(self.Pcent[0]-mcursor[0]) < 10 and abs(self.Pcent[1]-mcursor[1]) < 10:
            self.type = 'CENTER'
            self.location = self.po_cent

        else:
            if increment and previous_vert in self.bedge.verts:
                is_increment = True
            self.type = 'EDGE'
            orig, view_vector = region_2d_to_orig_and_view_vector(region, rv3d, mcursor)
            end = orig + view_vector
            self.location = intersect_line_line(self.vert0, self.vert1, orig, end)[0]

    elif isinstance(bm_geom, bmesh.types.BMFace):
        is_increment = True
        self.type = 'FACE'

        if self.bface != bm_geom:
            self.bface = bm_geom
            self.face_center = obj_matrix_world*bm_geom.calc_center_median()
            self.face_normal = bm_geom.normal*obj_matrix_world.inverted()

        orig, view_vector = region_2d_to_orig_and_view_vector(region, rv3d, mcursor)
        end = orig + view_vector
        location = intersect_line_plane(orig, end, self.face_center, self.face_normal, False)
        if constrain:
            is_increment = False
            location = intersect_point_line(location, constrain[0], constrain[1])[0]

        self.location = location

    else:
        is_increment = True
        self.type = 'OUT'

        orig, view_vector = region_2d_to_orig_and_view_vector(region, rv3d, mcursor)
        end = orig + view_vector * 1000

        if not outer_verts or self.out_obj == None:
            result, self.out_obj, self.out_mat, self.location, normal = context.scene.ray_cast(orig, end)
            self.out_mat_inv = self.out_mat.inverted()
            #print(self.location)

        if self.out_obj and self.out_obj != ignore_obj:
            self.type = 'FACE'
            if outer_verts:
                # get the ray relative to the self.out_obj
                ray_origin_obj = self.out_mat_inv * orig
                ray_target_obj = self.out_mat_inv * end
                location, normal, face_index = self.out_obj.ray_cast(ray_origin_obj, ray_target_obj)
                if face_index == -1:
                    self.out_obj = None
                else:
                    self.location = self.out_mat*location
                    try:
                        verts = self.out_obj.data.polygons[face_index].vertices
                        v_dist = 100

                        for i in verts:
                            v_co = self.out_mat*self.out_obj.data.vertices[i].co
                            v_2d = location_3d_to_region_2d(region, rv3d, v_co)
                            dist = (Vector(mcursor)-v_2d).length_squared
                            if dist < v_dist:
                                is_increment = False
                                self.type = 'VERT'
                                v_dist = dist
                                self.location = v_co
                    except:
                        print('Fail')
            if constrain:
                is_increment = False
                self.preloc = self.location
                self.location = intersect_point_line(self.preloc, constrain[0], constrain[1])[0]
        else:
            if constrain:
                self.location = intersect_line_line(constrain[0], constrain[1], orig, end)[0]
            else:
                self.location = out_Location(rv3d, region, orig, view_vector)

    if previous_vert:
        pvert_co = obj_matrix_world*previous_vert.co
        vec = self.location - pvert_co
        if is_increment and increment:
            pvert_co = obj_matrix_world*previous_vert.co
            vec = self.location - pvert_co
            self.len = round((1/increment)*vec.length)*increment
            self.location = self.len*vec.normalized() + pvert_co
        else:
            self.len = vec.length
def intersect_boundbox_threshold(sctx, MVP, ray_origin_local, ray_direction_local, bbmin, bbmax):
    local_bvmin = Vector()
    local_bvmax = Vector()
    tmin = Vector()
    tmax = Vector()

    if (ray_direction_local[0] < 0.0):
        local_bvmin[0] = bbmax[0]
        local_bvmax[0] = bbmin[0]
    else:
        local_bvmin[0] = bbmin[0]
        local_bvmax[0] = bbmax[0]

    if (ray_direction_local[1] < 0.0):
        local_bvmin[1] = bbmax[1]
        local_bvmax[1] = bbmin[1]
    else:
        local_bvmin[1] = bbmin[1]
        local_bvmax[1] = bbmax[1]

    if (ray_direction_local[2] < 0.0):
        local_bvmin[2] = bbmax[2]
        local_bvmax[2] = bbmin[2]
    else:
        local_bvmin[2] = bbmin[2]
        local_bvmax[2] = bbmax[2]

    if (ray_direction_local[0]):
        tmin[0] = (local_bvmin[0] - ray_origin_local[0]) / ray_direction_local[0]
        tmax[0] = (local_bvmax[0] - ray_origin_local[0]) / ray_direction_local[0]
    else:
        tmin[0] = sctx.depth_range[0]
        tmax[0] = sctx.depth_range[1]

    if (ray_direction_local[1]):
        tmin[1] = (local_bvmin[1] - ray_origin_local[1]) / ray_direction_local[1]
        tmax[1] = (local_bvmax[1] - ray_origin_local[1]) / ray_direction_local[1]
    else:
        tmin[1] = sctx.depth_range[0]
        tmax[1] = sctx.depth_range[1]

    if (ray_direction_local[2]):
        tmin[2] = (local_bvmin[2] - ray_origin_local[2]) / ray_direction_local[2]
        tmax[2] = (local_bvmax[2] - ray_origin_local[2]) / ray_direction_local[2]
    else:
        tmin[2] = sctx.depth_range[0]
        tmax[2] = sctx.depth_range[1]

    # `va` and `vb` are the coordinates of the AABB edge closest to the ray #
    va = Vector()
    vb = Vector()
    # `rtmin` and `rtmax` are the minimum and maximum distances of the ray hits on the AABB #

    if ((tmax[0] <= tmax[1]) and (tmax[0] <= tmax[2])):
        rtmax = tmax[0]
        va[0] = vb[0] = local_bvmax[0]
        main_axis = 3
    elif ((tmax[1] <= tmax[0]) and (tmax[1] <= tmax[2])):
        rtmax = tmax[1]
        va[1] = vb[1] = local_bvmax[1]
        main_axis = 2
    else:
        rtmax = tmax[2]
        va[2] = vb[2] = local_bvmax[2]
        main_axis = 1

    if ((tmin[0] >= tmin[1]) and (tmin[0] >= tmin[2])):
        rtmin = tmin[0]
        va[0] = vb[0] = local_bvmin[0]
        main_axis -= 3
    elif ((tmin[1] >= tmin[0]) and (tmin[1] >= tmin[2])):
        rtmin = tmin[1]
        va[1] = vb[1] = local_bvmin[1]
        main_axis -= 1
    else:
        rtmin = tmin[2]
        va[2] = vb[2] = local_bvmin[2]
        main_axis -= 2

    if (main_axis < 0):
        main_axis += 3

#ifdef IGNORE_BEHIND_RAY
    depth_max = depth_get(local_bvmax, ray_origin_local, ray_direction_local)
    if (depth_max < sctx.depth_range[0]):
        return False
#endif

    if (rtmin <= rtmax):
        # if rtmin < rtmax, ray intersect `AABB` #
        return True

    if (ray_direction_local[main_axis] < 0.0):
        va[main_axis] = local_bvmax[main_axis]
        vb[main_axis] = local_bvmin[main_axis]

    else:
        va[main_axis] = local_bvmin[main_axis]
        vb[main_axis] = local_bvmax[main_axis]

    win_half = sctx.winsize * 0.5

    scale = abs(local_bvmax[main_axis] - local_bvmin[main_axis])

    va2d = Vector((
        (MVP[0].xyz.dot(va) + MVP[0][3]),
        (MVP[1].xyz.dot(va) + MVP[1][3]),
    ))

    vb2d = Vector((
        (va2d[0] + MVP[0][main_axis] * scale),
        (va2d[1] + MVP[1][main_axis] * scale),
    ))

    depth_a = MVP[3].xyz.dot(va) + MVP[3][3]
    depth_b = depth_a + MVP[3][main_axis] * scale

    va2d /= depth_a
    vb2d /= depth_b

    va2d[0] = (va2d[0] + 1.0) * win_half[0]
    va2d[1] = (va2d[1] + 1.0) * win_half[1]
    vb2d[0] = (vb2d[0] + 1.0) * win_half[0]
    vb2d[1] = (vb2d[1] + 1.0) * win_half[1]

    p, fac = intersect_point_line(sctx.mval, va2d, vb2d)
    if fac < 0.0:
        return (sctx.mval - va2d).length_squared < sctx._dist_px_sq
    elif fac > 1.0:
        return (sctx.mval - vb2d).length_squared < sctx._dist_px_sq
    else:
        return (sctx.mval - p).length_squared < sctx._dist_px_sq