コード例 #1
0
ファイル: tests.py プロジェクト: jacrocitto/RayCaster
 def test_determine_diffuse_contribution(self):
     sphere = data.Sphere(data.Point(0, 0, 0), 1, data.Color(0.5, 0.7, 0.8), data.Finish(0.5, 0.5, 0.5, 0.05))
     light = data.Light(data.Point(0, 0, 100), data.Color(1.5, 1.2, 1.3))
     inter_point = data.Point(0, 0, 1)
     inter_list = [
         (
             data.Sphere(data.Point(0, 0, 102), 1, data.Color(0.5, 0.7, 0.8), data.Finish(0.5, 0.5, 0.5, 0.05)),
             data.Point(0, 0, 101),
         )
     ]
     normal = collisions.sphere_normal_at_point(sphere, inter_point)
     off_pt = cast.find_pt_off_sphere(inter_point, normal)
     dir_vect = vector_math.normalize_vector(vector_math.vector_from_to(off_pt, light.pt))
     ray = data.Ray(off_pt, dir_vect)
     sphere_list = []
     l_dir = vector_math.normalize_vector(vector_math.vector_from_to(off_pt, light.pt))
     l_dot_n = vector_math.dot_vector(normal, l_dir)
     result = cast.determine_diffuse_contribution(sphere, off_pt, light, normal, sphere_list, l_dir, l_dot_n)
     self.assertEqual(
         result[0], cast.get_diffuse_contribution(sphere, light, ray, inter_list, normal, dir_vect, off_pt)[0]
     )
     self.assertEqual(
         result[1], cast.get_diffuse_contribution(sphere, light, ray, inter_list, normal, dir_vect, off_pt)[1]
     )
     self.assertEqual(
         result[2], cast.get_diffuse_contribution(sphere, light, ray, inter_list, normal, dir_vect, off_pt)[2]
     )
コード例 #2
0
 def test_vectorToFrom_1(self):
   p1 = data.Point(1,2,3)
   p2 = data.Point(0,0,0)
   v1 = vector_math.vector_from_to(p1, p2)
   v2 = vector_math.vector_from_to(p2, p1)
   equals1 = data.Vector(-1, -2, -3)
   equals2 = vector_math.scale_vector(v1, -1)
   self.assertEqual(v1 == equals1, True)
   self.assertEqual(v2 == equals2, True)
   pass
コード例 #3
0
ファイル: cast.py プロジェクト: blueostrich/cpe101
def cast_ray(ray, sphere_list, color, light):
    """Find the rendered color at the nearest intersection point along ray"""
    nearest = closest_intersect(ray, sphere_list)
    if not nearest:
        # No intersection, return white
        return Color(1.0, 1.0, 1.0)
    point, sphere = nearest

    # Compute initial ambient colors
    r = sphere.color.r * sphere.finish.ambient * color.r
    g = sphere.color.g * sphere.finish.ambient * color.g
    b = sphere.color.b * sphere.finish.ambient * color.b

    # Calculate diffuse value
    normal = sphere_normal_at_point(sphere, point)
    to_light = normalize_vector(vector_from_to(point, light.pt))
    l_dot = dot_vector(normal, to_light)
    diffuse = sphere.finish.diffuse * l_dot
    if diffuse < 0:
        diffuse = 0
    else:
        # Check for shadows
        new_point = translate_point(point, scale_vector(normal, 0.01))
        light_ray = Ray(new_point, to_light)
        shadow_intersect = closest_intersect(light_ray, sphere_list)
        if (shadow_intersect and
                length_vector_sq(vector_from_to(new_point, shadow_intersect[0]))
                < length_vector_sq(vector_from_to(new_point, light.pt))):
            diffuse = 0

    # Add diffuse to existing colors
    r += sphere.color.r * diffuse * light.color.r
    g += sphere.color.g * diffuse * light.color.g
    b += sphere.color.b * diffuse * light.color.b

    # Compute specular intensity
    if diffuse > 0:
        reflection = difference_vector(to_light, scale_vector(normal, 2 * l_dot))
        intensity = dot_vector(reflection, normalize_vector(ray.dir))
        power = 1. / sphere.finish.roughness
        if intensity > 0:
            r += light.color.r * sphere.finish.specular * intensity ** power
            g += light.color.g * sphere.finish.specular * intensity ** power
            b += light.color.b * sphere.finish.specular * intensity ** power

    # Max out colors at 1.0
    if r > 1:
        r = 1
    if g > 1:
        g = 1
    if b > 1:
        b = 1

    return Color(r, g, b)
コード例 #4
0
ファイル: cast.py プロジェクト: mattpiasecki/RayCaster
def find_closest(inter,ray):
	close = vector_math.length_vector(vector_math.vector_from_to(ray.pt,inter[0][1]))
	sphere = inter[0][0]
	point = inter[0][1]
	for (s,p) in inter:
		distance = vector_math.length_vector(vector_math.vector_from_to(ray.pt,p))
		if close > distance:
			close = distance
			sphere = s
			point = p
	return sphere, point
コード例 #5
0
ファイル: cast.py プロジェクト: 14bmkelley/raytracer-python
def cast_ray(ray, sphere_list, amb, light, eye_point):
    result_color = data.Color(1.0, 1.0, 1.0)
    # test for closest sphere to the eye
    collision_tuple = find_closest_collision(ray, sphere_list)
    if collision_tuple:
        # some useful variables
        sphere_hit = collision_tuple[0]
        sphere_hit_point = collision_tuple[1]
        # basic color before manipulation
        result_r = sphere_hit.color.r * sphere_hit.finish.amb * amb.r
        result_g = sphere_hit.color.g * sphere_hit.finish.amb * amb.g
        result_b = sphere_hit.color.b * sphere_hit.finish.amb * amb.b
        # computing light intensity
        sphere_vector = vector_math.vector_from_to(sphere_hit.center, sphere_hit_point)
        sphere_normal = vector_math.normalize_vector(sphere_vector)

        scaled_normal = vector_math.scale_vector(sphere_normal, 0.01)
        hit_point = vector_math.translate_point(sphere_hit_point, scaled_normal)

        light_vector = vector_math.vector_from_to(hit_point, light.pt)
        light_normal = vector_math.normalize_vector(light_vector)

        light_scale = vector_math.dot_vector(sphere_normal, light_normal)

        if light_scale > 0:
            sphere_normal_ray = data.Ray(hit_point, light_normal)
            possible_obstruction = find_closest_collision(sphere_normal_ray, sphere_list)
            if possible_obstruction == None or distance(hit_point, possible_obstruction[1]) > distance(
                hit_point, light.pt
            ):
                result_r += sphere_hit.color.r * light_scale * light.color.r * sphere_hit.finish.diff
                result_g += sphere_hit.color.g * light_scale * light.color.g * sphere_hit.finish.diff
                result_b += sphere_hit.color.b * light_scale * light.color.b * sphere_hit.finish.diff

                # computing specular intensity
        tmp_vector = vector_math.scale_vector(sphere_normal, 2 * light_scale)
        reflection_vector = vector_math.difference_vector(light_normal, tmp_vector)

        eye_vector = vector_math.vector_from_to(eye_point, hit_point)
        eye_normal = vector_math.normalize_vector(eye_vector)

        spec_scale = vector_math.dot_vector(reflection_vector, eye_normal)

        if spec_scale > 0:

            result_r += light.color.r * sphere_hit.finish.spec * spec_scale ** (1 / float(sphere_hit.finish.rough))
            result_g += light.color.g * sphere_hit.finish.spec * spec_scale ** (1 / float(sphere_hit.finish.rough))
            result_b += light.color.b * sphere_hit.finish.spec * spec_scale ** (1 / float(sphere_hit.finish.rough))

        result_color = data.Color(result_r, result_g, result_b)
    return result_color
コード例 #6
0
ファイル: cast.py プロジェクト: blueostrich/cpe101
def closest_intersect(ray, sphere_list):
    """Find the nearest intersection point and sphere"""
    intersections = find_intersection_points(ray, sphere_list)
    if len(intersections) < 1:
        # We don't intersect anything
        return None
    # Find the nearest intersection point and its sphere
    nearest = intersections[0]
    nearest_dist_sq = length_vector_sq(vector_from_to(ray.pt, nearest[0]))
    for tup in intersections[1:]:
        dist_sq = length_vector_sq(vector_from_to(ray.pt, tup[0]))
        if dist_sq < nearest_dist_sq:
            nearest = tup
            nearest_dist_sq = dist_sq
    return nearest
コード例 #7
0
ファイル: tests.py プロジェクト: jacrocitto/RayCaster
 def test_cast_ray_1(self):
     ray = data.Ray(data.Point(0, 10, 6), data.Vector(0, 0, -2))
     sphere_list = [
         data.Sphere(data.Point(0, 10, -2), 3, data.Color(0, 0.5, 1.0), data.Finish(0.5, 0.4, 0.5, 0.05)),
         data.Sphere(data.Point(0, 10, -20), 0.5, data.Color(0, 0.3, 0.2), data.Finish(0.5, 0.4, 0.5, 0.05)),
     ]
     ambient_color = data.Color(0.25, 0.5, 0.75)
     light = data.Light(data.Point(-100.0, 100.0, -100.0), data.Color(1.5, 1.5, 1.5))
     eye_position = data.Point(0, 0, -14)
     cr = cast.cast_ray(ray, sphere_list, ambient_color, light, eye_position)
     inter_point = collisions.sphere_intersection_point(ray, sphere_list[0])
     normal = collisions.sphere_normal_at_point(sphere_list[0], inter_point)
     off_pt = cast.find_pt_off_sphere(inter_point, normal)
     l_dir = vector_math.normalize_vector(vector_math.vector_from_to(off_pt, light.pt))
     l_dot_n = vector_math.dot_vector(normal, l_dir)
     diffuse_list = cast.determine_diffuse_contribution(
         sphere_list[0], off_pt, light, normal, sphere_list, l_dir, l_dot_n
     )
     spec_list = cast.determine_specular_contribution(
         l_dir, l_dot_n, normal, eye_position, off_pt, light.color, sphere_list[0].finish
     )
     self.assertEqual(
         cr,
         data.Color(
             0 + diffuse_list[0] + spec_list[0],
             0.125 + diffuse_list[1] + spec_list[1],
             0.375 + diffuse_list[2] + spec_list[2],
         ),
     )
コード例 #8
0
ファイル: cast.py プロジェクト: jacrocitto/RayCaster
def determine_specular_contribution(l_dir,l_dot_n,normal,eye_position,
                                    off_pt,light,sphere_finish,ray,
                                    inter_list):
   reflection_vect = vector_math.difference_vector(l_dir,
                                 vector_math.scale_vector(normal,
                                                          2 * l_dot_n))
   v_dir = vector_math.normalize_vector(
                       vector_math.vector_from_to(eye_position,off_pt))
   spec_intensity = vector_math.dot_vector(reflection_vect,v_dir)
   def compute_spec(color_comp):
               return (color_comp * sphere_finish.specular *
                       (spec_intensity ** (1 / sphere_finish.roughness)))
   if spec_intensity > 0:
      r_comp = compute_spec(light.color.r)
      g_comp = compute_spec(light.color.g)
      b_comp = compute_spec(light.color.b)
      if inter_list == []:
         return [r_comp,g_comp,b_comp]
      else:
         dist_pt_to_light = distance(off_pt,light.pt)
         nearest_point = find_nearest(inter_list,ray)
         if distance(off_pt,nearest_point) < dist_pt_to_light:
            return [0,0,0]        
         else:
            return [r_comp,g_comp,b_comp]
   else:
      return [0,0,0]
コード例 #9
0
ファイル: cast.py プロジェクト: mMcaniff/Ray-Caster
def cast_all_rays(min_x, max_x, min_y, max_y, width, height, eye_point, sphere_list, ambient_color, light):
  
   f = open("image.ppm", 'w')

   f.write("P3\n")
   f.write("%d %d\n" % (width, height))
   f.write("255\n")

   w = max_x - min_x 
   h = max_y - min_y
   scale_x = w / width
   scale_y = h / height 
   
   total = width * height 
   percent = 0

   for i in range(height):
      print int(percent) 
      for j in range(width):
         position = width * i + j
         percent = float(position) / total * 100
         x = j * scale_x + min_x
         y = max_y - i * scale_y
         dir = vector_math.vector_from_to(eye_point, data.Point(x,y,0))
         ray = data.Ray(eye_point, dir)
         b = cast_ray(ray, sphere_list, ambient_color, light, eye_point)
         print_color(f,b)
コード例 #10
0
 def test_vectorToFrom_2(self):
   p1 = data.Point(4,4,4)
   p2 = data.Point(1,2,3)
   v1 = vector_math.vector_from_to(p1, p2)
   equals = data.Vector(-3, -2, -1)
   self.assertEqual(v1 == equals, True)
   pass
コード例 #11
0
ファイル: tests.py プロジェクト: jacrocitto/RayCaster
 def test_get_diffuse_contribution(self):
     sphere = data.Sphere(data.Point(0, 0, 0), 1, data.Color(0.5, 0.7, 0.8), data.Finish(0.5, 0.5, 0.5, 0.05))
     light = data.Light(data.Point(0, 0, 100), data.Color(1.5, 1.2, 1.3))
     inter_point = data.Point(0, 0, 1)
     normal = collisions.sphere_normal_at_point(sphere, inter_point)
     inter_list = []
     off_pt = cast.find_pt_off_sphere(inter_point, normal)
     dir_vect = vector_math.normalize_vector(vector_math.vector_from_to(off_pt, light.pt))
     ray = data.Ray(off_pt, dir_vect)
     result = cast.get_diffuse_contribution(sphere, light, ray, inter_list, normal, dir_vect, off_pt)
     self.assertEqual(result[0], (vector_math.dot_vector(normal, dir_vect) * 1.5 * 0.5 * 0.5))
     self.assertEqual(result[1], (vector_math.dot_vector(normal, dir_vect) * 1.2 * 0.7 * 0.5))
     self.assertEqual(result[2], (vector_math.dot_vector(normal, dir_vect) * 1.3 * 0.8 * 0.5))
コード例 #12
0
ファイル: cast.py プロジェクト: mMcaniff/Ray-Caster
def get_diffuse_color(tu, light, s_list):
   pE = get_pe(tu)
   N = collisions.sphere_normal_at_point(tu[0], tu[1])
   lDir = vector_math.vector_from_to(pE, light.pt)
   lDir = vector_math.normalize_vector(lDir)
   lDirection = vector_math.dot_vector(N, lDir)
   sI = get_specular_intensity(lDir, lDirection, N, pE, light, tu[0])
   ray = data.Ray(pE, lDir)
   if lDirection <= 0 or collides_with_spheres(ray, s_list, pE, light):
      return data.Color(0,0,0) 
   dif = get_diffuse(lDirection, light, tu[0], tu[0].finish.diffuse)
   finalColor = data.Color(sI.r + dif.r, sI.g + dif.g, sI.b + dif.b)
   return finalColor 
コード例 #13
0
ファイル: cast.py プロジェクト: mattpiasecki/RayCaster
def comp(sphere_list,inter,light,sphere,int,eye_point):
	n = collisions.sphere_normal_at_point(sphere,int)
	scaled_normal = vector_math.scale_vector(n,.01)
	Pe = vector_math.translate_point(inter[0][1],scaled_normal)
	vr_light = vector_math.vector_from_to(Pe,light.pt)
	L_dir = vector_math.normalize_vector(vr_light)
	dot_product = vector_math.dot_vector(n,L_dir)
	reflection_vr = vector_math.difference_vector(L_dir,vector_math.scale_vector(n,(2 * dot_product)))
	V_dir = vector_math.normalize_vector(vector_math.vector_from_to(eye_point,Pe))
	intensity = vector_math.dot_vector(reflection_vr,V_dir)
	ray = data.Ray(Pe,L_dir)
	inter2 = collisions.find_intersection_points(sphere_list,ray)
	if dot_product>0 and inter2 == []:
		diff_r = sphere.color.r*sphere.finish.diffuse*dot_product*light.color.r
		diff_g = sphere.color.g*sphere.finish.diffuse*dot_product*light.color.g
		diff_b = sphere.color.b*sphere.finish.diffuse*dot_product*light.color.b
		spec_r = light.color.r*sphere.finish.specular*math.pow(intensity,(1/sphere.finish.roughness))
		spec_g = light.color.g*sphere.finish.specular*math.pow(intensity,(1/sphere.finish.roughness))
		spec_b = light.color.b*sphere.finish.specular*math.pow(intensity,(1/sphere.finish.roughness))
		return data.Color(diff_r,diff_g,diff_b),data.Color(spec_r,spec_g,spec_b)
	else :    
		return data.Color(0,0,0), data.Color(0,0,0)
コード例 #14
0
ファイル: cast.py プロジェクト: mMcaniff/Ray-Caster
def get_specular_intensity(lDir, lDirection, N, pE, light, sphere):
   reflection_vector = vector_math.difference_vector(lDir, vector_math.scale_vector(N, lDirection * 2)) 
   vDir = vector_math.vector_from_to(data.Point(0.0,0.0,-14.0), pE)
   vDir = vector_math.normalize_vector(vDir)
   intensity = vector_math.dot_vector(reflection_vector, vDir)
   if intensity > 0: 
      r = light.color.r * sphere.finish.specular * intensity**(1 / sphere.finish.roughness)
      g = light.color.g * sphere.finish.specular * intensity**(1 / sphere.finish.roughness)
      b = light.color.b * sphere.finish.specular * intensity**(1 / sphere.finish.roughness)
      color = data.Color(r,g,b)
   else: 
      color = data.Color(0,0,0)

   return color
コード例 #15
0
ファイル: cast.py プロジェクト: 14bmkelley/raytracer-python
def cast_all_rays(view, eye_point, sphere_list, amb, light, file):
    j = view.max_y
    while j > view.min_y:
        i = view.min_x
        while i < view.max_x:
            screen_point = data.Point(i, j, 0)
            dir_to_pixel = vector_math.vector_from_to(eye_point, screen_point)
            ray = data.Ray(eye_point, dir_to_pixel)
            color = cast_ray(ray, sphere_list, amb, light, eye_point)
            printed_r = str(color_convert(color.r))
            printed_g = str(color_convert(color.g))
            printed_b = str(color_convert(color.b))
            file.write("{0} {1} {2}\n".format(printed_r, printed_g, printed_b))
            i += find_delta(view.min_x, view.max_x, view.width)
        j -= find_delta(view.min_y, view.max_y, view.height)
コード例 #16
0
ファイル: cast.py プロジェクト: mattpiasecki/RayCaster
def cast_all_rays(min_x, max_x, min_y, max_y, width, height, eye_point, sphere_list,amb,light):
	image = open('image.ppm','w')
	print >> image, 'P3'
	print >> image, width, height
	print >> image, 255

	distx=(max_x-min_x)/float(width)
	disty=(max_y-min_y)/float(height)
	for y in range(height):
		for x in range(width):
			pix_x = min_x + distx*x
			pix_y = max_y - disty*y

			vr = vector_math.vector_from_to(eye_point,data.Point(pix_x,pix_y,0.0))
			ray = data.Ray(eye_point,vr)
			color = cast_ray(ray,sphere_list,amb,light,eye_point)
			print >> image, int(min(color.r*255,255)),int(min(color.g*255,255)),int(min(color.b*255,255))
コード例 #17
0
ファイル: cast.py プロジェクト: jacrocitto/RayCaster
def cast_ray(ray,sphere_list,ambient_color,light,eye_position):
   inter_list = collisions.find_intersection_points(sphere_list,
                                                           ray)
   if inter_list != []:
      mindex = 0
      for i in range(1,len(inter_list)):
         if (distance(ray.pt,inter_list[i][1]) <       
             distance(ray.pt,inter_list[mindex][1])):
            mindex = i
      result_sphere = inter_list[mindex][0]
      inter_point = inter_list[mindex][1]
      sphere_color = result_sphere.color
      sphere_finish = result_sphere.finish
      sphere_normal = collisions.sphere_normal_at_point(result_sphere,
                                                        inter_point)
      pt_off_sphere = find_pt_off_sphere(inter_point,sphere_normal)
      l_dir = vector_math.normalize_vector(
                 vector_math.vector_from_to(pt_off_sphere,
                                            light.pt))
      l_dot_n = vector_math.dot_vector(sphere_normal,l_dir)
      ray_off_to_l = data.Ray(pt_off_sphere,l_dir)
      inter_list = collisions.find_intersection_points(sphere_list,ray_off_to_l)
      diffuse_list = determine_diffuse_contribution(result_sphere,
                                                    pt_off_sphere,
                                                    light,sphere_normal,
                                                    sphere_list,l_dir,
                                                    l_dot_n,ray_off_to_l,
                                                    inter_list)
      spec_intensity = determine_specular_contribution(l_dir,l_dot_n,
                                                       sphere_normal,
                                                       eye_position,
                                                       pt_off_sphere,
                                                       light,
                                                       result_sphere.finish,
                                                       ray_off_to_l,inter_list)

      result_r = ((sphere_color.r * sphere_finish.ambient * 
                   ambient_color.r) + diffuse_list[0] + spec_intensity[0])
      result_g = ((sphere_color.g * sphere_finish.ambient * 
                   ambient_color.g) + diffuse_list[1] + spec_intensity[1])
      result_b = ((sphere_color.b * sphere_finish.ambient * 
                   ambient_color.b) + diffuse_list[2] + spec_intensity[2])
      return data.Color(result_r,result_g,result_b)   
   else:
      return ambient_color
コード例 #18
0
ファイル: cast.py プロジェクト: blueostrich/cpe101
def cast_all_rays(min_x, max_x, min_y, max_y, width, height, eye_point,
        sphere_list, color, light, file):
    """
    Loop through all potetial points in xy-plane, calculating the ray from
    eye_point to that point. For each point, determine the projected color by
    applying cast_ray on the sphere list

    Outputs one line per pixel with decimal r, g, b values separated by a space
    """
    for y in range(height):
        for x in range(width):
            pt = Point(min_x + (max_x - min_x) * x / float(width),
                       max_y - (max_y - min_y) * y / float(height), 0.0)
            ray = Ray(eye_point, vector_from_to(eye_point, pt))
            c = cast_ray(ray, sphere_list, color, light)
            file.write(str(int(c.r * 255)) + ' ')
            file.write(str(int(c.g * 255)) + ' ')
            file.write(str(int(c.b * 255)) + ' ')
コード例 #19
0
ファイル: cast.py プロジェクト: 14bmkelley/raytracer-python
def distance(p1, p2):
    vector = vector_math.vector_from_to(p1, p2)
    return vector_math.length_vector(vector)
コード例 #20
0
 def test_vector_from_to_1(self):
     p1 = data.Point(0.0, 0.0, 0.0)
     p2 = data.Point(1.0, 2.0, 3.0)
     v = vector_math.vector_from_to(p1, p2)
     self.assertEqual(v, data.Vector(1.0, 2.0, 3.0))
コード例 #21
0
 def test_vector_from_to_1(self):
    from_point1 = data.Point(4, 8, 7)
    to_point1 = data.Point(5, 9, 6)
    travel = data.Point(1, 1, -1)
    self.assertEqual(vector_math.vector_from_to(from_point1, to_point1), travel)
コード例 #22
0
 def test_vector_from_to_2(self):
    from_point2 = data.Point(-8, 5, -6)
    to_point2 = data.Point(12, 15, -24)
    travel = data.Point(20, 10, -18)
    self.assertEqual(vector_math.vector_from_to(from_point2, to_point2), travel)
コード例 #23
0
 def test_vector_from_to_2(self):
     pt_1 = data.Point(2, 2, 2)
     pt_2 = data.Point(6, 6, 6)
     n_v = data.Vector(4, 4, 4)
     self.assertAlmostEqual(vector_math.vector_from_to(pt_1, pt_2), n_v)
コード例 #24
0
ファイル: tests.py プロジェクト: jacrocitto/RayCaster
 def test_vector_from_to_again(self):
     vft = vector_math.vector_from_to(data.Point(0, 0, 1), data.Point(-3.3, 8, 9.9))
     self.assertEqual(vft, data.Vector(-3.3, 8, 8.9))
コード例 #25
0
ファイル: tests.py プロジェクト: jacrocitto/RayCaster
 def test_vector_from_to(self):
     vft = vector_math.vector_from_to(data.Point(3, -6, 2.9), data.Point(7, -7, 0.3))
     self.assertEqual(vft, data.Vector(4, -1, -2.6))
コード例 #26
0
ファイル: collisions.py プロジェクト: jacrocitto/RayCaster
def sphere_normal_at_point(sphere,point):
   return vector_math.normalize_vector(vector_math.vector_from_to(sphere.center,
                                                                  point))
コード例 #27
0
 def test_vector_from_to(self):
     pt_1 = data.Point(1, 1, 1)
     pt_2 = data.Point(5, 5, 5)
     n_v = data.Vector(4, 4, 4)
     self.assertAlmostEqual(vector_math.vector_from_to(pt_1, pt_2), n_v)