diff --git a/Image_based/branchpointdetection.py b/Image_based/branchpointdetection.py index ef7234b..b30df55 100644 --- a/Image_based/branchpointdetection.py +++ b/Image_based/branchpointdetection.py @@ -9,7 +9,7 @@ import json from os.path import exists from bezier_cyl_2d import BezierCyl2D -from line_seg_2d import draw_line, draw_box, draw_cross, LineSeg2D +from line_seg_2d import LineSeg2D from scipy.cluster.vq import kmeans, whiten, vq class BranchPointDetection: @@ -67,18 +67,19 @@ def __init__(self, path, image_name, b_output_debug=True, b_recalc=False): # For each of the trunk/branches, see if we have reasonable upper left/lower right points # Save points in debug image + if b_output_debug: self.images_single["marked points"] = np.copy(self.images_single["masked"]) for im in self.images: try: p1 = im["stats"]["lower_left"] p2 = im["stats"]["upper_right"] - draw_line(im["image"], p1, p2, (128, 128, 128), 2) - draw_line(self.images_single["marked points"], p1, p2, (128, 128, 128), 1) + LineSeg2D.draw_line(im["image"], p1, p2, (128, 128, 128), 2) + LineSeg2D.draw_line(self.images_single["marked points"], p1, p2, (128, 128, 128), 1) pc = im["stats"]["center"] - draw_cross(im["image"], pc, (128, 128, 128), 1, 2) - draw_cross(self.images_single["marked points"], pc, (180, 180, 128), 1, 3) + LineSeg2D.draw_cross(im["image"], pc, (128, 128, 128), 1, 2) + LineSeg2D.draw_cross(self.images_single["marked points"], pc, (180, 180, 128), 1, 3) cv2.imwrite(self.path_debug + image_name + "_" + im["name"] + "_points.png", im["image"]) except: @@ -111,8 +112,8 @@ def __init__(self, path, image_name, b_output_debug=True, b_recalc=False): # Draw the original, the edges, and the depth mask with the fitted quad im["quad"].draw_bezier(im_orig_debug) if im["quad"].is_wire(): - draw_cross(im_orig_debug, im["quad"].p0, (255, 0, 0), thickness=2, length=10) - draw_cross(im_orig_debug, im["quad"].p2, (255, 0, 0), thickness=2, length=10) + LineSeg2D.draw_cross(im_orig_debug, im["quad"].p0, (255, 0, 0), thickness=2, length=10) + LineSeg2D.draw_cross(im_orig_debug, im["quad"].p2, (255, 0, 0), thickness=2, length=10) else: im["quad"].draw_boundary(im_orig_debug, 10) im["quad"].draw_edge_rects(im_covert_back, step_size=params["step_size"], perc_width=params["width"]) @@ -158,8 +159,8 @@ def __init__(self, path, image_name, b_output_debug=True, b_recalc=False): # Draw the original, the edges, and the depth mask with the fitted quad im["quad_flow"].draw_bezier(im_orig_debug) if im["quad_flow"].is_wire(): - draw_cross(im_orig_debug, im["quad_flow"].p0, (255, 0, 0), thickness=2, length=10) - draw_cross(im_orig_debug, im["quad_flow"].p2, (255, 0, 0), thickness=2, length=10) + LineSeg2D.draw_cross(im_orig_debug, im["quad_flow"].p0, (255, 0, 0), thickness=2, length=10) + LineSeg2D.draw_cross(im_orig_debug, im["quad_flow"].p2, (255, 0, 0), thickness=2, length=10) else: im["quad_flow"].draw_boundary(im_orig_debug, 10) im["quad_flow"].draw_edge_rects(im_covert_back, step_size=params["step_size"], perc_width=params["width"]) @@ -202,8 +203,8 @@ def __init__(self, path, image_name, b_output_debug=True, b_recalc=False): if b_output_debug: for p, v in self.branch_points: - draw_box(self.images_single["marked points"], p, (254, 128, 254), 6) - draw_line(self.images_single["marked points"], p, p + v, (128, 254, 254), 1) + LineSeg2D.draw_box(self.images_single["marked points"], p, (254, 128, 254), 6) + LineSeg2D.draw_line(self.images_single["marked points"], p, p + v, (128, 254, 254), 1) cv2.imwrite(self.path_debug + image_name + "_" + "_marked_joins_points.png", self.images_single["marked points"]) @@ -333,7 +334,7 @@ def fit_quad(self, im, b_output_debug=True): quad = BezierCyl2D(pts['lower_left'], pts['upper_right'], 0.5 * pts['width']) # Current parameters for the vertical leader - params = {"step_size": int(quad.radius_2d * 1.5), "width_mask": 1.4, "width": 0.3} + params = {"step_size": int(quad.radius * 1.5), "width_mask": 1.4, "width": 0.3} # Iteratively move the quad to the center of the mask for i in range(0, 5): @@ -482,4 +483,4 @@ def find_branch_point(self, im_trunk, im_sidebranch): for im_i in range(0, 18): name = str(im_i) print(name) - bp = BranchPointDetection(path, name, b_output_debug=True) + bp = BranchPointDetection(path, name, b_output_debug=False) diff --git a/__pycache__/bezier_cyl_3d.cpython-310.pyc b/__pycache__/bezier_cyl_3d.cpython-310.pyc new file mode 100644 index 0000000..e125f4e Binary files /dev/null and b/__pycache__/bezier_cyl_3d.cpython-310.pyc differ diff --git a/bezier_cyl_3d.py b/bezier_cyl_3d.py index 8c03cd8..a91e4a8 100644 --- a/bezier_cyl_3d.py +++ b/bezier_cyl_3d.py @@ -12,7 +12,9 @@ import numpy as np from json import load, dump - +#switch to this +#use sdk--> look at point cloud +#take every 3 points and do bezier class BezierCyl3D: def __init__(self, p1=(0.0, 0.0, 0.0), p2=(0.5, 0.75, 0.5), p3=(1.0, 1.0, 1.0), start_radius=10.0, end_radius=20.0): @@ -145,6 +147,7 @@ def frenet_frame(self, t): def _calc_radii(self): """ Calculate the radii along the branch @return a numpy array of radii""" + radii = np.linspace(self.start_radii, self.end_radii, self.n_along) return radii @@ -152,7 +155,7 @@ def _calc_cyl_vertices(self): """Calculate the cylinder vertices""" pt = np.ones(shape=(4,)) radii = self._calc_radii() - + for it, t in enumerate(np.linspace(0, 1.0, self.n_along)): mat = self.frenet_frame(t) pt[0] = 0 @@ -165,6 +168,7 @@ def _calc_cyl_vertices(self): pt_on_crv = mat @ pt self.vertex_locs[it, itheta, :] = pt_on_crv[0:3].transpose() + def make_mesh(self): """ Make a 3D generalized cylinder """ @@ -237,17 +241,17 @@ def read_json(fname, bezier_crv=None, compute_mesh=True): from os.path import exists from os import mkdir - if not exists("data/DebugImages"): - mkdir("data/DebugImages") + #if not exists("data/DebugImages"): + #mkdir("data/DebugImages") branch = BezierCyl3D([506.5, 156.0, 0.0], [457.49999996771703, 478.9999900052037, 0.0], [521.5, 318.0, 0.0], start_radius=10.5, end_radius=8.25) branch.make_mesh() - branch.write_mesh("data/DebugImages/check_3d_bezier1.obj") + branch.write_mesh("check_3d_bezier1.obj") branch = BezierCyl3D([-0.5, 0.0, 0.0], [0.0, 0.1, 0.05], [0.5, 0.0, 0.0], start_radius=0.5, end_radius=0.25) branch.make_mesh() - branch.write_mesh("data/DebugImages/check_3d_bezier2.obj") + branch.write_mesh("check_3d_bezier2.obj") branch.set_dims(n_along=30, n_radial=32) branch.make_mesh() - branch.write_mesh("data/DebugImages/check_3d_bezier_more_vs.obj") + branch.write_mesh("check_3d_bezier_more_vs.obj") diff --git a/data/DebugImages/check_3d_bezier1.obj b/data/DebugImages/check_3d_bezier1.obj new file mode 100644 index 0000000..f7194ef --- /dev/null +++ b/data/DebugImages/check_3d_bezier1.obj @@ -0,0 +1,1793 @@ +# Branch +v 496.119 154.425 0.0 +v 496.169 154.433 -1.02918 +v 496.318 154.455 -2.04845 +v 496.566 154.493 -3.04799 +v 496.909 154.545 -4.01818 +v 497.345 154.611 -4.94967 +v 497.868 154.691 -5.83349 +v 498.475 154.783 -6.66113 +v 499.159 154.886 -7.42462 +v 499.914 155.001 -8.11661 +v 500.733 155.125 -8.73043 +v 501.606 155.258 -9.26017 +v 502.527 155.397 -9.70074 +v 503.486 155.543 -10.0479 +v 504.475 155.693 -10.2982 +v 505.482 155.846 -10.4494 +v 506.5 156.0 -10.5 +v 507.518 156.154 -10.4494 +v 508.525 156.307 -10.2982 +v 509.514 156.457 -10.0479 +v 510.473 156.603 -9.70074 +v 511.394 156.742 -9.26017 +v 512.267 156.875 -8.73043 +v 513.086 156.999 -8.11661 +v 513.841 157.114 -7.42462 +v 514.525 157.217 -6.66113 +v 515.132 157.309 -5.83349 +v 515.655 157.389 -4.94967 +v 516.091 157.455 -4.01818 +v 516.434 157.507 -3.04799 +v 516.682 157.545 -2.04845 +v 516.831 157.567 -1.02918 +v 516.881 157.575 -1.28588e-15 +v 516.831 157.567 1.02918 +v 516.682 157.545 2.04845 +v 516.434 157.507 3.04799 +v 516.091 157.455 4.01818 +v 515.655 157.389 4.94967 +v 515.132 157.309 5.83349 +v 514.525 157.217 6.66113 +v 513.841 157.114 7.42462 +v 513.086 156.999 8.11661 +v 512.267 156.875 8.73043 +v 511.394 156.742 9.26017 +v 510.473 156.603 9.70074 +v 509.514 156.457 10.0479 +v 508.525 156.307 10.2982 +v 507.518 156.154 10.4494 +v 506.5 156.0 10.5 +v 505.482 155.846 10.4494 +v 504.475 155.693 10.2982 +v 503.486 155.543 10.0479 +v 502.527 155.397 9.70074 +v 501.606 155.258 9.26017 +v 500.733 155.125 8.73043 +v 499.914 155.001 8.11661 +v 499.159 154.886 7.42462 +v 498.475 154.783 6.66113 +v 497.868 154.691 5.83349 +v 497.345 154.611 4.94967 +v 496.909 154.545 4.01818 +v 496.566 154.493 3.04799 +v 496.318 154.455 2.04845 +v 496.169 154.433 1.02918 +v 486.849 220.427 0.0 +v 486.898 220.434 -1.00468 +v 487.044 220.454 -1.99968 +v 487.286 220.487 -2.97542 +v 487.622 220.532 -3.92251 +v 488.048 220.59 -4.83182 +v 488.561 220.659 -5.69459 +v 489.154 220.74 -6.50253 +v 489.824 220.83 -7.24784 +v 490.562 220.93 -7.92336 +v 491.363 221.039 -8.52256 +v 492.218 221.154 -9.03969 +v 493.119 221.276 -9.46977 +v 494.058 221.403 -9.80864 +v 495.025 221.534 -10.053 +v 496.011 221.668 -10.2006 +v 497.006 221.802 -10.25 +v 498.002 221.937 -10.2006 +v 498.988 222.071 -10.053 +v 499.955 222.202 -9.80864 +v 500.893 222.329 -9.46977 +v 501.794 222.451 -9.03969 +v 502.649 222.566 -8.52256 +v 503.45 222.675 -7.92336 +v 504.189 222.775 -7.24784 +v 504.858 222.865 -6.50253 +v 505.452 222.946 -5.69459 +v 505.964 223.015 -4.83182 +v 506.39 223.073 -3.92251 +v 506.726 223.118 -2.97542 +v 506.968 223.151 -1.99968 +v 507.115 223.171 -1.00468 +v 507.164 223.177 -1.25526e-15 +v 507.115 223.171 1.00468 +v 506.968 223.151 1.99968 +v 506.726 223.118 2.97542 +v 506.39 223.073 3.92251 +v 505.964 223.015 4.83182 +v 505.452 222.946 5.69459 +v 504.858 222.865 6.50253 +v 504.189 222.775 7.24784 +v 503.45 222.675 7.92336 +v 502.649 222.566 8.52256 +v 501.794 222.451 9.03969 +v 500.893 222.329 9.46977 +v 499.955 222.202 9.80864 +v 498.988 222.071 10.053 +v 498.002 221.937 10.2006 +v 497.006 221.802 10.25 +v 496.011 221.668 10.2006 +v 495.025 221.534 10.053 +v 494.058 221.403 9.80864 +v 493.119 221.276 9.46977 +v 492.218 221.154 9.03969 +v 491.363 221.039 8.52256 +v 490.562 220.93 7.92336 +v 489.824 220.83 7.24784 +v 489.154 220.74 6.50253 +v 488.561 220.659 5.69459 +v 488.048 220.59 4.83182 +v 487.622 220.532 3.92251 +v 487.286 220.487 2.97542 +v 487.044 220.454 1.99968 +v 486.898 220.434 1.00468 +v 480.363 274.552 0.0 +v 480.411 274.558 -0.980171 +v 480.554 274.573 -1.9509 +v 480.791 274.6 -2.90285 +v 481.12 274.636 -3.82683 +v 481.537 274.682 -4.71397 +v 482.038 274.738 -5.5557 +v 482.619 274.802 -6.34393 +v 483.274 274.875 -7.07107 +v 483.997 274.955 -7.7301 +v 484.781 275.042 -8.3147 +v 485.617 275.135 -8.81921 +v 486.499 275.233 -9.2388 +v 487.417 275.334 -9.5694 +v 488.363 275.439 -9.80785 +v 489.328 275.546 -9.95185 +v 490.302 275.654 -10.0 +v 491.277 275.762 -9.95185 +v 492.241 275.869 -9.80785 +v 493.188 275.974 -9.5694 +v 494.106 276.076 -9.2388 +v 494.988 276.174 -8.81921 +v 495.824 276.267 -8.3147 +v 496.608 276.353 -7.7301 +v 497.33 276.434 -7.07107 +v 497.985 276.506 -6.34393 +v 498.567 276.571 -5.5557 +v 499.068 276.626 -4.71397 +v 499.485 276.672 -3.82683 +v 499.814 276.709 -2.90285 +v 500.051 276.735 -1.9509 +v 500.194 276.751 -0.980171 +v 500.242 276.756 -1.22465e-15 +v 500.194 276.751 0.980171 +v 500.051 276.735 1.9509 +v 499.814 276.709 2.90285 +v 499.485 276.672 3.82683 +v 499.068 276.626 4.71397 +v 498.567 276.571 5.5557 +v 497.985 276.506 6.34393 +v 497.33 276.434 7.07107 +v 496.608 276.353 7.7301 +v 495.824 276.267 8.3147 +v 494.988 276.174 8.81921 +v 494.106 276.076 9.2388 +v 493.188 275.974 9.5694 +v 492.241 275.869 9.80785 +v 491.277 275.762 9.95185 +v 490.302 275.654 10.0 +v 489.328 275.546 9.95185 +v 488.363 275.439 9.80785 +v 487.417 275.334 9.5694 +v 486.499 275.233 9.2388 +v 485.617 275.135 8.81921 +v 484.781 275.042 8.3147 +v 483.997 274.955 7.7301 +v 483.274 274.875 7.07107 +v 482.619 274.802 6.34393 +v 482.038 274.738 5.5557 +v 481.537 274.682 4.71397 +v 481.12 274.636 3.82683 +v 480.791 274.6 2.90285 +v 480.554 274.573 1.9509 +v 480.411 274.558 0.980171 +v 476.663 316.874 0.0 +v 476.71 316.877 -0.955667 +v 476.85 316.887 -1.90213 +v 477.082 316.903 -2.83028 +v 477.403 316.926 -3.73116 +v 477.811 316.954 -4.59612 +v 478.302 316.989 -5.41681 +v 478.87 317.028 -6.18533 +v 479.511 317.073 -6.89429 +v 480.219 317.123 -7.53685 +v 480.985 317.177 -8.10683 +v 481.804 317.234 -8.59873 +v 482.667 317.295 -9.00783 +v 483.566 317.358 -9.33017 +v 484.491 317.423 -9.56266 +v 485.436 317.489 -9.70305 +v 486.389 317.556 -9.75 +v 487.342 317.622 -9.70305 +v 488.286 317.689 -9.56266 +v 489.212 317.753 -9.33017 +v 490.111 317.816 -9.00783 +v 490.974 317.877 -8.59873 +v 491.792 317.934 -8.10683 +v 492.559 317.988 -7.53685 +v 493.266 318.038 -6.89429 +v 493.907 318.083 -6.18533 +v 494.476 318.122 -5.41681 +v 494.967 318.157 -4.59612 +v 495.375 318.185 -3.73116 +v 495.696 318.208 -2.83028 +v 495.928 318.224 -1.90213 +v 496.068 318.234 -0.955667 +v 496.115 318.237 -1.19403e-15 +v 496.068 318.234 0.955667 +v 495.928 318.224 1.90213 +v 495.696 318.208 2.83028 +v 495.375 318.185 3.73116 +v 494.967 318.157 4.59612 +v 494.476 318.122 5.41681 +v 493.907 318.083 6.18533 +v 493.266 318.038 6.89429 +v 492.559 317.988 7.53685 +v 491.792 317.934 8.10683 +v 490.974 317.877 8.59873 +v 490.111 317.816 9.00783 +v 489.212 317.753 9.33017 +v 488.286 317.689 9.56266 +v 487.342 317.622 9.70305 +v 486.389 317.556 9.75 +v 485.436 317.489 9.70305 +v 484.491 317.423 9.56266 +v 483.566 317.358 9.33017 +v 482.667 317.295 9.00783 +v 481.804 317.234 8.59873 +v 480.985 317.177 8.10683 +v 480.219 317.123 7.53685 +v 479.511 317.073 6.89429 +v 478.87 317.028 6.18533 +v 478.302 316.989 5.41681 +v 477.811 316.954 4.59612 +v 477.403 316.926 3.73116 +v 477.082 316.903 2.83028 +v 476.85 316.887 1.90213 +v 476.71 316.877 0.955667 +v 475.766 347.614 0.0 +v 475.812 347.613 -0.931163 +v 475.949 347.612 -1.85336 +v 476.175 347.609 -2.7577 +v 476.489 347.606 -3.63549 +v 476.888 347.601 -4.47827 +v 477.367 347.596 -5.27792 +v 477.922 347.589 -6.02674 +v 478.548 347.582 -6.71751 +v 479.239 347.574 -7.3436 +v 479.988 347.566 -7.89896 +v 480.787 347.557 -8.37825 +v 481.63 347.547 -8.77686 +v 482.508 347.537 -9.09093 +v 483.412 347.527 -9.31746 +v 484.334 347.517 -9.45425 +v 485.265 347.506 -9.5 +v 486.197 347.496 -9.45425 +v 487.119 347.485 -9.31746 +v 488.023 347.475 -9.09093 +v 488.901 347.465 -8.77686 +v 489.743 347.455 -8.37825 +v 490.543 347.446 -7.89896 +v 491.292 347.438 -7.3436 +v 491.983 347.43 -6.71751 +v 492.609 347.423 -6.02674 +v 493.164 347.417 -5.27792 +v 493.643 347.411 -4.47827 +v 494.042 347.407 -3.63549 +v 494.356 347.403 -2.7577 +v 494.582 347.401 -1.85336 +v 494.719 347.399 -0.931163 +v 494.765 347.399 -1.16341e-15 +v 494.719 347.399 0.931163 +v 494.582 347.401 1.85336 +v 494.356 347.403 2.7577 +v 494.042 347.407 3.63549 +v 493.643 347.411 4.47827 +v 493.164 347.417 5.27792 +v 492.609 347.423 6.02674 +v 491.983 347.43 6.71751 +v 491.292 347.438 7.3436 +v 490.543 347.446 7.89896 +v 489.743 347.455 8.37825 +v 488.901 347.465 8.77686 +v 488.023 347.475 9.09093 +v 487.119 347.485 9.31746 +v 486.197 347.496 9.45425 +v 485.265 347.506 9.5 +v 484.334 347.517 9.45425 +v 483.412 347.527 9.31746 +v 482.508 347.537 9.09093 +v 481.63 347.547 8.77686 +v 480.787 347.557 8.37825 +v 479.988 347.566 7.89896 +v 479.239 347.574 7.3436 +v 478.548 347.582 6.71751 +v 477.922 347.589 6.02674 +v 477.367 347.596 5.27792 +v 476.888 347.601 4.47827 +v 476.489 347.606 3.63549 +v 476.175 347.609 2.7577 +v 475.949 347.612 1.85336 +v 475.812 347.613 0.931163 +v 477.968 367.789 0.0 +v 478.011 367.778 -0.906659 +v 478.14 367.745 -1.80459 +v 478.354 367.69 -2.68513 +v 478.65 367.615 -3.53982 +v 479.027 367.519 -4.36042 +v 479.479 367.404 -5.13902 +v 480.003 367.27 -5.86814 +v 480.594 367.12 -6.54074 +v 481.245 366.954 -7.15035 +v 481.952 366.774 -7.69109 +v 482.707 366.582 -8.15777 +v 483.502 366.38 -8.54589 +v 484.33 366.169 -8.8517 +v 485.183 365.951 -9.07226 +v 486.053 365.73 -9.20546 +v 486.932 365.506 -9.25 +v 487.811 365.282 -9.20546 +v 488.681 365.061 -9.07226 +v 489.534 364.844 -8.8517 +v 490.362 364.633 -8.54589 +v 491.158 364.43 -8.15777 +v 491.912 364.238 -7.69109 +v 492.619 364.058 -7.15035 +v 493.271 363.892 -6.54074 +v 493.861 363.742 -5.86814 +v 494.385 363.608 -5.13902 +v 494.838 363.493 -4.36042 +v 495.214 363.397 -3.53982 +v 495.51 363.322 -2.68513 +v 495.724 363.268 -1.80459 +v 495.853 363.235 -0.906659 +v 495.896 363.224 -1.1328e-15 +v 495.853 363.235 0.906659 +v 495.724 363.268 1.80459 +v 495.51 363.322 2.68513 +v 495.214 363.397 3.53982 +v 494.838 363.493 4.36042 +v 494.385 363.608 5.13902 +v 493.861 363.742 5.86814 +v 493.271 363.892 6.54074 +v 492.619 364.058 7.15035 +v 491.912 364.238 7.69109 +v 491.158 364.43 8.15777 +v 490.362 364.633 8.54589 +v 489.534 364.844 8.8517 +v 488.681 365.061 9.07226 +v 487.811 365.282 9.20546 +v 486.932 365.506 9.25 +v 486.053 365.73 9.20546 +v 485.183 365.951 9.07226 +v 484.33 366.169 8.8517 +v 483.502 366.38 8.54589 +v 482.707 366.582 8.15777 +v 481.952 366.774 7.69109 +v 481.245 366.954 7.15035 +v 480.594 367.12 6.54074 +v 480.003 367.27 5.86814 +v 479.479 367.404 5.13902 +v 479.027 367.519 4.36042 +v 478.65 367.615 3.53982 +v 478.354 367.69 2.68513 +v 478.14 367.745 1.80459 +v 478.011 367.778 0.906659 +v 491.275 380.555 0.0 +v 491.276 380.511 -0.882154 +v 491.277 380.382 -1.75581 +v 491.28 380.167 -2.61256 +v 491.284 379.87 -3.44415 +v 491.288 379.492 -4.24257 +v 491.294 379.038 -5.00013 +v 491.301 378.512 -5.70954 +v 491.308 377.919 -6.36396 +v 491.317 377.265 -6.95709 +v 491.326 376.555 -7.48323 +v 491.335 375.798 -7.93729 +v 491.345 374.999 -8.31492 +v 491.356 374.168 -8.61246 +v 491.367 373.311 -8.82707 +v 491.378 372.438 -8.95666 +v 491.389 371.556 -9.0 +v 491.4 370.673 -8.95666 +v 491.411 369.8 -8.82707 +v 491.422 368.943 -8.61246 +v 491.432 368.112 -8.31492 +v 491.443 367.313 -7.93729 +v 491.452 366.556 -7.48323 +v 491.461 365.846 -6.95709 +v 491.469 365.192 -6.36396 +v 491.477 364.599 -5.70954 +v 491.484 364.073 -5.00013 +v 491.489 363.619 -4.24257 +v 491.494 363.241 -3.44415 +v 491.498 362.944 -2.61256 +v 491.501 362.729 -1.75581 +v 491.502 362.6 -0.882154 +v 491.503 362.556 -1.10218e-15 +v 491.502 362.6 0.882154 +v 491.501 362.729 1.75581 +v 491.498 362.944 2.61256 +v 491.494 363.241 3.44415 +v 491.489 363.619 4.24257 +v 491.484 364.073 5.00013 +v 491.477 364.599 5.70954 +v 491.469 365.192 6.36396 +v 491.461 365.846 6.95709 +v 491.452 366.556 7.48323 +v 491.443 367.313 7.93729 +v 491.432 368.112 8.31492 +v 491.422 368.943 8.61246 +v 491.411 369.8 8.82707 +v 491.4 370.673 8.95666 +v 491.389 371.556 9.0 +v 491.378 372.438 8.95666 +v 491.367 373.311 8.82707 +v 491.356 374.168 8.61246 +v 491.345 374.999 8.31492 +v 491.335 375.798 7.93729 +v 491.326 376.555 7.48323 +v 491.317 377.265 6.95709 +v 491.308 377.919 6.36396 +v 491.301 378.512 5.70954 +v 491.294 379.038 5.00013 +v 491.288 379.492 4.24257 +v 491.284 379.87 3.44415 +v 491.28 380.167 2.61256 +v 491.277 380.382 1.75581 +v 491.276 380.511 0.882154 +v 505.711 370.803 0.0 +v 505.677 370.778 -0.85765 +v 505.575 370.704 -1.70704 +v 505.406 370.581 -2.53999 +v 505.172 370.411 -3.34848 +v 504.876 370.195 -4.12472 +v 504.519 369.935 -4.86124 +v 504.105 369.634 -5.55094 +v 503.639 369.295 -6.18718 +v 503.124 368.92 -6.76384 +v 502.567 368.515 -7.27536 +v 501.971 368.081 -7.71681 +v 501.343 367.624 -8.08395 +v 500.69 367.149 -8.37323 +v 500.016 366.659 -8.58187 +v 499.329 366.159 -8.70787 +v 498.636 365.654 -8.75 +v 497.942 365.15 -8.70787 +v 497.256 364.65 -8.58187 +v 496.582 364.16 -8.37323 +v 495.928 363.684 -8.08395 +v 495.301 363.227 -7.71681 +v 494.705 362.794 -7.27536 +v 494.147 362.388 -6.76384 +v 493.633 362.014 -6.18718 +v 493.167 361.675 -5.55094 +v 492.753 361.374 -4.86124 +v 492.396 361.114 -4.12472 +v 492.099 360.898 -3.34848 +v 491.865 360.728 -2.53999 +v 491.697 360.605 -1.70704 +v 491.595 360.531 -0.85765 +v 491.561 360.506 -1.07157e-15 +v 491.595 360.531 0.85765 +v 491.697 360.605 1.70704 +v 491.865 360.728 2.53999 +v 492.099 360.898 3.34848 +v 492.396 361.114 4.12472 +v 492.753 361.374 4.86124 +v 493.167 361.675 5.55094 +v 493.633 362.014 6.18718 +v 494.147 362.388 6.76384 +v 494.705 362.794 7.27536 +v 495.301 363.227 7.71681 +v 495.928 363.684 8.08395 +v 496.582 364.16 8.37323 +v 497.256 364.65 8.58187 +v 497.942 365.15 8.70787 +v 498.636 365.654 8.75 +v 499.329 366.159 8.70787 +v 500.016 366.659 8.58187 +v 500.69 367.149 8.37323 +v 501.343 367.624 8.08395 +v 501.971 368.081 7.71681 +v 502.567 368.515 7.27536 +v 503.124 368.92 6.76384 +v 503.639 369.295 6.18718 +v 504.105 369.634 5.55094 +v 504.519 369.935 4.86124 +v 504.876 370.195 4.12472 +v 505.172 370.411 3.34848 +v 505.406 370.581 2.53999 +v 505.575 370.704 1.70704 +v 505.677 370.778 0.85765 +v 516.336 351.479 0.0 +v 516.3 351.462 -0.833146 +v 516.189 351.409 -1.65827 +v 516.006 351.321 -2.46742 +v 515.753 351.2 -3.25281 +v 515.432 351.045 -4.00687 +v 515.045 350.86 -4.72235 +v 514.597 350.645 -5.39234 +v 514.092 350.402 -6.01041 +v 513.535 350.135 -6.57059 +v 512.93 349.845 -7.06749 +v 512.285 349.536 -7.49633 +v 511.606 349.21 -7.85298 +v 510.897 348.87 -8.13399 +v 510.168 348.52 -8.33667 +v 509.424 348.163 -8.45907 +v 508.673 347.802 -8.5 +v 507.922 347.442 -8.45907 +v 507.178 347.085 -8.33667 +v 506.448 346.735 -8.13399 +v 505.74 346.395 -7.85298 +v 505.06 346.069 -7.49633 +v 504.415 345.76 -7.06749 +v 503.811 345.47 -6.57059 +v 503.254 345.202 -6.01041 +v 502.749 344.96 -5.39234 +v 502.301 344.745 -4.72235 +v 501.914 344.56 -4.00687 +v 501.593 344.405 -3.25281 +v 501.339 344.284 -2.46742 +v 501.157 344.196 -1.65827 +v 501.046 344.143 -0.833146 +v 501.009 344.126 -1.04095e-15 +v 501.046 344.143 0.833146 +v 501.157 344.196 1.65827 +v 501.339 344.284 2.46742 +v 501.593 344.405 3.25281 +v 501.914 344.56 4.00687 +v 502.301 344.745 4.72235 +v 502.749 344.96 5.39234 +v 503.254 345.202 6.01041 +v 503.811 345.47 6.57059 +v 504.415 345.76 7.06749 +v 505.06 346.069 7.49633 +v 505.74 346.395 7.85298 +v 506.448 346.735 8.13399 +v 507.178 347.085 8.33667 +v 507.922 347.442 8.45907 +v 508.673 347.802 8.5 +v 509.424 348.163 8.45907 +v 510.168 348.52 8.33667 +v 510.897 348.87 8.13399 +v 511.606 349.21 7.85298 +v 512.285 349.536 7.49633 +v 512.93 349.845 7.06749 +v 513.535 350.135 6.57059 +v 514.092 350.402 6.01041 +v 514.597 350.645 5.39234 +v 515.045 350.86 4.72235 +v 515.432 351.045 4.00687 +v 515.753 351.2 3.25281 +v 516.006 351.321 2.46742 +v 516.189 351.409 1.65827 +v 516.3 351.462 0.833146 +v 529.166 321.048 0.0 +v 529.13 321.033 -0.808641 +v 529.019 320.989 -1.6095 +v 528.836 320.916 -2.39485 +v 528.583 320.816 -3.15714 +v 528.261 320.688 -3.88902 +v 527.874 320.534 -4.58345 +v 527.426 320.356 -5.23374 +v 526.921 320.155 -5.83363 +v 526.364 319.933 -6.37734 +v 525.759 319.693 -6.85962 +v 525.114 319.437 -7.27585 +v 524.434 319.166 -7.62201 +v 523.725 318.885 -7.89476 +v 522.996 318.595 -8.09148 +v 522.251 318.299 -8.21027 +v 521.5 318.0 -8.25 +v 520.749 317.701 -8.21027 +v 520.004 317.405 -8.09148 +v 519.275 317.115 -7.89476 +v 518.566 316.834 -7.62201 +v 517.886 316.563 -7.27585 +v 517.241 316.307 -6.85962 +v 516.636 316.067 -6.37734 +v 516.079 315.845 -5.83363 +v 515.574 315.644 -5.23374 +v 515.126 315.466 -4.58345 +v 514.739 315.312 -3.88902 +v 514.417 315.184 -3.15714 +v 514.164 315.084 -2.39485 +v 513.981 315.011 -1.6095 +v 513.87 314.967 -0.808641 +v 513.834 314.952 -1.01033e-15 +v 513.87 314.967 0.808641 +v 513.981 315.011 1.6095 +v 514.164 315.084 2.39485 +v 514.417 315.184 3.15714 +v 514.739 315.312 3.88902 +v 515.126 315.466 4.58345 +v 515.574 315.644 5.23374 +v 516.079 315.845 5.83363 +v 516.636 316.067 6.37734 +v 517.241 316.307 6.85962 +v 517.886 316.563 7.27585 +v 518.566 316.834 7.62201 +v 519.275 317.115 7.89476 +v 520.004 317.405 8.09148 +v 520.749 317.701 8.21027 +v 521.5 318.0 8.25 +v 522.251 318.299 8.21027 +v 522.996 318.595 8.09148 +v 523.725 318.885 7.89476 +v 524.434 319.166 7.62201 +v 525.114 319.437 7.27585 +v 525.759 319.693 6.85962 +v 526.364 319.933 6.37734 +v 526.921 320.155 5.83363 +v 527.426 320.356 5.23374 +v 527.874 320.534 4.58345 +v 528.261 320.688 3.88902 +v 528.583 320.816 3.15714 +v 528.836 320.916 2.39485 +v 529.019 320.989 1.6095 +v 529.13 321.033 0.808641 +f 1 66 2 +f 1 65 66 +f 2 67 3 +f 2 66 67 +f 3 68 4 +f 3 67 68 +f 4 69 5 +f 4 68 69 +f 5 70 6 +f 5 69 70 +f 6 71 7 +f 6 70 71 +f 7 72 8 +f 7 71 72 +f 8 73 9 +f 8 72 73 +f 9 74 10 +f 9 73 74 +f 10 75 11 +f 10 74 75 +f 11 76 12 +f 11 75 76 +f 12 77 13 +f 12 76 77 +f 13 78 14 +f 13 77 78 +f 14 79 15 +f 14 78 79 +f 15 80 16 +f 15 79 80 +f 16 81 17 +f 16 80 81 +f 17 82 18 +f 17 81 82 +f 18 83 19 +f 18 82 83 +f 19 84 20 +f 19 83 84 +f 20 85 21 +f 20 84 85 +f 21 86 22 +f 21 85 86 +f 22 87 23 +f 22 86 87 +f 23 88 24 +f 23 87 88 +f 24 89 25 +f 24 88 89 +f 25 90 26 +f 25 89 90 +f 26 91 27 +f 26 90 91 +f 27 92 28 +f 27 91 92 +f 28 93 29 +f 28 92 93 +f 29 94 30 +f 29 93 94 +f 30 95 31 +f 30 94 95 +f 31 96 32 +f 31 95 96 +f 32 97 33 +f 32 96 97 +f 33 98 34 +f 33 97 98 +f 34 99 35 +f 34 98 99 +f 35 100 36 +f 35 99 100 +f 36 101 37 +f 36 100 101 +f 37 102 38 +f 37 101 102 +f 38 103 39 +f 38 102 103 +f 39 104 40 +f 39 103 104 +f 40 105 41 +f 40 104 105 +f 41 106 42 +f 41 105 106 +f 42 107 43 +f 42 106 107 +f 43 108 44 +f 43 107 108 +f 44 109 45 +f 44 108 109 +f 45 110 46 +f 45 109 110 +f 46 111 47 +f 46 110 111 +f 47 112 48 +f 47 111 112 +f 48 113 49 +f 48 112 113 +f 49 114 50 +f 49 113 114 +f 50 115 51 +f 50 114 115 +f 51 116 52 +f 51 115 116 +f 52 117 53 +f 52 116 117 +f 53 118 54 +f 53 117 118 +f 54 119 55 +f 54 118 119 +f 55 120 56 +f 55 119 120 +f 56 121 57 +f 56 120 121 +f 57 122 58 +f 57 121 122 +f 58 123 59 +f 58 122 123 +f 59 124 60 +f 59 123 124 +f 60 125 61 +f 60 124 125 +f 61 126 62 +f 61 125 126 +f 62 127 63 +f 62 126 127 +f 63 128 64 +f 63 127 128 +f 64 65 1 +f 64 128 65 +f 65 130 66 +f 65 129 130 +f 66 131 67 +f 66 130 131 +f 67 132 68 +f 67 131 132 +f 68 133 69 +f 68 132 133 +f 69 134 70 +f 69 133 134 +f 70 135 71 +f 70 134 135 +f 71 136 72 +f 71 135 136 +f 72 137 73 +f 72 136 137 +f 73 138 74 +f 73 137 138 +f 74 139 75 +f 74 138 139 +f 75 140 76 +f 75 139 140 +f 76 141 77 +f 76 140 141 +f 77 142 78 +f 77 141 142 +f 78 143 79 +f 78 142 143 +f 79 144 80 +f 79 143 144 +f 80 145 81 +f 80 144 145 +f 81 146 82 +f 81 145 146 +f 82 147 83 +f 82 146 147 +f 83 148 84 +f 83 147 148 +f 84 149 85 +f 84 148 149 +f 85 150 86 +f 85 149 150 +f 86 151 87 +f 86 150 151 +f 87 152 88 +f 87 151 152 +f 88 153 89 +f 88 152 153 +f 89 154 90 +f 89 153 154 +f 90 155 91 +f 90 154 155 +f 91 156 92 +f 91 155 156 +f 92 157 93 +f 92 156 157 +f 93 158 94 +f 93 157 158 +f 94 159 95 +f 94 158 159 +f 95 160 96 +f 95 159 160 +f 96 161 97 +f 96 160 161 +f 97 162 98 +f 97 161 162 +f 98 163 99 +f 98 162 163 +f 99 164 100 +f 99 163 164 +f 100 165 101 +f 100 164 165 +f 101 166 102 +f 101 165 166 +f 102 167 103 +f 102 166 167 +f 103 168 104 +f 103 167 168 +f 104 169 105 +f 104 168 169 +f 105 170 106 +f 105 169 170 +f 106 171 107 +f 106 170 171 +f 107 172 108 +f 107 171 172 +f 108 173 109 +f 108 172 173 +f 109 174 110 +f 109 173 174 +f 110 175 111 +f 110 174 175 +f 111 176 112 +f 111 175 176 +f 112 177 113 +f 112 176 177 +f 113 178 114 +f 113 177 178 +f 114 179 115 +f 114 178 179 +f 115 180 116 +f 115 179 180 +f 116 181 117 +f 116 180 181 +f 117 182 118 +f 117 181 182 +f 118 183 119 +f 118 182 183 +f 119 184 120 +f 119 183 184 +f 120 185 121 +f 120 184 185 +f 121 186 122 +f 121 185 186 +f 122 187 123 +f 122 186 187 +f 123 188 124 +f 123 187 188 +f 124 189 125 +f 124 188 189 +f 125 190 126 +f 125 189 190 +f 126 191 127 +f 126 190 191 +f 127 192 128 +f 127 191 192 +f 128 129 65 +f 128 192 129 +f 129 194 130 +f 129 193 194 +f 130 195 131 +f 130 194 195 +f 131 196 132 +f 131 195 196 +f 132 197 133 +f 132 196 197 +f 133 198 134 +f 133 197 198 +f 134 199 135 +f 134 198 199 +f 135 200 136 +f 135 199 200 +f 136 201 137 +f 136 200 201 +f 137 202 138 +f 137 201 202 +f 138 203 139 +f 138 202 203 +f 139 204 140 +f 139 203 204 +f 140 205 141 +f 140 204 205 +f 141 206 142 +f 141 205 206 +f 142 207 143 +f 142 206 207 +f 143 208 144 +f 143 207 208 +f 144 209 145 +f 144 208 209 +f 145 210 146 +f 145 209 210 +f 146 211 147 +f 146 210 211 +f 147 212 148 +f 147 211 212 +f 148 213 149 +f 148 212 213 +f 149 214 150 +f 149 213 214 +f 150 215 151 +f 150 214 215 +f 151 216 152 +f 151 215 216 +f 152 217 153 +f 152 216 217 +f 153 218 154 +f 153 217 218 +f 154 219 155 +f 154 218 219 +f 155 220 156 +f 155 219 220 +f 156 221 157 +f 156 220 221 +f 157 222 158 +f 157 221 222 +f 158 223 159 +f 158 222 223 +f 159 224 160 +f 159 223 224 +f 160 225 161 +f 160 224 225 +f 161 226 162 +f 161 225 226 +f 162 227 163 +f 162 226 227 +f 163 228 164 +f 163 227 228 +f 164 229 165 +f 164 228 229 +f 165 230 166 +f 165 229 230 +f 166 231 167 +f 166 230 231 +f 167 232 168 +f 167 231 232 +f 168 233 169 +f 168 232 233 +f 169 234 170 +f 169 233 234 +f 170 235 171 +f 170 234 235 +f 171 236 172 +f 171 235 236 +f 172 237 173 +f 172 236 237 +f 173 238 174 +f 173 237 238 +f 174 239 175 +f 174 238 239 +f 175 240 176 +f 175 239 240 +f 176 241 177 +f 176 240 241 +f 177 242 178 +f 177 241 242 +f 178 243 179 +f 178 242 243 +f 179 244 180 +f 179 243 244 +f 180 245 181 +f 180 244 245 +f 181 246 182 +f 181 245 246 +f 182 247 183 +f 182 246 247 +f 183 248 184 +f 183 247 248 +f 184 249 185 +f 184 248 249 +f 185 250 186 +f 185 249 250 +f 186 251 187 +f 186 250 251 +f 187 252 188 +f 187 251 252 +f 188 253 189 +f 188 252 253 +f 189 254 190 +f 189 253 254 +f 190 255 191 +f 190 254 255 +f 191 256 192 +f 191 255 256 +f 192 193 129 +f 192 256 193 +f 193 258 194 +f 193 257 258 +f 194 259 195 +f 194 258 259 +f 195 260 196 +f 195 259 260 +f 196 261 197 +f 196 260 261 +f 197 262 198 +f 197 261 262 +f 198 263 199 +f 198 262 263 +f 199 264 200 +f 199 263 264 +f 200 265 201 +f 200 264 265 +f 201 266 202 +f 201 265 266 +f 202 267 203 +f 202 266 267 +f 203 268 204 +f 203 267 268 +f 204 269 205 +f 204 268 269 +f 205 270 206 +f 205 269 270 +f 206 271 207 +f 206 270 271 +f 207 272 208 +f 207 271 272 +f 208 273 209 +f 208 272 273 +f 209 274 210 +f 209 273 274 +f 210 275 211 +f 210 274 275 +f 211 276 212 +f 211 275 276 +f 212 277 213 +f 212 276 277 +f 213 278 214 +f 213 277 278 +f 214 279 215 +f 214 278 279 +f 215 280 216 +f 215 279 280 +f 216 281 217 +f 216 280 281 +f 217 282 218 +f 217 281 282 +f 218 283 219 +f 218 282 283 +f 219 284 220 +f 219 283 284 +f 220 285 221 +f 220 284 285 +f 221 286 222 +f 221 285 286 +f 222 287 223 +f 222 286 287 +f 223 288 224 +f 223 287 288 +f 224 289 225 +f 224 288 289 +f 225 290 226 +f 225 289 290 +f 226 291 227 +f 226 290 291 +f 227 292 228 +f 227 291 292 +f 228 293 229 +f 228 292 293 +f 229 294 230 +f 229 293 294 +f 230 295 231 +f 230 294 295 +f 231 296 232 +f 231 295 296 +f 232 297 233 +f 232 296 297 +f 233 298 234 +f 233 297 298 +f 234 299 235 +f 234 298 299 +f 235 300 236 +f 235 299 300 +f 236 301 237 +f 236 300 301 +f 237 302 238 +f 237 301 302 +f 238 303 239 +f 238 302 303 +f 239 304 240 +f 239 303 304 +f 240 305 241 +f 240 304 305 +f 241 306 242 +f 241 305 306 +f 242 307 243 +f 242 306 307 +f 243 308 244 +f 243 307 308 +f 244 309 245 +f 244 308 309 +f 245 310 246 +f 245 309 310 +f 246 311 247 +f 246 310 311 +f 247 312 248 +f 247 311 312 +f 248 313 249 +f 248 312 313 +f 249 314 250 +f 249 313 314 +f 250 315 251 +f 250 314 315 +f 251 316 252 +f 251 315 316 +f 252 317 253 +f 252 316 317 +f 253 318 254 +f 253 317 318 +f 254 319 255 +f 254 318 319 +f 255 320 256 +f 255 319 320 +f 256 257 193 +f 256 320 257 +f 257 322 258 +f 257 321 322 +f 258 323 259 +f 258 322 323 +f 259 324 260 +f 259 323 324 +f 260 325 261 +f 260 324 325 +f 261 326 262 +f 261 325 326 +f 262 327 263 +f 262 326 327 +f 263 328 264 +f 263 327 328 +f 264 329 265 +f 264 328 329 +f 265 330 266 +f 265 329 330 +f 266 331 267 +f 266 330 331 +f 267 332 268 +f 267 331 332 +f 268 333 269 +f 268 332 333 +f 269 334 270 +f 269 333 334 +f 270 335 271 +f 270 334 335 +f 271 336 272 +f 271 335 336 +f 272 337 273 +f 272 336 337 +f 273 338 274 +f 273 337 338 +f 274 339 275 +f 274 338 339 +f 275 340 276 +f 275 339 340 +f 276 341 277 +f 276 340 341 +f 277 342 278 +f 277 341 342 +f 278 343 279 +f 278 342 343 +f 279 344 280 +f 279 343 344 +f 280 345 281 +f 280 344 345 +f 281 346 282 +f 281 345 346 +f 282 347 283 +f 282 346 347 +f 283 348 284 +f 283 347 348 +f 284 349 285 +f 284 348 349 +f 285 350 286 +f 285 349 350 +f 286 351 287 +f 286 350 351 +f 287 352 288 +f 287 351 352 +f 288 353 289 +f 288 352 353 +f 289 354 290 +f 289 353 354 +f 290 355 291 +f 290 354 355 +f 291 356 292 +f 291 355 356 +f 292 357 293 +f 292 356 357 +f 293 358 294 +f 293 357 358 +f 294 359 295 +f 294 358 359 +f 295 360 296 +f 295 359 360 +f 296 361 297 +f 296 360 361 +f 297 362 298 +f 297 361 362 +f 298 363 299 +f 298 362 363 +f 299 364 300 +f 299 363 364 +f 300 365 301 +f 300 364 365 +f 301 366 302 +f 301 365 366 +f 302 367 303 +f 302 366 367 +f 303 368 304 +f 303 367 368 +f 304 369 305 +f 304 368 369 +f 305 370 306 +f 305 369 370 +f 306 371 307 +f 306 370 371 +f 307 372 308 +f 307 371 372 +f 308 373 309 +f 308 372 373 +f 309 374 310 +f 309 373 374 +f 310 375 311 +f 310 374 375 +f 311 376 312 +f 311 375 376 +f 312 377 313 +f 312 376 377 +f 313 378 314 +f 313 377 378 +f 314 379 315 +f 314 378 379 +f 315 380 316 +f 315 379 380 +f 316 381 317 +f 316 380 381 +f 317 382 318 +f 317 381 382 +f 318 383 319 +f 318 382 383 +f 319 384 320 +f 319 383 384 +f 320 321 257 +f 320 384 321 +f 321 386 322 +f 321 385 386 +f 322 387 323 +f 322 386 387 +f 323 388 324 +f 323 387 388 +f 324 389 325 +f 324 388 389 +f 325 390 326 +f 325 389 390 +f 326 391 327 +f 326 390 391 +f 327 392 328 +f 327 391 392 +f 328 393 329 +f 328 392 393 +f 329 394 330 +f 329 393 394 +f 330 395 331 +f 330 394 395 +f 331 396 332 +f 331 395 396 +f 332 397 333 +f 332 396 397 +f 333 398 334 +f 333 397 398 +f 334 399 335 +f 334 398 399 +f 335 400 336 +f 335 399 400 +f 336 401 337 +f 336 400 401 +f 337 402 338 +f 337 401 402 +f 338 403 339 +f 338 402 403 +f 339 404 340 +f 339 403 404 +f 340 405 341 +f 340 404 405 +f 341 406 342 +f 341 405 406 +f 342 407 343 +f 342 406 407 +f 343 408 344 +f 343 407 408 +f 344 409 345 +f 344 408 409 +f 345 410 346 +f 345 409 410 +f 346 411 347 +f 346 410 411 +f 347 412 348 +f 347 411 412 +f 348 413 349 +f 348 412 413 +f 349 414 350 +f 349 413 414 +f 350 415 351 +f 350 414 415 +f 351 416 352 +f 351 415 416 +f 352 417 353 +f 352 416 417 +f 353 418 354 +f 353 417 418 +f 354 419 355 +f 354 418 419 +f 355 420 356 +f 355 419 420 +f 356 421 357 +f 356 420 421 +f 357 422 358 +f 357 421 422 +f 358 423 359 +f 358 422 423 +f 359 424 360 +f 359 423 424 +f 360 425 361 +f 360 424 425 +f 361 426 362 +f 361 425 426 +f 362 427 363 +f 362 426 427 +f 363 428 364 +f 363 427 428 +f 364 429 365 +f 364 428 429 +f 365 430 366 +f 365 429 430 +f 366 431 367 +f 366 430 431 +f 367 432 368 +f 367 431 432 +f 368 433 369 +f 368 432 433 +f 369 434 370 +f 369 433 434 +f 370 435 371 +f 370 434 435 +f 371 436 372 +f 371 435 436 +f 372 437 373 +f 372 436 437 +f 373 438 374 +f 373 437 438 +f 374 439 375 +f 374 438 439 +f 375 440 376 +f 375 439 440 +f 376 441 377 +f 376 440 441 +f 377 442 378 +f 377 441 442 +f 378 443 379 +f 378 442 443 +f 379 444 380 +f 379 443 444 +f 380 445 381 +f 380 444 445 +f 381 446 382 +f 381 445 446 +f 382 447 383 +f 382 446 447 +f 383 448 384 +f 383 447 448 +f 384 385 321 +f 384 448 385 +f 385 450 386 +f 385 449 450 +f 386 451 387 +f 386 450 451 +f 387 452 388 +f 387 451 452 +f 388 453 389 +f 388 452 453 +f 389 454 390 +f 389 453 454 +f 390 455 391 +f 390 454 455 +f 391 456 392 +f 391 455 456 +f 392 457 393 +f 392 456 457 +f 393 458 394 +f 393 457 458 +f 394 459 395 +f 394 458 459 +f 395 460 396 +f 395 459 460 +f 396 461 397 +f 396 460 461 +f 397 462 398 +f 397 461 462 +f 398 463 399 +f 398 462 463 +f 399 464 400 +f 399 463 464 +f 400 465 401 +f 400 464 465 +f 401 466 402 +f 401 465 466 +f 402 467 403 +f 402 466 467 +f 403 468 404 +f 403 467 468 +f 404 469 405 +f 404 468 469 +f 405 470 406 +f 405 469 470 +f 406 471 407 +f 406 470 471 +f 407 472 408 +f 407 471 472 +f 408 473 409 +f 408 472 473 +f 409 474 410 +f 409 473 474 +f 410 475 411 +f 410 474 475 +f 411 476 412 +f 411 475 476 +f 412 477 413 +f 412 476 477 +f 413 478 414 +f 413 477 478 +f 414 479 415 +f 414 478 479 +f 415 480 416 +f 415 479 480 +f 416 481 417 +f 416 480 481 +f 417 482 418 +f 417 481 482 +f 418 483 419 +f 418 482 483 +f 419 484 420 +f 419 483 484 +f 420 485 421 +f 420 484 485 +f 421 486 422 +f 421 485 486 +f 422 487 423 +f 422 486 487 +f 423 488 424 +f 423 487 488 +f 424 489 425 +f 424 488 489 +f 425 490 426 +f 425 489 490 +f 426 491 427 +f 426 490 491 +f 427 492 428 +f 427 491 492 +f 428 493 429 +f 428 492 493 +f 429 494 430 +f 429 493 494 +f 430 495 431 +f 430 494 495 +f 431 496 432 +f 431 495 496 +f 432 497 433 +f 432 496 497 +f 433 498 434 +f 433 497 498 +f 434 499 435 +f 434 498 499 +f 435 500 436 +f 435 499 500 +f 436 501 437 +f 436 500 501 +f 437 502 438 +f 437 501 502 +f 438 503 439 +f 438 502 503 +f 439 504 440 +f 439 503 504 +f 440 505 441 +f 440 504 505 +f 441 506 442 +f 441 505 506 +f 442 507 443 +f 442 506 507 +f 443 508 444 +f 443 507 508 +f 444 509 445 +f 444 508 509 +f 445 510 446 +f 445 509 510 +f 446 511 447 +f 446 510 511 +f 447 512 448 +f 447 511 512 +f 448 449 385 +f 448 512 449 +f 449 514 450 +f 449 513 514 +f 450 515 451 +f 450 514 515 +f 451 516 452 +f 451 515 516 +f 452 517 453 +f 452 516 517 +f 453 518 454 +f 453 517 518 +f 454 519 455 +f 454 518 519 +f 455 520 456 +f 455 519 520 +f 456 521 457 +f 456 520 521 +f 457 522 458 +f 457 521 522 +f 458 523 459 +f 458 522 523 +f 459 524 460 +f 459 523 524 +f 460 525 461 +f 460 524 525 +f 461 526 462 +f 461 525 526 +f 462 527 463 +f 462 526 527 +f 463 528 464 +f 463 527 528 +f 464 529 465 +f 464 528 529 +f 465 530 466 +f 465 529 530 +f 466 531 467 +f 466 530 531 +f 467 532 468 +f 467 531 532 +f 468 533 469 +f 468 532 533 +f 469 534 470 +f 469 533 534 +f 470 535 471 +f 470 534 535 +f 471 536 472 +f 471 535 536 +f 472 537 473 +f 472 536 537 +f 473 538 474 +f 473 537 538 +f 474 539 475 +f 474 538 539 +f 475 540 476 +f 475 539 540 +f 476 541 477 +f 476 540 541 +f 477 542 478 +f 477 541 542 +f 478 543 479 +f 478 542 543 +f 479 544 480 +f 479 543 544 +f 480 545 481 +f 480 544 545 +f 481 546 482 +f 481 545 546 +f 482 547 483 +f 482 546 547 +f 483 548 484 +f 483 547 548 +f 484 549 485 +f 484 548 549 +f 485 550 486 +f 485 549 550 +f 486 551 487 +f 486 550 551 +f 487 552 488 +f 487 551 552 +f 488 553 489 +f 488 552 553 +f 489 554 490 +f 489 553 554 +f 490 555 491 +f 490 554 555 +f 491 556 492 +f 491 555 556 +f 492 557 493 +f 492 556 557 +f 493 558 494 +f 493 557 558 +f 494 559 495 +f 494 558 559 +f 495 560 496 +f 495 559 560 +f 496 561 497 +f 496 560 561 +f 497 562 498 +f 497 561 562 +f 498 563 499 +f 498 562 563 +f 499 564 500 +f 499 563 564 +f 500 565 501 +f 500 564 565 +f 501 566 502 +f 501 565 566 +f 502 567 503 +f 502 566 567 +f 503 568 504 +f 503 567 568 +f 504 569 505 +f 504 568 569 +f 505 570 506 +f 505 569 570 +f 506 571 507 +f 506 570 571 +f 507 572 508 +f 507 571 572 +f 508 573 509 +f 508 572 573 +f 509 574 510 +f 509 573 574 +f 510 575 511 +f 510 574 575 +f 511 576 512 +f 511 575 576 +f 512 513 449 +f 512 576 513 +f 513 578 514 +f 513 577 578 +f 514 579 515 +f 514 578 579 +f 515 580 516 +f 515 579 580 +f 516 581 517 +f 516 580 581 +f 517 582 518 +f 517 581 582 +f 518 583 519 +f 518 582 583 +f 519 584 520 +f 519 583 584 +f 520 585 521 +f 520 584 585 +f 521 586 522 +f 521 585 586 +f 522 587 523 +f 522 586 587 +f 523 588 524 +f 523 587 588 +f 524 589 525 +f 524 588 589 +f 525 590 526 +f 525 589 590 +f 526 591 527 +f 526 590 591 +f 527 592 528 +f 527 591 592 +f 528 593 529 +f 528 592 593 +f 529 594 530 +f 529 593 594 +f 530 595 531 +f 530 594 595 +f 531 596 532 +f 531 595 596 +f 532 597 533 +f 532 596 597 +f 533 598 534 +f 533 597 598 +f 534 599 535 +f 534 598 599 +f 535 600 536 +f 535 599 600 +f 536 601 537 +f 536 600 601 +f 537 602 538 +f 537 601 602 +f 538 603 539 +f 538 602 603 +f 539 604 540 +f 539 603 604 +f 540 605 541 +f 540 604 605 +f 541 606 542 +f 541 605 606 +f 542 607 543 +f 542 606 607 +f 543 608 544 +f 543 607 608 +f 544 609 545 +f 544 608 609 +f 545 610 546 +f 545 609 610 +f 546 611 547 +f 546 610 611 +f 547 612 548 +f 547 611 612 +f 548 613 549 +f 548 612 613 +f 549 614 550 +f 549 613 614 +f 550 615 551 +f 550 614 615 +f 551 616 552 +f 551 615 616 +f 552 617 553 +f 552 616 617 +f 553 618 554 +f 553 617 618 +f 554 619 555 +f 554 618 619 +f 555 620 556 +f 555 619 620 +f 556 621 557 +f 556 620 621 +f 557 622 558 +f 557 621 622 +f 558 623 559 +f 558 622 623 +f 559 624 560 +f 559 623 624 +f 560 625 561 +f 560 624 625 +f 561 626 562 +f 561 625 626 +f 562 627 563 +f 562 626 627 +f 563 628 564 +f 563 627 628 +f 564 629 565 +f 564 628 629 +f 565 630 566 +f 565 629 630 +f 566 631 567 +f 566 630 631 +f 567 632 568 +f 567 631 632 +f 568 633 569 +f 568 632 633 +f 569 634 570 +f 569 633 634 +f 570 635 571 +f 570 634 635 +f 571 636 572 +f 571 635 636 +f 572 637 573 +f 572 636 637 +f 573 638 574 +f 573 637 638 +f 574 639 575 +f 574 638 639 +f 575 640 576 +f 575 639 640 +f 576 577 513 +f 576 640 577 diff --git a/data/DebugImages/check_3d_bezier2.obj b/data/DebugImages/check_3d_bezier2.obj new file mode 100644 index 0000000..2b50efb --- /dev/null +++ b/data/DebugImages/check_3d_bezier2.obj @@ -0,0 +1,1793 @@ +# Branch +v -0.609109 0.436436 0.218218 +v -0.608584 0.456252 0.173333 +v -0.607012 0.471673 0.126778 +v -0.604411 0.482553 0.0790022 +v -0.600804 0.488785 0.0304658 +v -0.596225 0.49031 -0.018364 +v -0.590721 0.487112 -0.067017 +v -0.584342 0.479224 -0.115025 +v -0.577152 0.466721 -0.161924 +v -0.569218 0.449722 -0.207265 +v -0.560618 0.428393 -0.250609 +v -0.551434 0.402938 -0.29154 +v -0.541754 0.373602 -0.329663 +v -0.531673 0.340669 -0.364611 +v -0.521286 0.304455 -0.396048 +v -0.510695 0.265308 -0.423671 +v -0.5 0.223607 -0.447214 +v -0.489305 0.179752 -0.466449 +v -0.478714 0.134166 -0.481193 +v -0.468327 0.0872877 -0.491302 +v -0.458246 0.039569 -0.49668 +v -0.448566 -0.00853081 -0.497274 +v -0.439382 -0.0565485 -0.49308 +v -0.430782 -0.104022 -0.484137 +v -0.422848 -0.150493 -0.470531 +v -0.415658 -0.195515 -0.452394 +v -0.409279 -0.238654 -0.4299 +v -0.403775 -0.279494 -0.403266 +v -0.399196 -0.317643 -0.372748 +v -0.395589 -0.352733 -0.338641 +v -0.392988 -0.384426 -0.301272 +v -0.391416 -0.412417 -0.261002 +v -0.390891 -0.436436 -0.218218 +v -0.391416 -0.456252 -0.173333 +v -0.392988 -0.471673 -0.126778 +v -0.395589 -0.482553 -0.0790022 +v -0.399196 -0.488785 -0.0304658 +v -0.403775 -0.49031 0.018364 +v -0.409279 -0.487112 0.067017 +v -0.415658 -0.479224 0.115025 +v -0.422848 -0.466721 0.161924 +v -0.430782 -0.449722 0.207265 +v -0.439382 -0.428393 0.250609 +v -0.448566 -0.402938 0.29154 +v -0.458246 -0.373602 0.329663 +v -0.468327 -0.340669 0.364611 +v -0.478714 -0.304455 0.396048 +v -0.489305 -0.265308 0.423671 +v -0.5 -0.223607 0.447214 +v -0.510695 -0.179752 0.466449 +v -0.521286 -0.134166 0.481193 +v -0.531673 -0.0872877 0.491302 +v -0.541754 -0.039569 0.49668 +v -0.551434 0.00853081 0.497274 +v -0.560618 0.0565485 0.49308 +v -0.569218 0.104022 0.484137 +v -0.577152 0.150493 0.470531 +v -0.584342 0.195515 0.452394 +v -0.590721 0.238654 0.4299 +v -0.596225 0.279494 0.403266 +v -0.600804 0.317643 0.372748 +v -0.604411 0.352733 0.338641 +v -0.607012 0.384426 0.301272 +v -0.608584 0.412417 0.261002 +v -0.469802 0.435875 0.217938 +v -0.469412 0.454571 0.175536 +v -0.468247 0.469079 0.13154 +v -0.466317 0.479261 0.0863715 +v -0.463642 0.485016 0.0404665 +v -0.460247 0.486292 -0.00573309 +v -0.456165 0.483074 -0.0517823 +v -0.451435 0.475394 -0.0972378 +v -0.446103 0.463326 -0.141662 +v -0.440219 0.446986 -0.184626 +v -0.433842 0.426531 -0.225717 +v -0.427031 0.40216 -0.26454 +v -0.419853 0.374105 -0.300719 +v -0.412377 0.342638 -0.333908 +v -0.404674 0.308061 -0.363785 +v -0.39682 0.270707 -0.390064 +v -0.388889 0.230937 -0.412492 +v -0.380958 0.189133 -0.430852 +v -0.373104 0.145698 -0.444967 +v -0.365401 0.10105 -0.454702 +v -0.357925 0.0556188 -0.459962 +v -0.350747 0.00984233 -0.460698 +v -0.343936 -0.0358387 -0.456902 +v -0.337558 -0.0809844 -0.448611 +v -0.331675 -0.12516 -0.435904 +v -0.326343 -0.16794 -0.418904 +v -0.321612 -0.208912 -0.397775 +v -0.31753 -0.247682 -0.37272 +v -0.314135 -0.283877 -0.34398 +v -0.31146 -0.317147 -0.311833 +v -0.309531 -0.347173 -0.276587 +v -0.308366 -0.373666 -0.238582 +v -0.307976 -0.396369 -0.198184 +v -0.308366 -0.415065 -0.155783 +v -0.309531 -0.429573 -0.111787 +v -0.31146 -0.439754 -0.0666184 +v -0.314135 -0.44551 -0.0207134 +v -0.31753 -0.446785 0.0254862 +v -0.321612 -0.443567 0.0715354 +v -0.326343 -0.435887 0.116991 +v -0.331675 -0.423819 0.161415 +v -0.337558 -0.40748 0.204379 +v -0.343936 -0.387025 0.245471 +v -0.350747 -0.362653 0.284293 +v -0.357925 -0.334599 0.320473 +v -0.365401 -0.303131 0.353661 +v -0.373104 -0.268555 0.383539 +v -0.380958 -0.231201 0.409818 +v -0.388889 -0.191431 0.432245 +v -0.39682 -0.149627 0.450605 +v -0.404674 -0.106192 0.46472 +v -0.412377 -0.0615437 0.474455 +v -0.419853 -0.0161126 0.479716 +v -0.427031 0.0296638 0.480452 +v -0.433842 0.0753449 0.476656 +v -0.440219 0.120491 0.468364 +v -0.446103 0.164666 0.455657 +v -0.451435 0.207446 0.438658 +v -0.456165 0.248418 0.417528 +v -0.460247 0.287188 0.392473 +v -0.463642 0.323383 0.363733 +v -0.466317 0.356654 0.331586 +v -0.468247 0.386679 0.29634 +v -0.469412 0.413172 0.258335 +v -0.332568 0.429059 0.214529 +v -0.332304 0.446641 0.174616 +v -0.331515 0.460255 0.133186 +v -0.330209 0.46977 0.0906412 +v -0.328398 0.475093 0.0473895 +v -0.326099 0.476173 0.00384779 +v -0.323334 0.473001 -0.0395645 +v -0.320131 0.465607 -0.0824293 +v -0.31652 0.454061 -0.124334 +v -0.312536 0.438475 -0.164874 +v -0.308218 0.419 -0.203661 +v -0.303606 0.395822 -0.240319 +v -0.298745 0.369165 -0.274497 +v -0.293683 0.339286 -0.305865 +v -0.288467 0.306472 -0.33412 +v -0.283148 0.271039 -0.358992 +v -0.277778 0.233329 -0.380239 +v -0.272407 0.193706 -0.397658 +v -0.267089 0.152549 -0.411082 +v -0.261873 0.110256 -0.420379 +v -0.25681 0.0672345 -0.425462 +v -0.25195 0.0238982 -0.426281 +v -0.247338 -0.0193353 -0.422828 +v -0.243019 -0.0620497 -0.415137 +v -0.239035 -0.103834 -0.403281 +v -0.235424 -0.144285 -0.387375 +v -0.232221 -0.183013 -0.367572 +v -0.229457 -0.219646 -0.344062 +v -0.227158 -0.253831 -0.317073 +v -0.225347 -0.285239 -0.286863 +v -0.22404 -0.313567 -0.253724 +v -0.223251 -0.338541 -0.217976 +v -0.222987 -0.359923 -0.179962 +v -0.223251 -0.377505 -0.140048 +v -0.22404 -0.391119 -0.0986186 +v -0.225347 -0.400634 -0.0560733 +v -0.227158 -0.405957 -0.0128216 +v -0.229457 -0.407038 0.0307201 +v -0.232221 -0.403865 0.0741324 +v -0.235424 -0.396471 0.116997 +v -0.239035 -0.384925 0.158902 +v -0.243019 -0.369339 0.199442 +v -0.247338 -0.349864 0.238229 +v -0.25195 -0.326686 0.274887 +v -0.25681 -0.300029 0.309065 +v -0.261873 -0.27015 0.340433 +v -0.267089 -0.237336 0.368688 +v -0.272407 -0.201903 0.39356 +v -0.277778 -0.164194 0.414807 +v -0.283148 -0.12457 0.432226 +v -0.288467 -0.0834132 0.44565 +v -0.293683 -0.0411204 0.454947 +v -0.298745 0.00190128 0.46003 +v -0.303606 0.0452376 0.460849 +v -0.308218 0.0884711 0.457396 +v -0.312536 0.131186 0.449705 +v -0.31652 0.172969 0.437849 +v -0.320131 0.21342 0.421943 +v -0.323334 0.252149 0.40214 +v -0.326099 0.288782 0.37863 +v -0.328398 0.322967 0.351641 +v -0.330209 0.354375 0.321431 +v -0.331515 0.382702 0.288292 +v -0.332304 0.407677 0.252544 +v -0.197637 0.416092 0.208046 +v -0.197488 0.432566 0.170622 +v -0.197042 0.445303 0.131769 +v -0.196304 0.45418 0.0918615 +v -0.19528 0.45911 0.0512831 +v -0.19398 0.460047 0.0104248 +v -0.192418 0.456982 -0.03032 +v -0.190607 0.449944 -0.0705587 +v -0.188566 0.439 -0.109904 +v -0.186314 0.424257 -0.147977 +v -0.183873 0.405856 -0.18441 +v -0.181266 0.383974 -0.218854 +v -0.178519 0.358822 -0.250976 +v -0.175657 0.330643 -0.280467 +v -0.172709 0.299708 -0.307042 +v -0.169702 0.266314 -0.330447 +v -0.166667 0.230783 -0.350456 +v -0.163631 0.193458 -0.366875 +v -0.160625 0.154698 -0.379547 +v -0.157676 0.114876 -0.38835 +v -0.154815 0.0743761 -0.393199 +v -0.152067 0.0335876 -0.394047 +v -0.14946 -0.00709639 -0.390886 +v -0.147019 -0.047284 -0.383747 +v -0.144767 -0.0865882 -0.372698 +v -0.142726 -0.12463 -0.357846 +v -0.140916 -0.161044 -0.339333 +v -0.139353 -0.195479 -0.317339 +v -0.138054 -0.227604 -0.292074 +v -0.13703 -0.257108 -0.263783 +v -0.136291 -0.283709 -0.232737 +v -0.135845 -0.307149 -0.199235 +v -0.135696 -0.327203 -0.163601 +v -0.135845 -0.343677 -0.126178 +v -0.136291 -0.356414 -0.0873249 +v -0.13703 -0.365291 -0.0474171 +v -0.138054 -0.370222 -0.00683865 +v -0.139353 -0.371159 0.0340197 +v -0.140916 -0.368093 0.0747644 +v -0.142726 -0.361055 0.115003 +v -0.144767 -0.350111 0.154348 +v -0.147019 -0.335368 0.192421 +v -0.14946 -0.316967 0.228855 +v -0.152067 -0.295085 0.263298 +v -0.154815 -0.269934 0.29542 +v -0.157676 -0.241754 0.324911 +v -0.160625 -0.210819 0.351487 +v -0.163631 -0.177425 0.374892 +v -0.166667 -0.141895 0.3949 +v -0.169702 -0.104569 0.41132 +v -0.172709 -0.0658094 0.423992 +v -0.175657 -0.0259874 0.432795 +v -0.178519 0.0145128 0.437643 +v -0.181266 0.0553013 0.438491 +v -0.183873 0.0959853 0.435331 +v -0.186314 0.136173 0.428191 +v -0.188566 0.175477 0.417142 +v -0.190607 0.213519 0.40229 +v -0.192418 0.249933 0.383778 +v -0.19398 0.284368 0.361783 +v -0.19528 0.316493 0.336518 +v -0.196304 0.345997 0.308227 +v -0.197042 0.372597 0.277181 +v -0.197488 0.396038 0.24368 +v -0.0652146 0.397108 0.198554 +v -0.0651681 0.412481 0.163623 +v -0.065029 0.424356 0.127355 +v -0.0647987 0.432621 0.0900971 +v -0.0644793 0.437194 0.0522097 +v -0.0640741 0.438033 0.0140574 +v -0.0635868 0.435129 -0.0239926 +v -0.0630221 0.42851 -0.0615737 +v -0.0623855 0.418239 -0.098324 +v -0.0616832 0.404417 -0.13389 +v -0.0609218 0.387175 -0.167928 +v -0.0601088 0.36668 -0.200111 +v -0.0592519 0.343129 -0.23013 +v -0.0583594 0.31675 -0.257694 +v -0.0574399 0.287795 -0.282539 +v -0.0565023 0.256545 -0.304425 +v -0.0555556 0.223299 -0.323141 +v -0.0546088 0.188379 -0.338508 +v -0.0536712 0.152119 -0.350377 +v -0.0527517 0.114871 -0.358634 +v -0.0518592 0.0769917 -0.363199 +v -0.0510023 0.0388466 -0.364028 +v -0.0501893 0.000802985 -0.361114 +v -0.0494279 -0.0367728 -0.354484 +v -0.0487256 -0.0735189 -0.344203 +v -0.048089 -0.109081 -0.330369 +v -0.0475244 -0.143118 -0.313116 +v -0.047037 -0.1753 -0.292609 +v -0.0466318 -0.205319 -0.269047 +v -0.0463124 -0.232885 -0.242655 +v -0.0460821 -0.257732 -0.213689 +v -0.045943 -0.279622 -0.182428 +v -0.0458965 -0.298343 -0.149171 +v -0.045943 -0.313715 -0.114241 +v -0.0460821 -0.325591 -0.0779719 +v -0.0463124 -0.333855 -0.0407144 +v -0.0466318 -0.338429 -0.00282703 +v -0.047037 -0.339267 0.0353254 +v -0.0475244 -0.336363 0.0733753 +v -0.048089 -0.329744 0.110956 +v -0.0487256 -0.319474 0.147707 +v -0.0494279 -0.305651 0.183272 +v -0.0501893 -0.288409 0.217311 +v -0.0510023 -0.267915 0.249494 +v -0.0518592 -0.244364 0.279513 +v -0.0527517 -0.217984 0.307077 +v -0.0536712 -0.18903 0.331922 +v -0.0546088 -0.157779 0.353808 +v -0.0555556 -0.124534 0.372524 +v -0.0565023 -0.0896132 0.387891 +v -0.0574399 -0.053354 0.39976 +v -0.0583594 -0.0161055 0.408016 +v -0.0592519 0.0217737 0.412581 +v -0.0601088 0.0599188 0.413411 +v -0.0609218 0.0979624 0.410497 +v -0.0616832 0.135538 0.403867 +v -0.0623855 0.172284 0.393586 +v -0.0630221 0.207847 0.379752 +v -0.0635868 0.241883 0.362498 +v -0.0640741 0.274066 0.341992 +v -0.0644793 0.304084 0.318429 +v -0.0647987 0.33165 0.292038 +v -0.065029 0.356497 0.263072 +v -0.0651681 0.378387 0.23181 +v 0.0645247 0.372271 0.186135 +v 0.0644815 0.386545 0.1537 +v 0.0643523 0.397572 0.120021 +v 0.0641385 0.405246 0.0854253 +v 0.0638419 0.409493 0.0502441 +v 0.0634656 0.410272 0.0148169 +v 0.0630131 0.407575 -0.0205152 +v 0.0624888 0.401429 -0.0554119 +v 0.0618977 0.391892 -0.0895372 +v 0.0612455 0.379057 -0.122562 +v 0.0605385 0.363047 -0.15417 +v 0.0597836 0.344016 -0.184054 +v 0.0589879 0.322147 -0.211928 +v 0.0581592 0.297652 -0.237524 +v 0.0573053 0.270766 -0.260594 +v 0.0564347 0.241747 -0.280917 +v 0.0555556 0.210877 -0.298296 +v 0.0546764 0.17845 -0.312565 +v 0.0538058 0.144781 -0.323586 +v 0.052952 0.110193 -0.331253 +v 0.0521232 0.0750197 -0.335492 +v 0.0513275 0.0395992 -0.336262 +v 0.0505726 0.00427297 -0.333556 +v 0.0498656 -0.0306188 -0.3274 +v 0.0492134 -0.0647402 -0.317853 +v 0.0486223 -0.0977625 -0.305008 +v 0.048098 -0.129368 -0.288987 +v 0.0476455 -0.159251 -0.269945 +v 0.0472692 -0.187126 -0.248065 +v 0.0469727 -0.212723 -0.223559 +v 0.0467588 -0.235795 -0.196662 +v 0.0466296 -0.256121 -0.167634 +v 0.0465864 -0.273505 -0.136753 +v 0.0466296 -0.28778 -0.104317 +v 0.0467588 -0.298807 -0.0706388 +v 0.0469727 -0.306481 -0.0360425 +v 0.0472692 -0.310728 -0.000861426 +v 0.0476455 -0.311507 0.0345658 +v 0.048098 -0.30881 0.0698979 +v 0.0486223 -0.302664 0.104795 +v 0.0492134 -0.293127 0.13892 +v 0.0498656 -0.280292 0.171945 +v 0.0505726 -0.264281 0.203552 +v 0.0513275 -0.24525 0.233437 +v 0.0521232 -0.223382 0.261311 +v 0.052952 -0.198887 0.286907 +v 0.0538058 -0.172 0.309977 +v 0.0546764 -0.142982 0.330299 +v 0.0555556 -0.112111 0.347679 +v 0.0564347 -0.0796849 0.361948 +v 0.0573053 -0.0460157 0.372969 +v 0.0581592 -0.0114278 0.380636 +v 0.0589879 0.0237458 0.384875 +v 0.0597836 0.0591662 0.385645 +v 0.0605385 0.0944925 0.382939 +v 0.0612455 0.129384 0.376783 +v 0.0618977 0.163506 0.367236 +v 0.0624888 0.196528 0.35439 +v 0.0630131 0.228133 0.338369 +v 0.0634656 0.258017 0.319328 +v 0.0638419 0.285891 0.297448 +v 0.0641385 0.311488 0.272942 +v 0.0643523 0.334561 0.246045 +v 0.0644815 0.354887 0.217016 +v 0.191443 0.341762 0.170881 +v 0.191324 0.354942 0.140942 +v 0.190967 0.365132 0.10986 +v 0.190376 0.372233 0.0779337 +v 0.189557 0.376177 0.0454709 +v 0.188518 0.376927 0.0127843 +v 0.187268 0.374475 -0.0198115 +v 0.185819 0.368844 -0.0520025 +v 0.184186 0.360089 -0.0834786 +v 0.182385 0.348294 -0.113937 +v 0.180432 0.333573 -0.143084 +v 0.178346 0.316068 -0.170639 +v 0.176148 0.295947 -0.196336 +v 0.173859 0.273403 -0.219929 +v 0.1715 0.248655 -0.24119 +v 0.169095 0.22194 -0.259913 +v 0.166667 0.193516 -0.27592 +v 0.164238 0.163656 -0.289056 +v 0.161833 0.132647 -0.299193 +v 0.159474 0.10079 -0.306236 +v 0.157185 0.0683897 -0.310115 +v 0.154987 0.0357589 -0.310793 +v 0.152902 0.00321178 -0.308265 +v 0.150949 -0.0289383 -0.302553 +v 0.149147 -0.0603816 -0.293714 +v 0.147514 -0.0908154 -0.281832 +v 0.146066 -0.119947 -0.267022 +v 0.144816 -0.147495 -0.249427 +v 0.143776 -0.173194 -0.229215 +v 0.142957 -0.196798 -0.206582 +v 0.142366 -0.218078 -0.181745 +v 0.14201 -0.23683 -0.154944 +v 0.14189 -0.252873 -0.126437 +v 0.14201 -0.266053 -0.0964977 +v 0.142366 -0.276243 -0.0654155 +v 0.142957 -0.283344 -0.0334892 +v 0.143776 -0.287288 -0.00102647 +v 0.144816 -0.288038 0.0316602 +v 0.146066 -0.285586 0.064256 +v 0.147514 -0.279955 0.0964469 +v 0.149147 -0.2712 0.127923 +v 0.150949 -0.259405 0.158381 +v 0.152902 -0.244685 0.187528 +v 0.154987 -0.227179 0.215083 +v 0.157185 -0.207058 0.240781 +v 0.159474 -0.184515 0.264373 +v 0.161833 -0.159766 0.285634 +v 0.164238 -0.133051 0.304358 +v 0.166667 -0.104627 0.320365 +v 0.169095 -0.0747667 0.3335 +v 0.1715 -0.0437586 0.343638 +v 0.173859 -0.011901 0.35068 +v 0.176148 0.0204992 0.354559 +v 0.178346 0.05313 0.355238 +v 0.180432 0.0856771 0.352709 +v 0.182385 0.117827 0.346998 +v 0.184186 0.149271 0.338158 +v 0.185819 0.179704 0.326277 +v 0.187268 0.208836 0.311467 +v 0.188518 0.236384 0.293871 +v 0.189557 0.262083 0.273659 +v 0.190376 0.285687 0.251026 +v 0.190967 0.306967 0.226189 +v 0.191324 0.325719 0.199388 +v 0.315446 0.30578 0.15289 +v 0.315265 0.317868 0.125449 +v 0.314722 0.327228 0.0969669 +v 0.313824 0.333769 0.0677171 +v 0.312579 0.337429 0.0379815 +v 0.310998 0.338172 0.00804659 +v 0.309098 0.335991 -0.0217994 +v 0.306896 0.330907 -0.0512689 +v 0.304413 0.322969 -0.0800782 +v 0.301674 0.312254 -0.10795 +v 0.298705 0.298865 -0.134616 +v 0.295535 0.28293 -0.159818 +v 0.292193 0.264603 -0.183315 +v 0.288712 0.244061 -0.204881 +v 0.285127 0.221502 -0.224306 +v 0.28147 0.197142 -0.241406 +v 0.277778 0.171216 -0.256013 +v 0.274086 0.143975 -0.267989 +v 0.270429 0.11568 -0.277217 +v 0.266843 0.0866036 -0.28361 +v 0.263363 0.0570262 -0.287104 +v 0.260021 0.0272325 -0.287667 +v 0.25685 -0.00249054 -0.285293 +v 0.253881 -0.0318567 -0.280005 +v 0.251142 -0.0605832 -0.271854 +v 0.24866 -0.0883933 -0.260919 +v 0.246458 -0.115019 -0.247304 +v 0.244557 -0.140204 -0.231142 +v 0.242977 -0.163707 -0.212586 +v 0.241731 -0.185299 -0.191817 +v 0.240833 -0.204775 -0.169034 +v 0.240291 -0.221945 -0.144457 +v 0.240109 -0.236645 -0.118322 +v 0.240291 -0.248733 -0.0908815 +v 0.240833 -0.258092 -0.062399 +v 0.241731 -0.264633 -0.0331492 +v 0.242977 -0.268293 -0.00341359 +v 0.244557 -0.269036 0.0265213 +v 0.246458 -0.266855 0.0563673 +v 0.24866 -0.261771 0.0858368 +v 0.251142 -0.253833 0.114646 +v 0.253881 -0.243118 0.142518 +v 0.25685 -0.229729 0.169183 +v 0.260021 -0.213794 0.194386 +v 0.263363 -0.195467 0.217883 +v 0.266843 -0.174925 0.239449 +v 0.270429 -0.152366 0.258874 +v 0.274086 -0.128006 0.275973 +v 0.277778 -0.102081 0.290581 +v 0.28147 -0.0748392 0.302557 +v 0.285127 -0.0465441 0.311785 +v 0.288712 -0.0174678 0.318177 +v 0.292193 0.0121096 0.321672 +v 0.295535 0.0419033 0.322235 +v 0.298705 0.0716263 0.319861 +v 0.301674 0.100993 0.314573 +v 0.304413 0.129719 0.306422 +v 0.306896 0.157529 0.295487 +v 0.309098 0.184155 0.281872 +v 0.310998 0.20934 0.265709 +v 0.312579 0.232842 0.247154 +v 0.313824 0.254435 0.226385 +v 0.314722 0.27391 0.203602 +v 0.315265 0.291081 0.179025 +v 0.436485 0.264531 0.132265 +v 0.436255 0.275528 0.107323 +v 0.43557 0.284063 0.0814431 +v 0.434435 0.290052 0.0548736 +v 0.432862 0.293437 0.0278706 +v 0.430865 0.294187 0.000694407 +v 0.428463 0.292295 -0.0263934 +v 0.425681 0.287777 -0.0531319 +v 0.422544 0.280678 -0.0792636 +v 0.419083 0.271066 -0.104537 +v 0.415332 0.259034 -0.128708 +v 0.411325 0.244698 -0.151545 +v 0.407103 0.228195 -0.172827 +v 0.402705 0.209685 -0.19235 +v 0.398174 0.189346 -0.209925 +v 0.393554 0.167373 -0.225383 +v 0.388889 0.143979 -0.238575 +v 0.384224 0.119388 -0.249375 +v 0.379603 0.0938384 -0.257678 +v 0.375073 0.0675747 -0.263405 +v 0.370675 0.0408506 -0.266499 +v 0.366452 0.0139232 -0.266932 +v 0.362446 -0.012948 -0.264699 +v 0.358695 -0.0395042 -0.259822 +v 0.355234 -0.0654898 -0.252348 +v 0.352097 -0.0906545 -0.242348 +v 0.349315 -0.114756 -0.229919 +v 0.346913 -0.137562 -0.21518 +v 0.344916 -0.158853 -0.198274 +v 0.343343 -0.178424 -0.179364 +v 0.342208 -0.196086 -0.158631 +v 0.341522 -0.21167 -0.136276 +v 0.341293 -0.225025 -0.112512 +v 0.341522 -0.236022 -0.0875704 +v 0.342208 -0.244557 -0.0616901 +v 0.343343 -0.250545 -0.0351205 +v 0.344916 -0.253931 -0.00811754 +v 0.346913 -0.254681 0.0190587 +v 0.349315 -0.252788 0.0461465 +v 0.352097 -0.248271 0.072885 +v 0.355234 -0.241172 0.0990167 +v 0.358695 -0.23156 0.12429 +v 0.362446 -0.219528 0.148461 +v 0.366452 -0.205192 0.171298 +v 0.370675 -0.188689 0.19258 +v 0.375073 -0.170179 0.212103 +v 0.379603 -0.14984 0.229678 +v 0.384224 -0.127867 0.245136 +v 0.388889 -0.104473 0.258329 +v 0.393554 -0.0798823 0.269128 +v 0.398174 -0.0543322 0.277431 +v 0.402705 -0.0280686 0.283158 +v 0.407103 -0.0013444 0.286252 +v 0.411325 0.0255829 0.286685 +v 0.415332 0.0524541 0.284452 +v 0.419083 0.0790104 0.279575 +v 0.422544 0.104996 0.272101 +v 0.425681 0.130161 0.262101 +v 0.428463 0.154262 0.249672 +v 0.430865 0.177068 0.234933 +v 0.432862 0.198359 0.218028 +v 0.434435 0.21793 0.199117 +v 0.43557 0.235592 0.178384 +v 0.436255 0.251176 0.156029 +v 0.554554 0.218218 0.109109 +v 0.554292 0.228126 0.0866663 +v 0.553506 0.235837 0.0633889 +v 0.552205 0.241276 0.0395011 +v 0.550402 0.244392 0.0152329 +v 0.548113 0.245155 -0.00918202 +v 0.54536 0.243556 -0.0335085 +v 0.542171 0.239612 -0.0575123 +v 0.538576 0.23336 -0.0809622 +v 0.534609 0.224861 -0.103632 +v 0.530309 0.214196 -0.125305 +v 0.525717 0.201469 -0.14577 +v 0.520877 0.186801 -0.164832 +v 0.515836 0.170334 -0.182306 +v 0.510643 0.152227 -0.198024 +v 0.505347 0.132654 -0.211836 +v 0.5 0.111803 -0.223607 +v 0.494653 0.0898759 -0.233225 +v 0.489357 0.0670829 -0.240596 +v 0.484164 0.0436439 -0.245651 +v 0.479123 0.0197845 -0.24834 +v 0.474283 -0.00426541 -0.248637 +v 0.469691 -0.0282742 -0.24654 +v 0.465391 -0.0520108 -0.242068 +v 0.461424 -0.0752464 -0.235266 +v 0.457829 -0.0977574 -0.226197 +v 0.45464 -0.119327 -0.21495 +v 0.451887 -0.139747 -0.201633 +v 0.449598 -0.158822 -0.186374 +v 0.447795 -0.176367 -0.16932 +v 0.446494 -0.192213 -0.150636 +v 0.445708 -0.206208 -0.130501 +v 0.445446 -0.218218 -0.109109 +v 0.445708 -0.228126 -0.0866663 +v 0.446494 -0.235837 -0.0633889 +v 0.447795 -0.241276 -0.0395011 +v 0.449598 -0.244392 -0.0152329 +v 0.451887 -0.245155 0.00918202 +v 0.45464 -0.243556 0.0335085 +v 0.457829 -0.239612 0.0575123 +v 0.461424 -0.23336 0.0809622 +v 0.465391 -0.224861 0.103632 +v 0.469691 -0.214196 0.125305 +v 0.474283 -0.201469 0.14577 +v 0.479123 -0.186801 0.164832 +v 0.484164 -0.170334 0.182306 +v 0.489357 -0.152227 0.198024 +v 0.494653 -0.132654 0.211836 +v 0.5 -0.111803 0.223607 +v 0.505347 -0.0898759 0.233225 +v 0.510643 -0.0670829 0.240596 +v 0.515836 -0.0436439 0.245651 +v 0.520877 -0.0197845 0.24834 +v 0.525717 0.00426541 0.248637 +v 0.530309 0.0282742 0.24654 +v 0.534609 0.0520108 0.242068 +v 0.538576 0.0752464 0.235266 +v 0.542171 0.0977574 0.226197 +v 0.54536 0.119327 0.21495 +v 0.548113 0.139747 0.201633 +v 0.550402 0.158822 0.186374 +v 0.552205 0.176367 0.16932 +v 0.553506 0.192213 0.150636 +v 0.554292 0.206208 0.130501 +f 1 66 2 +f 1 65 66 +f 2 67 3 +f 2 66 67 +f 3 68 4 +f 3 67 68 +f 4 69 5 +f 4 68 69 +f 5 70 6 +f 5 69 70 +f 6 71 7 +f 6 70 71 +f 7 72 8 +f 7 71 72 +f 8 73 9 +f 8 72 73 +f 9 74 10 +f 9 73 74 +f 10 75 11 +f 10 74 75 +f 11 76 12 +f 11 75 76 +f 12 77 13 +f 12 76 77 +f 13 78 14 +f 13 77 78 +f 14 79 15 +f 14 78 79 +f 15 80 16 +f 15 79 80 +f 16 81 17 +f 16 80 81 +f 17 82 18 +f 17 81 82 +f 18 83 19 +f 18 82 83 +f 19 84 20 +f 19 83 84 +f 20 85 21 +f 20 84 85 +f 21 86 22 +f 21 85 86 +f 22 87 23 +f 22 86 87 +f 23 88 24 +f 23 87 88 +f 24 89 25 +f 24 88 89 +f 25 90 26 +f 25 89 90 +f 26 91 27 +f 26 90 91 +f 27 92 28 +f 27 91 92 +f 28 93 29 +f 28 92 93 +f 29 94 30 +f 29 93 94 +f 30 95 31 +f 30 94 95 +f 31 96 32 +f 31 95 96 +f 32 97 33 +f 32 96 97 +f 33 98 34 +f 33 97 98 +f 34 99 35 +f 34 98 99 +f 35 100 36 +f 35 99 100 +f 36 101 37 +f 36 100 101 +f 37 102 38 +f 37 101 102 +f 38 103 39 +f 38 102 103 +f 39 104 40 +f 39 103 104 +f 40 105 41 +f 40 104 105 +f 41 106 42 +f 41 105 106 +f 42 107 43 +f 42 106 107 +f 43 108 44 +f 43 107 108 +f 44 109 45 +f 44 108 109 +f 45 110 46 +f 45 109 110 +f 46 111 47 +f 46 110 111 +f 47 112 48 +f 47 111 112 +f 48 113 49 +f 48 112 113 +f 49 114 50 +f 49 113 114 +f 50 115 51 +f 50 114 115 +f 51 116 52 +f 51 115 116 +f 52 117 53 +f 52 116 117 +f 53 118 54 +f 53 117 118 +f 54 119 55 +f 54 118 119 +f 55 120 56 +f 55 119 120 +f 56 121 57 +f 56 120 121 +f 57 122 58 +f 57 121 122 +f 58 123 59 +f 58 122 123 +f 59 124 60 +f 59 123 124 +f 60 125 61 +f 60 124 125 +f 61 126 62 +f 61 125 126 +f 62 127 63 +f 62 126 127 +f 63 128 64 +f 63 127 128 +f 64 65 1 +f 64 128 65 +f 65 130 66 +f 65 129 130 +f 66 131 67 +f 66 130 131 +f 67 132 68 +f 67 131 132 +f 68 133 69 +f 68 132 133 +f 69 134 70 +f 69 133 134 +f 70 135 71 +f 70 134 135 +f 71 136 72 +f 71 135 136 +f 72 137 73 +f 72 136 137 +f 73 138 74 +f 73 137 138 +f 74 139 75 +f 74 138 139 +f 75 140 76 +f 75 139 140 +f 76 141 77 +f 76 140 141 +f 77 142 78 +f 77 141 142 +f 78 143 79 +f 78 142 143 +f 79 144 80 +f 79 143 144 +f 80 145 81 +f 80 144 145 +f 81 146 82 +f 81 145 146 +f 82 147 83 +f 82 146 147 +f 83 148 84 +f 83 147 148 +f 84 149 85 +f 84 148 149 +f 85 150 86 +f 85 149 150 +f 86 151 87 +f 86 150 151 +f 87 152 88 +f 87 151 152 +f 88 153 89 +f 88 152 153 +f 89 154 90 +f 89 153 154 +f 90 155 91 +f 90 154 155 +f 91 156 92 +f 91 155 156 +f 92 157 93 +f 92 156 157 +f 93 158 94 +f 93 157 158 +f 94 159 95 +f 94 158 159 +f 95 160 96 +f 95 159 160 +f 96 161 97 +f 96 160 161 +f 97 162 98 +f 97 161 162 +f 98 163 99 +f 98 162 163 +f 99 164 100 +f 99 163 164 +f 100 165 101 +f 100 164 165 +f 101 166 102 +f 101 165 166 +f 102 167 103 +f 102 166 167 +f 103 168 104 +f 103 167 168 +f 104 169 105 +f 104 168 169 +f 105 170 106 +f 105 169 170 +f 106 171 107 +f 106 170 171 +f 107 172 108 +f 107 171 172 +f 108 173 109 +f 108 172 173 +f 109 174 110 +f 109 173 174 +f 110 175 111 +f 110 174 175 +f 111 176 112 +f 111 175 176 +f 112 177 113 +f 112 176 177 +f 113 178 114 +f 113 177 178 +f 114 179 115 +f 114 178 179 +f 115 180 116 +f 115 179 180 +f 116 181 117 +f 116 180 181 +f 117 182 118 +f 117 181 182 +f 118 183 119 +f 118 182 183 +f 119 184 120 +f 119 183 184 +f 120 185 121 +f 120 184 185 +f 121 186 122 +f 121 185 186 +f 122 187 123 +f 122 186 187 +f 123 188 124 +f 123 187 188 +f 124 189 125 +f 124 188 189 +f 125 190 126 +f 125 189 190 +f 126 191 127 +f 126 190 191 +f 127 192 128 +f 127 191 192 +f 128 129 65 +f 128 192 129 +f 129 194 130 +f 129 193 194 +f 130 195 131 +f 130 194 195 +f 131 196 132 +f 131 195 196 +f 132 197 133 +f 132 196 197 +f 133 198 134 +f 133 197 198 +f 134 199 135 +f 134 198 199 +f 135 200 136 +f 135 199 200 +f 136 201 137 +f 136 200 201 +f 137 202 138 +f 137 201 202 +f 138 203 139 +f 138 202 203 +f 139 204 140 +f 139 203 204 +f 140 205 141 +f 140 204 205 +f 141 206 142 +f 141 205 206 +f 142 207 143 +f 142 206 207 +f 143 208 144 +f 143 207 208 +f 144 209 145 +f 144 208 209 +f 145 210 146 +f 145 209 210 +f 146 211 147 +f 146 210 211 +f 147 212 148 +f 147 211 212 +f 148 213 149 +f 148 212 213 +f 149 214 150 +f 149 213 214 +f 150 215 151 +f 150 214 215 +f 151 216 152 +f 151 215 216 +f 152 217 153 +f 152 216 217 +f 153 218 154 +f 153 217 218 +f 154 219 155 +f 154 218 219 +f 155 220 156 +f 155 219 220 +f 156 221 157 +f 156 220 221 +f 157 222 158 +f 157 221 222 +f 158 223 159 +f 158 222 223 +f 159 224 160 +f 159 223 224 +f 160 225 161 +f 160 224 225 +f 161 226 162 +f 161 225 226 +f 162 227 163 +f 162 226 227 +f 163 228 164 +f 163 227 228 +f 164 229 165 +f 164 228 229 +f 165 230 166 +f 165 229 230 +f 166 231 167 +f 166 230 231 +f 167 232 168 +f 167 231 232 +f 168 233 169 +f 168 232 233 +f 169 234 170 +f 169 233 234 +f 170 235 171 +f 170 234 235 +f 171 236 172 +f 171 235 236 +f 172 237 173 +f 172 236 237 +f 173 238 174 +f 173 237 238 +f 174 239 175 +f 174 238 239 +f 175 240 176 +f 175 239 240 +f 176 241 177 +f 176 240 241 +f 177 242 178 +f 177 241 242 +f 178 243 179 +f 178 242 243 +f 179 244 180 +f 179 243 244 +f 180 245 181 +f 180 244 245 +f 181 246 182 +f 181 245 246 +f 182 247 183 +f 182 246 247 +f 183 248 184 +f 183 247 248 +f 184 249 185 +f 184 248 249 +f 185 250 186 +f 185 249 250 +f 186 251 187 +f 186 250 251 +f 187 252 188 +f 187 251 252 +f 188 253 189 +f 188 252 253 +f 189 254 190 +f 189 253 254 +f 190 255 191 +f 190 254 255 +f 191 256 192 +f 191 255 256 +f 192 193 129 +f 192 256 193 +f 193 258 194 +f 193 257 258 +f 194 259 195 +f 194 258 259 +f 195 260 196 +f 195 259 260 +f 196 261 197 +f 196 260 261 +f 197 262 198 +f 197 261 262 +f 198 263 199 +f 198 262 263 +f 199 264 200 +f 199 263 264 +f 200 265 201 +f 200 264 265 +f 201 266 202 +f 201 265 266 +f 202 267 203 +f 202 266 267 +f 203 268 204 +f 203 267 268 +f 204 269 205 +f 204 268 269 +f 205 270 206 +f 205 269 270 +f 206 271 207 +f 206 270 271 +f 207 272 208 +f 207 271 272 +f 208 273 209 +f 208 272 273 +f 209 274 210 +f 209 273 274 +f 210 275 211 +f 210 274 275 +f 211 276 212 +f 211 275 276 +f 212 277 213 +f 212 276 277 +f 213 278 214 +f 213 277 278 +f 214 279 215 +f 214 278 279 +f 215 280 216 +f 215 279 280 +f 216 281 217 +f 216 280 281 +f 217 282 218 +f 217 281 282 +f 218 283 219 +f 218 282 283 +f 219 284 220 +f 219 283 284 +f 220 285 221 +f 220 284 285 +f 221 286 222 +f 221 285 286 +f 222 287 223 +f 222 286 287 +f 223 288 224 +f 223 287 288 +f 224 289 225 +f 224 288 289 +f 225 290 226 +f 225 289 290 +f 226 291 227 +f 226 290 291 +f 227 292 228 +f 227 291 292 +f 228 293 229 +f 228 292 293 +f 229 294 230 +f 229 293 294 +f 230 295 231 +f 230 294 295 +f 231 296 232 +f 231 295 296 +f 232 297 233 +f 232 296 297 +f 233 298 234 +f 233 297 298 +f 234 299 235 +f 234 298 299 +f 235 300 236 +f 235 299 300 +f 236 301 237 +f 236 300 301 +f 237 302 238 +f 237 301 302 +f 238 303 239 +f 238 302 303 +f 239 304 240 +f 239 303 304 +f 240 305 241 +f 240 304 305 +f 241 306 242 +f 241 305 306 +f 242 307 243 +f 242 306 307 +f 243 308 244 +f 243 307 308 +f 244 309 245 +f 244 308 309 +f 245 310 246 +f 245 309 310 +f 246 311 247 +f 246 310 311 +f 247 312 248 +f 247 311 312 +f 248 313 249 +f 248 312 313 +f 249 314 250 +f 249 313 314 +f 250 315 251 +f 250 314 315 +f 251 316 252 +f 251 315 316 +f 252 317 253 +f 252 316 317 +f 253 318 254 +f 253 317 318 +f 254 319 255 +f 254 318 319 +f 255 320 256 +f 255 319 320 +f 256 257 193 +f 256 320 257 +f 257 322 258 +f 257 321 322 +f 258 323 259 +f 258 322 323 +f 259 324 260 +f 259 323 324 +f 260 325 261 +f 260 324 325 +f 261 326 262 +f 261 325 326 +f 262 327 263 +f 262 326 327 +f 263 328 264 +f 263 327 328 +f 264 329 265 +f 264 328 329 +f 265 330 266 +f 265 329 330 +f 266 331 267 +f 266 330 331 +f 267 332 268 +f 267 331 332 +f 268 333 269 +f 268 332 333 +f 269 334 270 +f 269 333 334 +f 270 335 271 +f 270 334 335 +f 271 336 272 +f 271 335 336 +f 272 337 273 +f 272 336 337 +f 273 338 274 +f 273 337 338 +f 274 339 275 +f 274 338 339 +f 275 340 276 +f 275 339 340 +f 276 341 277 +f 276 340 341 +f 277 342 278 +f 277 341 342 +f 278 343 279 +f 278 342 343 +f 279 344 280 +f 279 343 344 +f 280 345 281 +f 280 344 345 +f 281 346 282 +f 281 345 346 +f 282 347 283 +f 282 346 347 +f 283 348 284 +f 283 347 348 +f 284 349 285 +f 284 348 349 +f 285 350 286 +f 285 349 350 +f 286 351 287 +f 286 350 351 +f 287 352 288 +f 287 351 352 +f 288 353 289 +f 288 352 353 +f 289 354 290 +f 289 353 354 +f 290 355 291 +f 290 354 355 +f 291 356 292 +f 291 355 356 +f 292 357 293 +f 292 356 357 +f 293 358 294 +f 293 357 358 +f 294 359 295 +f 294 358 359 +f 295 360 296 +f 295 359 360 +f 296 361 297 +f 296 360 361 +f 297 362 298 +f 297 361 362 +f 298 363 299 +f 298 362 363 +f 299 364 300 +f 299 363 364 +f 300 365 301 +f 300 364 365 +f 301 366 302 +f 301 365 366 +f 302 367 303 +f 302 366 367 +f 303 368 304 +f 303 367 368 +f 304 369 305 +f 304 368 369 +f 305 370 306 +f 305 369 370 +f 306 371 307 +f 306 370 371 +f 307 372 308 +f 307 371 372 +f 308 373 309 +f 308 372 373 +f 309 374 310 +f 309 373 374 +f 310 375 311 +f 310 374 375 +f 311 376 312 +f 311 375 376 +f 312 377 313 +f 312 376 377 +f 313 378 314 +f 313 377 378 +f 314 379 315 +f 314 378 379 +f 315 380 316 +f 315 379 380 +f 316 381 317 +f 316 380 381 +f 317 382 318 +f 317 381 382 +f 318 383 319 +f 318 382 383 +f 319 384 320 +f 319 383 384 +f 320 321 257 +f 320 384 321 +f 321 386 322 +f 321 385 386 +f 322 387 323 +f 322 386 387 +f 323 388 324 +f 323 387 388 +f 324 389 325 +f 324 388 389 +f 325 390 326 +f 325 389 390 +f 326 391 327 +f 326 390 391 +f 327 392 328 +f 327 391 392 +f 328 393 329 +f 328 392 393 +f 329 394 330 +f 329 393 394 +f 330 395 331 +f 330 394 395 +f 331 396 332 +f 331 395 396 +f 332 397 333 +f 332 396 397 +f 333 398 334 +f 333 397 398 +f 334 399 335 +f 334 398 399 +f 335 400 336 +f 335 399 400 +f 336 401 337 +f 336 400 401 +f 337 402 338 +f 337 401 402 +f 338 403 339 +f 338 402 403 +f 339 404 340 +f 339 403 404 +f 340 405 341 +f 340 404 405 +f 341 406 342 +f 341 405 406 +f 342 407 343 +f 342 406 407 +f 343 408 344 +f 343 407 408 +f 344 409 345 +f 344 408 409 +f 345 410 346 +f 345 409 410 +f 346 411 347 +f 346 410 411 +f 347 412 348 +f 347 411 412 +f 348 413 349 +f 348 412 413 +f 349 414 350 +f 349 413 414 +f 350 415 351 +f 350 414 415 +f 351 416 352 +f 351 415 416 +f 352 417 353 +f 352 416 417 +f 353 418 354 +f 353 417 418 +f 354 419 355 +f 354 418 419 +f 355 420 356 +f 355 419 420 +f 356 421 357 +f 356 420 421 +f 357 422 358 +f 357 421 422 +f 358 423 359 +f 358 422 423 +f 359 424 360 +f 359 423 424 +f 360 425 361 +f 360 424 425 +f 361 426 362 +f 361 425 426 +f 362 427 363 +f 362 426 427 +f 363 428 364 +f 363 427 428 +f 364 429 365 +f 364 428 429 +f 365 430 366 +f 365 429 430 +f 366 431 367 +f 366 430 431 +f 367 432 368 +f 367 431 432 +f 368 433 369 +f 368 432 433 +f 369 434 370 +f 369 433 434 +f 370 435 371 +f 370 434 435 +f 371 436 372 +f 371 435 436 +f 372 437 373 +f 372 436 437 +f 373 438 374 +f 373 437 438 +f 374 439 375 +f 374 438 439 +f 375 440 376 +f 375 439 440 +f 376 441 377 +f 376 440 441 +f 377 442 378 +f 377 441 442 +f 378 443 379 +f 378 442 443 +f 379 444 380 +f 379 443 444 +f 380 445 381 +f 380 444 445 +f 381 446 382 +f 381 445 446 +f 382 447 383 +f 382 446 447 +f 383 448 384 +f 383 447 448 +f 384 385 321 +f 384 448 385 +f 385 450 386 +f 385 449 450 +f 386 451 387 +f 386 450 451 +f 387 452 388 +f 387 451 452 +f 388 453 389 +f 388 452 453 +f 389 454 390 +f 389 453 454 +f 390 455 391 +f 390 454 455 +f 391 456 392 +f 391 455 456 +f 392 457 393 +f 392 456 457 +f 393 458 394 +f 393 457 458 +f 394 459 395 +f 394 458 459 +f 395 460 396 +f 395 459 460 +f 396 461 397 +f 396 460 461 +f 397 462 398 +f 397 461 462 +f 398 463 399 +f 398 462 463 +f 399 464 400 +f 399 463 464 +f 400 465 401 +f 400 464 465 +f 401 466 402 +f 401 465 466 +f 402 467 403 +f 402 466 467 +f 403 468 404 +f 403 467 468 +f 404 469 405 +f 404 468 469 +f 405 470 406 +f 405 469 470 +f 406 471 407 +f 406 470 471 +f 407 472 408 +f 407 471 472 +f 408 473 409 +f 408 472 473 +f 409 474 410 +f 409 473 474 +f 410 475 411 +f 410 474 475 +f 411 476 412 +f 411 475 476 +f 412 477 413 +f 412 476 477 +f 413 478 414 +f 413 477 478 +f 414 479 415 +f 414 478 479 +f 415 480 416 +f 415 479 480 +f 416 481 417 +f 416 480 481 +f 417 482 418 +f 417 481 482 +f 418 483 419 +f 418 482 483 +f 419 484 420 +f 419 483 484 +f 420 485 421 +f 420 484 485 +f 421 486 422 +f 421 485 486 +f 422 487 423 +f 422 486 487 +f 423 488 424 +f 423 487 488 +f 424 489 425 +f 424 488 489 +f 425 490 426 +f 425 489 490 +f 426 491 427 +f 426 490 491 +f 427 492 428 +f 427 491 492 +f 428 493 429 +f 428 492 493 +f 429 494 430 +f 429 493 494 +f 430 495 431 +f 430 494 495 +f 431 496 432 +f 431 495 496 +f 432 497 433 +f 432 496 497 +f 433 498 434 +f 433 497 498 +f 434 499 435 +f 434 498 499 +f 435 500 436 +f 435 499 500 +f 436 501 437 +f 436 500 501 +f 437 502 438 +f 437 501 502 +f 438 503 439 +f 438 502 503 +f 439 504 440 +f 439 503 504 +f 440 505 441 +f 440 504 505 +f 441 506 442 +f 441 505 506 +f 442 507 443 +f 442 506 507 +f 443 508 444 +f 443 507 508 +f 444 509 445 +f 444 508 509 +f 445 510 446 +f 445 509 510 +f 446 511 447 +f 446 510 511 +f 447 512 448 +f 447 511 512 +f 448 449 385 +f 448 512 449 +f 449 514 450 +f 449 513 514 +f 450 515 451 +f 450 514 515 +f 451 516 452 +f 451 515 516 +f 452 517 453 +f 452 516 517 +f 453 518 454 +f 453 517 518 +f 454 519 455 +f 454 518 519 +f 455 520 456 +f 455 519 520 +f 456 521 457 +f 456 520 521 +f 457 522 458 +f 457 521 522 +f 458 523 459 +f 458 522 523 +f 459 524 460 +f 459 523 524 +f 460 525 461 +f 460 524 525 +f 461 526 462 +f 461 525 526 +f 462 527 463 +f 462 526 527 +f 463 528 464 +f 463 527 528 +f 464 529 465 +f 464 528 529 +f 465 530 466 +f 465 529 530 +f 466 531 467 +f 466 530 531 +f 467 532 468 +f 467 531 532 +f 468 533 469 +f 468 532 533 +f 469 534 470 +f 469 533 534 +f 470 535 471 +f 470 534 535 +f 471 536 472 +f 471 535 536 +f 472 537 473 +f 472 536 537 +f 473 538 474 +f 473 537 538 +f 474 539 475 +f 474 538 539 +f 475 540 476 +f 475 539 540 +f 476 541 477 +f 476 540 541 +f 477 542 478 +f 477 541 542 +f 478 543 479 +f 478 542 543 +f 479 544 480 +f 479 543 544 +f 480 545 481 +f 480 544 545 +f 481 546 482 +f 481 545 546 +f 482 547 483 +f 482 546 547 +f 483 548 484 +f 483 547 548 +f 484 549 485 +f 484 548 549 +f 485 550 486 +f 485 549 550 +f 486 551 487 +f 486 550 551 +f 487 552 488 +f 487 551 552 +f 488 553 489 +f 488 552 553 +f 489 554 490 +f 489 553 554 +f 490 555 491 +f 490 554 555 +f 491 556 492 +f 491 555 556 +f 492 557 493 +f 492 556 557 +f 493 558 494 +f 493 557 558 +f 494 559 495 +f 494 558 559 +f 495 560 496 +f 495 559 560 +f 496 561 497 +f 496 560 561 +f 497 562 498 +f 497 561 562 +f 498 563 499 +f 498 562 563 +f 499 564 500 +f 499 563 564 +f 500 565 501 +f 500 564 565 +f 501 566 502 +f 501 565 566 +f 502 567 503 +f 502 566 567 +f 503 568 504 +f 503 567 568 +f 504 569 505 +f 504 568 569 +f 505 570 506 +f 505 569 570 +f 506 571 507 +f 506 570 571 +f 507 572 508 +f 507 571 572 +f 508 573 509 +f 508 572 573 +f 509 574 510 +f 509 573 574 +f 510 575 511 +f 510 574 575 +f 511 576 512 +f 511 575 576 +f 512 513 449 +f 512 576 513 +f 513 578 514 +f 513 577 578 +f 514 579 515 +f 514 578 579 +f 515 580 516 +f 515 579 580 +f 516 581 517 +f 516 580 581 +f 517 582 518 +f 517 581 582 +f 518 583 519 +f 518 582 583 +f 519 584 520 +f 519 583 584 +f 520 585 521 +f 520 584 585 +f 521 586 522 +f 521 585 586 +f 522 587 523 +f 522 586 587 +f 523 588 524 +f 523 587 588 +f 524 589 525 +f 524 588 589 +f 525 590 526 +f 525 589 590 +f 526 591 527 +f 526 590 591 +f 527 592 528 +f 527 591 592 +f 528 593 529 +f 528 592 593 +f 529 594 530 +f 529 593 594 +f 530 595 531 +f 530 594 595 +f 531 596 532 +f 531 595 596 +f 532 597 533 +f 532 596 597 +f 533 598 534 +f 533 597 598 +f 534 599 535 +f 534 598 599 +f 535 600 536 +f 535 599 600 +f 536 601 537 +f 536 600 601 +f 537 602 538 +f 537 601 602 +f 538 603 539 +f 538 602 603 +f 539 604 540 +f 539 603 604 +f 540 605 541 +f 540 604 605 +f 541 606 542 +f 541 605 606 +f 542 607 543 +f 542 606 607 +f 543 608 544 +f 543 607 608 +f 544 609 545 +f 544 608 609 +f 545 610 546 +f 545 609 610 +f 546 611 547 +f 546 610 611 +f 547 612 548 +f 547 611 612 +f 548 613 549 +f 548 612 613 +f 549 614 550 +f 549 613 614 +f 550 615 551 +f 550 614 615 +f 551 616 552 +f 551 615 616 +f 552 617 553 +f 552 616 617 +f 553 618 554 +f 553 617 618 +f 554 619 555 +f 554 618 619 +f 555 620 556 +f 555 619 620 +f 556 621 557 +f 556 620 621 +f 557 622 558 +f 557 621 622 +f 558 623 559 +f 558 622 623 +f 559 624 560 +f 559 623 624 +f 560 625 561 +f 560 624 625 +f 561 626 562 +f 561 625 626 +f 562 627 563 +f 562 626 627 +f 563 628 564 +f 563 627 628 +f 564 629 565 +f 564 628 629 +f 565 630 566 +f 565 629 630 +f 566 631 567 +f 566 630 631 +f 567 632 568 +f 567 631 632 +f 568 633 569 +f 568 632 633 +f 569 634 570 +f 569 633 634 +f 570 635 571 +f 570 634 635 +f 571 636 572 +f 571 635 636 +f 572 637 573 +f 572 636 637 +f 573 638 574 +f 573 637 638 +f 574 639 575 +f 574 638 639 +f 575 640 576 +f 575 639 640 +f 576 577 513 +f 576 640 577 diff --git a/data/DebugImages/check_3d_bezier_more_vs.obj b/data/DebugImages/check_3d_bezier_more_vs.obj new file mode 100644 index 0000000..d571d78 --- /dev/null +++ b/data/DebugImages/check_3d_bezier_more_vs.obj @@ -0,0 +1,2817 @@ +# Branch +v -0.609109 0.436436 0.218218 +v -0.607012 0.471673 0.126778 +v -0.600804 0.488785 0.0304658 +v -0.590721 0.487112 -0.067017 +v -0.577152 0.466721 -0.161924 +v -0.560618 0.428393 -0.250609 +v -0.541754 0.373602 -0.329663 +v -0.521286 0.304455 -0.396048 +v -0.5 0.223607 -0.447214 +v -0.478714 0.134166 -0.481193 +v -0.458246 0.039569 -0.49668 +v -0.439382 -0.0565485 -0.49308 +v -0.422848 -0.150493 -0.470531 +v -0.409279 -0.238654 -0.4299 +v -0.399196 -0.317643 -0.372748 +v -0.392988 -0.384426 -0.301272 +v -0.390891 -0.436436 -0.218218 +v -0.392988 -0.471673 -0.126778 +v -0.399196 -0.488785 -0.0304658 +v -0.409279 -0.487112 0.067017 +v -0.422848 -0.466721 0.161924 +v -0.439382 -0.428393 0.250609 +v -0.458246 -0.373602 0.329663 +v -0.478714 -0.304455 0.396048 +v -0.5 -0.223607 0.447214 +v -0.521286 -0.134166 0.481193 +v -0.541754 -0.039569 0.49668 +v -0.560618 0.0565485 0.49308 +v -0.577152 0.150493 0.470531 +v -0.590721 0.238654 0.4299 +v -0.600804 0.317643 0.372748 +v -0.607012 0.384426 0.301272 +v -0.565668 0.436936 0.218468 +v -0.563744 0.47154 0.128592 +v -0.558045 0.488279 0.0339011 +v -0.54879 0.486509 -0.0619641 +v -0.536335 0.466299 -0.15532 +v -0.521158 0.428425 -0.242579 +v -0.503843 0.374343 -0.320388 +v -0.485056 0.306131 -0.385757 +v -0.465517 0.22641 -0.436174 +v -0.445979 0.138245 -0.4697 +v -0.427191 0.0450226 -0.485049 +v -0.409876 -0.0496739 -0.481629 +v -0.3947 -0.142206 -0.459572 +v -0.382245 -0.229017 -0.419727 +v -0.37299 -0.306771 -0.363623 +v -0.367291 -0.37248 -0.293418 +v -0.365366 -0.423619 -0.211809 +v -0.367291 -0.458223 -0.121933 +v -0.37299 -0.474961 -0.0272424 +v -0.382245 -0.473191 0.0686228 +v -0.3947 -0.452981 0.161979 +v -0.409876 -0.415107 0.249238 +v -0.427191 -0.361025 0.327047 +v -0.445979 -0.292813 0.392416 +v -0.465517 -0.213093 0.442832 +v -0.485056 -0.124927 0.476359 +v -0.503843 -0.0317051 0.491707 +v -0.521158 0.0629914 0.488287 +v -0.536335 0.155523 0.466231 +v -0.54879 0.242334 0.426386 +v -0.558045 0.320088 0.370282 +v -0.563744 0.385797 0.300077 +v -0.522411 0.436829 0.218414 +v -0.520655 0.470801 0.130103 +v -0.515455 0.487175 0.0370376 +v -0.507011 0.48532 -0.0572039 +v -0.495647 0.465308 -0.149 +v -0.481801 0.427908 -0.234824 +v -0.466003 0.374557 -0.311377 +v -0.448861 0.307305 -0.375717 +v -0.431034 0.228738 -0.425372 +v -0.413208 0.141874 -0.458433 +v -0.396066 0.0500512 -0.47363 +v -0.380268 -0.0432016 -0.470379 +v -0.366422 -0.134301 -0.448804 +v -0.355058 -0.219745 -0.409736 +v -0.346614 -0.296251 -0.354675 +v -0.341414 -0.360879 -0.285738 +v -0.339658 -0.411145 -0.205573 +v -0.341414 -0.445118 -0.117261 +v -0.346614 -0.461491 -0.0241957 +v -0.355058 -0.459636 0.0700458 +v -0.366422 -0.439624 0.161842 +v -0.380268 -0.402224 0.247666 +v -0.396066 -0.348873 0.324219 +v -0.413208 -0.281622 0.388559 +v -0.431034 -0.203054 0.438213 +v -0.448861 -0.11619 0.471274 +v -0.466003 -0.0243674 0.486472 +v -0.481801 0.0688853 0.48322 +v -0.495647 0.159984 0.461646 +v -0.507011 0.245429 0.422578 +v -0.515455 0.321935 0.367517 +v -0.520655 0.386563 0.29858 +v -0.479345 0.436116 0.218058 +v -0.477754 0.469459 0.131312 +v -0.473043 0.485475 0.0398761 +v -0.465392 0.483547 -0.0527357 +v -0.455095 0.463749 -0.142964 +v -0.442549 0.426842 -0.227343 +v -0.428235 0.374245 -0.302628 +v -0.412704 0.307979 -0.365927 +v -0.396552 0.23059 -0.414807 +v -0.3804 0.145053 -0.44739 +v -0.364868 0.0546539 -0.462424 +v -0.350554 -0.0371325 -0.45933 +v -0.338008 -0.126779 -0.438228 +v -0.327712 -0.210841 -0.399929 +v -0.320061 -0.286087 -0.345905 +v -0.315349 -0.349626 -0.278231 +v -0.313758 -0.399017 -0.199508 +v -0.315349 -0.432361 -0.112763 +v -0.320061 -0.448376 -0.0213267 +v -0.327712 -0.446448 0.0712851 +v -0.338008 -0.42665 0.161514 +v -0.350554 -0.389744 0.245892 +v -0.364868 -0.337147 0.321177 +v -0.3804 -0.27088 0.384476 +v -0.396552 -0.193492 0.433357 +v -0.412704 -0.107954 0.465939 +v -0.428235 -0.0175552 0.480973 +v -0.442549 0.0742312 0.47788 +v -0.455095 0.163878 0.456778 +v -0.465392 0.247939 0.418479 +v -0.473043 0.323186 0.364454 +v -0.477754 0.386725 0.29678 +v -0.436477 0.434799 0.2174 +v -0.435048 0.467517 0.132221 +v -0.430813 0.483181 0.0424177 +v -0.423937 0.481192 -0.0485584 +v -0.414684 0.461624 -0.137212 +v -0.403408 0.425231 -0.220135 +v -0.390544 0.373409 -0.294141 +v -0.376585 0.308152 -0.356387 +v -0.362069 0.231967 -0.404481 +v -0.347553 0.147781 -0.436573 +v -0.333594 0.0588299 -0.451431 +v -0.32073 -0.0314681 -0.448484 +v -0.309454 -0.119643 -0.427845 +v -0.300201 -0.202306 -0.390307 +v -0.293325 -0.276281 -0.337313 +v -0.28909 -0.338724 -0.2709 +v -0.287661 -0.387237 -0.193618 +v -0.28909 -0.419954 -0.10844 +v -0.293325 -0.435619 -0.0186365 +v -0.300201 -0.433629 0.0723396 +v -0.309454 -0.414062 0.160993 +v -0.32073 -0.377668 0.243916 +v -0.333594 -0.325847 0.317923 +v -0.347553 -0.26059 0.380169 +v -0.362069 -0.184404 0.428262 +v -0.376585 -0.100219 0.460354 +v -0.390544 -0.0112675 0.475212 +v -0.403408 0.0790305 0.472265 +v -0.414684 0.167205 0.451626 +v -0.423937 0.249868 0.414089 +v -0.430813 0.323843 0.361095 +v -0.435048 0.386287 0.294681 +v -0.393815 0.432882 0.216441 +v -0.392542 0.464976 0.132831 +v -0.388774 0.480297 0.0446639 +v -0.382653 0.478258 -0.0446709 +v -0.374417 0.458936 -0.131741 +v -0.364381 0.423074 -0.213199 +v -0.352931 0.37205 -0.285917 +v -0.340507 0.307825 -0.347098 +v -0.327586 0.232868 -0.394392 +v -0.314666 0.150058 -0.425982 +v -0.302242 0.0625781 -0.440653 +v -0.290791 -0.0262099 -0.437841 +v -0.280755 -0.112894 -0.417655 +v -0.272519 -0.194143 -0.380871 +v -0.266399 -0.266834 -0.328902 +v -0.26263 -0.328175 -0.263745 +v -0.261357 -0.375807 -0.187904 +v -0.26263 -0.407901 -0.104293 +v -0.266399 -0.423222 -0.0161264 +v -0.272519 -0.421183 0.0732083 +v -0.280755 -0.401861 0.160278 +v -0.290791 -0.365999 0.241737 +v -0.302242 -0.314975 0.314454 +v -0.314666 -0.25075 0.375635 +v -0.327586 -0.175793 0.422929 +v -0.340507 -0.092983 0.454519 +v -0.352931 -0.00550319 0.46919 +v -0.364381 0.0832848 0.466379 +v -0.374417 0.169969 0.446193 +v -0.382653 0.251218 0.409409 +v -0.388774 0.323909 0.357439 +v -0.392542 0.38525 0.292282 +v -0.351365 0.430367 0.215184 +v -0.350246 0.461839 0.133143 +v -0.34693 0.476824 0.0466159 +v -0.341546 0.474746 -0.0410718 +v -0.334301 0.455685 -0.126551 +v -0.325472 0.420374 -0.206536 +v -0.315399 0.370168 -0.277953 +v -0.30447 0.306999 -0.338058 +v -0.293103 0.233293 -0.384541 +v -0.281737 0.151883 -0.415616 +v -0.270808 0.0658973 -0.430088 +v -0.260735 -0.0213596 -0.427402 +v -0.251906 -0.106534 -0.40766 +v -0.244661 -0.186354 -0.371622 +v -0.239277 -0.257751 -0.320672 +v -0.235961 -0.317982 -0.256768 +v -0.234842 -0.364731 -0.182366 +v -0.235961 -0.396203 -0.100325 +v -0.239277 -0.411188 -0.0137978 +v -0.244661 -0.40911 0.0738899 +v -0.251906 -0.390049 0.159369 +v -0.260735 -0.354737 0.239354 +v -0.270808 -0.304532 0.310771 +v -0.281737 -0.241363 0.370876 +v -0.293103 -0.167657 0.417359 +v -0.30447 -0.0862469 0.448434 +v -0.315399 -0.000261187 0.462906 +v -0.325472 0.0869957 0.46022 +v -0.334301 0.172171 0.440479 +v -0.341546 0.25199 0.40444 +v -0.34693 0.323387 0.35349 +v -0.350246 0.383618 0.289586 +v -0.309134 0.427259 0.213629 +v -0.308163 0.458111 0.133159 +v -0.305289 0.472766 0.0482753 +v -0.300621 0.470661 -0.0377599 +v -0.294339 0.451875 -0.12164 +v -0.286684 0.417132 -0.200142 +v -0.277951 0.367766 -0.27025 +v -0.268475 0.305674 -0.329267 +v -0.258621 0.233243 -0.374928 +v -0.248766 0.153256 -0.405477 +v -0.23929 0.0687863 -0.419739 +v -0.230557 -0.016919 -0.417168 +v -0.222902 -0.100567 -0.397861 +v -0.21662 -0.178942 -0.362561 +v -0.211953 -0.249034 -0.312625 +v -0.209078 -0.308148 -0.24997 +v -0.208107 -0.354012 -0.177006 +v -0.209078 -0.384865 -0.096536 +v -0.211953 -0.39952 -0.0116523 +v -0.21662 -0.397415 0.074383 +v -0.222902 -0.378629 0.158263 +v -0.230557 -0.343886 0.236766 +v -0.23929 -0.29452 0.306873 +v -0.248766 -0.232428 0.36589 +v -0.258621 -0.159997 0.411551 +v -0.268475 -0.0800095 0.4421 +v -0.277951 0.00445981 0.456362 +v -0.286684 0.0901651 0.453791 +v -0.294339 0.173813 0.434484 +v -0.300621 0.252188 0.399184 +v -0.305289 0.32228 0.349248 +v -0.308163 0.381394 0.286594 +v -0.267128 0.423559 0.21178 +v -0.266302 0.453795 0.132881 +v -0.263856 0.468127 0.0496438 +v -0.259883 0.466004 -0.0347336 +v -0.254537 0.447508 -0.117009 +v -0.248022 0.413351 -0.194019 +v -0.24059 0.364843 -0.262806 +v -0.232525 0.303851 -0.320726 +v -0.224138 0.232717 -0.365553 +v -0.215751 0.154175 -0.395564 +v -0.207686 0.0712437 -0.409606 +v -0.200254 -0.0128902 -0.40714 +v -0.193739 -0.0949933 -0.388259 +v -0.188393 -0.171911 -0.353691 +v -0.18442 -0.240686 -0.304762 +v -0.181974 -0.298677 -0.243355 +v -0.181148 -0.343654 -0.171827 +v -0.181974 -0.37389 -0.0929287 +v -0.18442 -0.388222 -0.00969139 +v -0.188393 -0.386099 0.074686 +v -0.193739 -0.367603 0.156961 +v -0.200254 -0.333446 0.233972 +v -0.207686 -0.284939 0.302759 +v -0.215751 -0.223946 0.360678 +v -0.224138 -0.152812 0.405505 +v -0.232525 -0.0742702 0.435516 +v -0.24059 0.00866118 0.449558 +v -0.248022 0.0927951 0.447092 +v -0.254537 0.174898 0.428212 +v -0.259883 0.251815 0.393643 +v -0.263856 0.320591 0.344715 +v -0.266302 0.378582 0.283307 +v -0.225355 0.419273 0.209636 +v -0.224669 0.448894 0.132311 +v -0.222637 0.462908 0.0507232 +v -0.219338 0.460779 -0.0319912 +v -0.214898 0.442587 -0.112654 +v -0.209489 0.409032 -0.188165 +v -0.203317 0.361403 -0.255622 +v -0.19662 0.301531 -0.312433 +v -0.189655 0.231715 -0.356415 +v -0.182691 0.154641 -0.385878 +v -0.175994 0.073268 -0.399689 +v -0.169822 -0.00927525 -0.397318 +v -0.164412 -0.089817 -0.378856 +v -0.159972 -0.165262 -0.345012 +v -0.156673 -0.232711 -0.297087 +v -0.154642 -0.289572 -0.236922 +v -0.153956 -0.333661 -0.16683 +v -0.154642 -0.363281 -0.0895047 +v -0.156673 -0.377296 -0.00791701 +v -0.159972 -0.375167 0.0747974 +v -0.164412 -0.356975 0.15546 +v -0.169822 -0.32342 0.230971 +v -0.175994 -0.275791 0.298428 +v -0.182691 -0.215918 0.355239 +v -0.189655 -0.146103 0.399221 +v -0.19662 -0.0690282 0.428684 +v -0.203317 0.0123444 0.442496 +v -0.209489 0.0948876 0.440124 +v -0.214898 0.175429 0.421662 +v -0.219338 0.250874 0.387818 +v -0.222637 0.318324 0.339893 +v -0.224669 0.375185 0.279728 +v -0.183819 0.414404 0.207202 +v -0.183268 0.443412 0.13145 +v -0.181638 0.457116 0.0515154 +v -0.178991 0.45499 -0.0295312 +v -0.175428 0.437115 -0.108575 +v -0.171087 0.404179 -0.182577 +v -0.166135 0.357446 -0.248696 +v -0.160761 0.298714 -0.304389 +v -0.155172 0.230238 -0.347516 +v -0.149584 0.154651 -0.37642 +v -0.14421 0.0748575 -0.38999 +v -0.139257 -0.00607656 -0.387705 +v -0.134916 -0.0850407 -0.369653 +v -0.131354 -0.159 -0.336526 +v -0.128707 -0.225113 -0.289599 +v -0.127076 -0.280839 -0.230675 +v -0.126526 -0.324036 -0.162018 +v -0.127076 -0.353043 -0.0862661 +v -0.128707 -0.366747 -0.00633105 +v -0.131354 -0.364621 0.0747155 +v -0.134916 -0.346746 0.153759 +v -0.139257 -0.31381 0.227762 +v -0.14421 -0.267078 0.29388 +v -0.149584 -0.208345 0.349573 +v -0.155172 -0.13987 0.3927 +v -0.160761 -0.0642826 0.421604 +v -0.166135 0.0155111 0.435174 +v -0.171087 0.0964452 0.432889 +v -0.175428 0.175409 0.414837 +v -0.178991 0.249369 0.381711 +v -0.181638 0.315482 0.334784 +v -0.183268 0.371207 0.275859 +v -0.142527 0.408957 0.204479 +v -0.142107 0.437354 0.130302 +v -0.140864 0.450753 0.0520224 +v -0.138846 0.44864 -0.0273515 +v -0.136131 0.431095 -0.10477 +v -0.132822 0.398792 -0.177257 +v -0.129046 0.352974 -0.242027 +v -0.12495 0.295401 -0.296592 +v -0.12069 0.228285 -0.338854 +v -0.116429 0.154206 -0.367189 +v -0.112333 0.0760106 -0.380509 +v -0.108558 -0.00329654 -0.378301 +v -0.105249 -0.0806675 -0.360651 +v -0.102533 -0.153129 -0.328236 +v -0.100515 -0.217896 -0.282302 +v -0.0992722 -0.27248 -0.224615 +v -0.0988526 -0.314784 -0.157392 +v -0.0992722 -0.343181 -0.083215 +v -0.100515 -0.35658 -0.00493556 +v -0.102533 -0.354466 0.0744383 +v -0.105249 -0.336921 0.151856 +v -0.108558 -0.304619 0.224343 +v -0.112333 -0.258801 0.289114 +v -0.116429 -0.201228 0.343679 +v -0.12069 -0.134112 0.385941 +v -0.12495 -0.0600327 0.414276 +v -0.129046 0.018163 0.427596 +v -0.132822 0.0974701 0.425388 +v -0.136131 0.174841 0.407737 +v -0.138846 0.247303 0.375323 +v -0.140864 0.31207 0.329389 +v -0.142107 0.366654 0.271702 +v -0.101484 0.402937 0.201469 +v -0.10119 0.430725 0.128868 +v -0.100321 0.443825 0.0522464 +v -0.0989091 0.441733 -0.0254504 +v -0.0970093 0.424529 -0.101237 +v -0.0946943 0.392876 -0.172201 +v -0.0920531 0.347989 -0.235615 +v -0.0891873 0.291594 -0.289042 +v -0.0862069 0.225857 -0.33043 +v -0.0832265 0.153305 -0.358187 +v -0.0803607 0.0767256 -0.371247 +v -0.0777195 -0.000937804 -0.369108 +v -0.0754045 -0.0767008 -0.351852 +v -0.0735046 -0.147652 -0.320143 +v -0.0720929 -0.211064 -0.275198 +v -0.0712236 -0.264502 -0.218746 +v -0.07093 -0.30591 -0.152955 +v -0.0712236 -0.333697 -0.0803538 +v -0.0720929 -0.346797 -0.0037327 +v -0.0735046 -0.344705 0.0739641 +v -0.0754045 -0.327502 0.149751 +v -0.0777195 -0.295849 0.220714 +v -0.0803607 -0.250962 0.284129 +v -0.0832265 -0.194567 0.337556 +v -0.0862069 -0.12883 0.378943 +v -0.0891873 -0.0562775 0.406701 +v -0.0920531 0.0203018 0.419761 +v -0.0946943 0.0979652 0.417622 +v -0.0970093 0.173728 0.400366 +v -0.0989091 0.244679 0.368656 +v -0.100321 0.308092 0.323712 +v -0.10119 0.361529 0.267259 +v -0.0606953 0.396348 0.198174 +v -0.0605229 0.423529 0.12715 +v -0.0600124 0.436334 0.0521896 +v -0.0591834 0.434273 -0.0238257 +v -0.0580677 0.417423 -0.0979749 +v -0.0567082 0.386433 -0.167409 +v -0.0551572 0.342493 -0.229458 +v -0.0534743 0.287293 -0.28174 +v -0.0517241 0.222953 -0.322244 +v -0.049974 0.151946 -0.349413 +v -0.048291 0.0770005 -0.362205 +v -0.0467401 0.000996929 -0.360127 +v -0.0453806 -0.073144 -0.343258 +v -0.0442649 -0.142573 -0.312249 +v -0.0434359 -0.204622 -0.268289 +v -0.0429254 -0.256907 -0.213068 +v -0.042753 -0.297418 -0.148709 +v -0.0429254 -0.324599 -0.0776849 +v -0.0434359 -0.337404 -0.00272473 +v -0.0442649 -0.335343 0.0732906 +v -0.0453806 -0.318493 0.14744 +v -0.0467401 -0.287503 0.216874 +v -0.048291 -0.243564 0.278923 +v -0.049974 -0.188363 0.331205 +v -0.0517241 -0.124023 0.371709 +v -0.0534743 -0.053016 0.398878 +v -0.0551572 0.0219294 0.41167 +v -0.0567082 0.0979329 0.409592 +v -0.0580677 0.172074 0.392723 +v -0.0591834 0.241503 0.361713 +v -0.0600124 0.303552 0.317754 +v -0.0605229 0.355837 0.262533 +v -0.020166 0.389196 0.194598 +v -0.0201098 0.415771 0.125151 +v -0.0199434 0.428287 0.0518546 +v -0.0196731 0.426264 -0.0224753 +v -0.0193094 0.409779 -0.0949818 +v -0.0188662 0.379465 -0.162879 +v -0.0183606 0.336488 -0.223556 +v -0.0178119 0.282499 -0.274684 +v -0.0172414 0.219573 -0.314295 +v -0.0166708 0.150128 -0.340869 +v -0.0161222 0.0768333 -0.353384 +v -0.0156165 0.00250482 -0.351359 +v -0.0151734 -0.0700008 -0.334872 +v -0.0148097 -0.137897 -0.304556 +v -0.0145394 -0.198575 -0.261577 +v -0.014373 -0.249702 -0.207585 +v -0.0143168 -0.289315 -0.144657 +v -0.014373 -0.31589 -0.0752107 +v -0.0145394 -0.328406 -0.00191401 +v -0.0148097 -0.326383 0.0724158 +v -0.0151734 -0.309898 0.144922 +v -0.0156165 -0.279584 0.212819 +v -0.0161222 -0.236607 0.273497 +v -0.0166708 -0.182618 0.324624 +v -0.0172414 -0.119692 0.364236 +v -0.0178119 -0.0502473 0.39081 +v -0.0183606 0.0230477 0.403324 +v -0.0188662 0.0973763 0.401299 +v -0.0193094 0.169882 0.384812 +v -0.0196731 0.237778 0.354496 +v -0.0199434 0.298456 0.311517 +v -0.0201098 0.349584 0.257526 +v 0.0200995 0.381486 0.190743 +v 0.0200446 0.407457 0.122874 +v 0.019882 0.419689 0.0512435 +v 0.0196178 0.417711 -0.0213969 +v 0.0192624 0.401601 -0.0922556 +v 0.0188293 0.371976 -0.158609 +v 0.0183351 0.329976 -0.217908 +v 0.017799 0.277214 -0.267873 +v 0.0172414 0.215718 -0.306585 +v 0.0166838 0.147851 -0.332555 +v 0.0161476 0.0762221 -0.344785 +v 0.0156535 0.0035829 -0.342806 +v 0.0152204 -0.0672748 -0.326693 +v 0.0148649 -0.133628 -0.297067 +v 0.0146008 -0.192927 -0.255064 +v 0.0144382 -0.242892 -0.2023 +v 0.0143832 -0.281605 -0.140802 +v 0.0144382 -0.307576 -0.0729338 +v 0.0146008 -0.319807 -0.001303 +v 0.0148649 -0.31783 0.0713375 +v 0.0152204 -0.30172 0.142196 +v 0.0156535 -0.272095 0.20855 +v 0.0161476 -0.230095 0.267849 +v 0.0166838 -0.177333 0.317814 +v 0.0172414 -0.115837 0.356525 +v 0.017799 -0.0479703 0.382495 +v 0.0183351 0.0236589 0.394725 +v 0.0188293 0.0962982 0.392746 +v 0.0192624 0.167156 0.376634 +v 0.0196178 0.233509 0.347007 +v 0.019882 0.292808 0.305005 +v 0.0200446 0.342773 0.252241 +v 0.0600972 0.373223 0.186611 +v 0.0599363 0.398591 0.120322 +v 0.0594598 0.410543 0.0503592 +v 0.0586861 0.408619 -0.0205885 +v 0.0576448 0.392892 -0.0897944 +v 0.056376 0.363968 -0.154599 +v 0.0549284 0.322958 -0.212512 +v 0.0533576 0.271438 -0.261308 +v 0.0517241 0.211387 -0.299112 +v 0.0500906 0.145114 -0.32447 +v 0.0485199 0.0751648 -0.336409 +v 0.0470723 0.00422813 -0.334469 +v 0.0458035 -0.0649701 -0.318726 +v 0.0447622 -0.129771 -0.289783 +v 0.0439885 -0.187683 -0.248754 +v 0.043512 -0.236482 -0.197215 +v 0.0433511 -0.274293 -0.137146 +v 0.043512 -0.299661 -0.070857 +v 0.0439885 -0.311613 -0.000894246 +v 0.0447622 -0.309689 0.0700534 +v 0.0458035 -0.293963 0.139259 +v 0.0470723 -0.265039 0.204064 +v 0.0485199 -0.224028 0.261977 +v 0.0500906 -0.172508 0.310773 +v 0.0517241 -0.112457 0.348577 +v 0.0533576 -0.046184 0.373935 +v 0.0549284 0.0237651 0.385874 +v 0.056376 0.0947017 0.383934 +v 0.0576448 0.1639 0.368191 +v 0.0586861 0.2287 0.339248 +v 0.0594598 0.286613 0.298219 +v 0.0599363 0.335412 0.24668 +v 0.0998232 0.364413 0.182206 +v 0.0995616 0.38918 0.117497 +v 0.0987868 0.400856 0.049204 +v 0.0975285 0.398991 -0.0200474 +v 0.0958351 0.383658 -0.0875963 +v 0.0937717 0.355446 -0.150847 +v 0.0914176 0.315438 -0.207368 +v 0.0888633 0.265172 -0.254988 +v 0.0862069 0.206581 -0.291877 +v 0.0835505 0.141914 -0.316617 +v 0.0809961 0.0736591 -0.328257 +v 0.0786421 0.00443736 -0.326351 +v 0.0765787 -0.0630905 -0.310971 +v 0.0748853 -0.12633 -0.282708 +v 0.073627 -0.182849 -0.242649 +v 0.0728522 -0.230478 -0.192332 +v 0.0725906 -0.267385 -0.133693 +v 0.0728522 -0.292153 -0.0689831 +v 0.073627 -0.303829 -0.000690358 +v 0.0748853 -0.301964 0.0685611 +v 0.0765787 -0.286631 0.13611 +v 0.0786421 -0.258418 0.19936 +v 0.0809961 -0.21841 0.255882 +v 0.0835505 -0.168145 0.303502 +v 0.0862069 -0.109553 0.340391 +v 0.0888633 -0.0448871 0.365131 +v 0.0914176 0.0233683 0.376771 +v 0.0937717 0.09259 0.374865 +v 0.0958351 0.160118 0.359484 +v 0.0975285 0.223357 0.331222 +v 0.0987868 0.279877 0.291162 +v 0.0995616 0.327506 0.240846 +v 0.139274 0.355062 0.177531 +v 0.138917 0.379229 0.114402 +v 0.13786 0.390633 0.0477808 +v 0.136142 0.388834 -0.0197714 +v 0.133831 0.373902 -0.0856591 +v 0.131015 0.346411 -0.14735 +v 0.127802 0.307417 -0.202474 +v 0.124315 0.258418 -0.248912 +v 0.12069 0.201298 -0.28488 +v 0.117064 0.138252 -0.308995 +v 0.113578 0.0717028 -0.320331 +v 0.110365 0.00420736 -0.318452 +v 0.107548 -0.0616403 -0.30343 +v 0.105237 -0.12331 -0.275843 +v 0.10352 -0.178431 -0.236751 +v 0.102462 -0.224885 -0.187656 +v 0.102105 -0.260888 -0.130444 +v 0.102462 -0.285056 -0.0673148 +v 0.10352 -0.296459 -0.000694015 +v 0.105237 -0.29466 0.0668582 +v 0.107548 -0.279728 0.132746 +v 0.110365 -0.252237 0.194437 +v 0.113578 -0.213243 0.249561 +v 0.117064 -0.164245 0.295999 +v 0.12069 -0.107125 0.331967 +v 0.124315 -0.0440787 0.356082 +v 0.127802 0.0224708 0.367418 +v 0.131015 0.0899662 0.365539 +v 0.133831 0.155814 0.350517 +v 0.136142 0.217483 0.32293 +v 0.13786 0.272604 0.283838 +v 0.138917 0.319059 0.234742 +v 0.178448 0.345175 0.172588 +v 0.178 0.368744 0.111039 +v 0.176676 0.379879 0.0460923 +v 0.174525 0.378151 -0.0197581 +v 0.17163 0.363628 -0.0839809 +v 0.168103 0.336867 -0.144108 +v 0.164079 0.298897 -0.197829 +v 0.159713 0.251177 -0.24308 +v 0.155172 0.195541 -0.27812 +v 0.150632 0.134126 -0.301605 +v 0.146265 0.0692938 -0.312631 +v 0.142241 0.00353486 -0.310774 +v 0.138714 -0.0606235 -0.296107 +v 0.13582 -0.120716 -0.269192 +v 0.133669 -0.174432 -0.231063 +v 0.132344 -0.21971 -0.183187 +v 0.131897 -0.254807 -0.127403 +v 0.132344 -0.278376 -0.0658552 +v 0.133669 -0.28951 -0.000907952 +v 0.13582 -0.287783 0.0649424 +v 0.138714 -0.273259 0.129165 +v 0.142241 -0.246499 0.189292 +v 0.146265 -0.208528 0.243014 +v 0.150632 -0.160808 0.288264 +v 0.155172 -0.105172 0.323305 +v 0.159713 -0.0437576 0.346789 +v 0.164079 0.0210748 0.357815 +v 0.168103 0.0868338 0.355959 +v 0.17163 0.150992 0.341291 +v 0.174525 0.211084 0.314376 +v 0.176676 0.264801 0.276248 +v 0.178 0.310078 0.228372 +v 0.21734 0.33476 0.16738 +v 0.216808 0.357731 0.107413 +v 0.215233 0.3686 0.0441411 +v 0.212675 0.366948 -0.0200048 +v 0.209232 0.352841 -0.0825594 +v 0.205036 0.326818 -0.141119 +v 0.20025 0.289881 -0.193433 +v 0.195056 0.24345 -0.23749 +v 0.189655 0.189307 -0.271599 +v 0.184254 0.129535 -0.294448 +v 0.17906 0.0664296 -0.305158 +v 0.174274 0.0024165 -0.30332 +v 0.170079 -0.0600444 -0.289002 +v 0.166636 -0.118553 -0.262755 +v 0.164077 -0.17086 -0.225589 +v 0.162502 -0.214957 -0.178931 +v 0.16197 -0.249148 -0.124574 +v 0.162502 -0.272119 -0.064607 +v 0.164077 -0.282987 -0.00133495 +v 0.166636 -0.281336 0.0628109 +v 0.170079 -0.267228 0.125366 +v 0.174274 -0.241206 0.183925 +v 0.17906 -0.204269 0.236239 +v 0.184254 -0.157837 0.280296 +v 0.189655 -0.103695 0.314405 +v 0.195056 -0.0439225 0.337254 +v 0.20025 0.0191828 0.347965 +v 0.205036 0.0831959 0.346126 +v 0.209232 0.145657 0.331808 +v 0.212675 0.204165 0.305562 +v 0.215233 0.256473 0.268395 +v 0.216808 0.300569 0.221737 +v 0.255951 0.323821 0.161911 +v 0.25534 0.346196 0.103526 +v 0.253529 0.356801 0.0419302 +v 0.250589 0.355231 -0.020509 +v 0.246633 0.341544 -0.0813925 +v 0.241812 0.316267 -0.13838 +v 0.236312 0.280372 -0.189283 +v 0.230344 0.235237 -0.232143 +v 0.224138 0.182598 -0.265315 +v 0.217932 0.124477 -0.287523 +v 0.211964 0.063108 -0.297915 +v 0.206464 0.000848904 -0.296089 +v 0.201643 -0.0599074 -0.282118 +v 0.197686 -0.116826 -0.256537 +v 0.194747 -0.16772 -0.22033 +v 0.192936 -0.210633 -0.174889 +v 0.192325 -0.243916 -0.121958 +v 0.192936 -0.266291 -0.0635734 +v 0.194747 -0.276896 -0.00197781 +v 0.197686 -0.275326 0.0604615 +v 0.201643 -0.261639 0.121345 +v 0.206464 -0.236362 0.178333 +v 0.211964 -0.200467 0.229235 +v 0.217932 -0.155332 0.272096 +v 0.224138 -0.102693 0.305268 +v 0.230344 -0.0445723 0.327476 +v 0.236312 0.0167969 0.337867 +v 0.241812 0.079056 0.336042 +v 0.246633 0.139812 0.322071 +v 0.250589 0.196731 0.29649 +v 0.253529 0.247625 0.260283 +v 0.25534 0.290538 0.214841 +v 0.294277 0.312366 0.156183 +v 0.293592 0.334144 0.0993804 +v 0.291563 0.344489 0.0394625 +v 0.288268 0.343003 -0.0212683 +v 0.283834 0.329742 -0.080478 +v 0.27843 0.305218 -0.135891 +v 0.272266 0.270371 -0.185379 +v 0.265577 0.226541 -0.227038 +v 0.258621 0.175413 -0.259269 +v 0.251664 0.118952 -0.280833 +v 0.244976 0.0593265 -0.290901 +v 0.238811 -0.00117134 -0.289086 +v 0.233408 -0.0602168 -0.275458 +v 0.228973 -0.115541 -0.25054 +v 0.225678 -0.165017 -0.215291 +v 0.223649 -0.206745 -0.171064 +v 0.222964 -0.23912 -0.11956 +v 0.223649 -0.260898 -0.0627573 +v 0.225678 -0.271243 -0.00283938 +v 0.228973 -0.269756 0.0578914 +v 0.233408 -0.256496 0.117101 +v 0.238811 -0.231971 0.172514 +v 0.244976 -0.197125 0.222002 +v 0.251664 -0.153295 0.263661 +v 0.258621 -0.102167 0.295892 +v 0.265577 -0.0457058 0.317456 +v 0.272266 0.0139196 0.327524 +v 0.27843 0.0744175 0.325709 +v 0.283834 0.133463 0.312081 +v 0.288268 0.188787 0.287163 +v 0.291563 0.238263 0.251914 +v 0.293592 0.279991 0.207687 +v 0.332318 0.300399 0.1502 +v 0.331564 0.321582 0.0949799 +v 0.329333 0.331668 0.0367406 +v 0.325709 0.33027 -0.02228 +v 0.320832 0.31744 -0.0798138 +v 0.31489 0.293673 -0.13365 +v 0.30811 0.259881 -0.181719 +v 0.300754 0.217363 -0.222174 +v 0.293103 0.167753 -0.253461 +v 0.285453 0.112958 -0.274377 +v 0.278097 0.055083 -0.284118 +v 0.271317 -0.00364766 -0.28231 +v 0.265375 -0.0609769 -0.269022 +v 0.260498 -0.114702 -0.244766 +v 0.256874 -0.162757 -0.210472 +v 0.254642 -0.203297 -0.16746 +v 0.253889 -0.234763 -0.117382 +v 0.254642 -0.255946 -0.0621618 +v 0.256874 -0.266032 -0.00392252 +v 0.260498 -0.264634 0.0550981 +v 0.265375 -0.251804 0.112632 +v 0.271317 -0.228037 0.166468 +v 0.278097 -0.194245 0.214537 +v 0.285453 -0.151727 0.254993 +v 0.293103 -0.102117 0.286279 +v 0.300754 -0.0473218 0.307195 +v 0.30811 0.0105532 0.316936 +v 0.31489 0.0692838 0.315128 +v 0.320832 0.126613 0.30184 +v 0.325709 0.180338 0.277584 +v 0.329333 0.228394 0.24329 +v 0.331564 0.268933 0.200278 +v 0.370073 0.287928 0.143964 +v 0.369256 0.308517 0.0903273 +v 0.366839 0.318345 0.0337675 +v 0.362912 0.317037 -0.0235416 +v 0.357629 0.304642 -0.0793976 +v 0.35119 0.281636 -0.131654 +v 0.343845 0.248904 -0.178303 +v 0.335875 0.207703 -0.217551 +v 0.327586 0.159617 -0.247891 +v 0.319298 0.106494 -0.268156 +v 0.311327 0.0503749 -0.277568 +v 0.303982 -0.00658349 -0.275764 +v 0.297544 -0.0621921 -0.262815 +v 0.29226 -0.114314 -0.239217 +v 0.288334 -0.160946 -0.205878 +v 0.285916 -0.200297 -0.164079 +v 0.2851 -0.230853 -0.115427 +v 0.285916 -0.251442 -0.0617898 +v 0.288334 -0.261271 -0.00523006 +v 0.29226 -0.259962 0.052079 +v 0.297544 -0.247567 0.107935 +v 0.303982 -0.224561 0.160192 +v 0.311327 -0.191829 0.20684 +v 0.319298 -0.150628 0.246089 +v 0.327586 -0.102542 0.276428 +v 0.335875 -0.0494191 0.296693 +v 0.343845 0.00670006 0.306105 +v 0.35119 0.0636584 0.304301 +v 0.357629 0.119267 0.291352 +v 0.362912 0.171389 0.267755 +v 0.366839 0.218021 0.234416 +v 0.369256 0.257372 0.192617 +v 0.407541 0.274959 0.137479 +v 0.406667 0.294953 0.0854257 +v 0.404079 0.304526 0.0305461 +v 0.399877 0.30331 -0.0250505 +v 0.394222 0.291352 -0.0792274 +v 0.387332 0.269111 -0.129903 +v 0.37947 0.237443 -0.175129 +v 0.37094 0.197564 -0.213168 +v 0.362069 0.151006 -0.242559 +v 0.353198 0.0995589 -0.262171 +v 0.344668 0.0451999 -0.27125 +v 0.336806 -0.00998225 -0.26945 +v 0.329916 -0.0638668 -0.256837 +v 0.324261 -0.114383 -0.233897 +v 0.320058 -0.15959 -0.201512 +v 0.317471 -0.19775 -0.160926 +v 0.316597 -0.227396 -0.113698 +v 0.317471 -0.24739 -0.0616445 +v 0.320058 -0.256963 -0.00676487 +v 0.324261 -0.255748 0.0488317 +v 0.329916 -0.24379 0.103009 +v 0.336806 -0.221549 0.153684 +v 0.344668 -0.18988 0.19891 +v 0.353198 -0.150001 0.236949 +v 0.362069 -0.103443 0.26634 +v 0.37094 -0.0519964 0.285952 +v 0.37947 0.00236257 0.295032 +v 0.387332 0.0575447 0.293231 +v 0.394222 0.111429 0.280618 +v 0.399877 0.161946 0.257678 +v 0.404079 0.207152 0.225293 +v 0.406667 0.245312 0.184707 +v 0.444722 0.261497 0.130749 +v 0.443797 0.280897 0.0802781 +v 0.441056 0.290215 0.0270791 +v 0.436604 0.289093 -0.0268041 +v 0.430614 0.277575 -0.0793008 +v 0.423314 0.256102 -0.128394 +v 0.414986 0.2255 -0.172196 +v 0.405949 0.186945 -0.209024 +v 0.396552 0.141919 -0.237464 +v 0.387154 0.0921514 -0.256421 +v 0.378118 0.0395556 -0.265168 +v 0.36979 -0.0138474 -0.263368 +v 0.36249 -0.0660054 -0.251091 +v 0.356499 -0.114914 -0.228808 +v 0.352048 -0.158694 -0.197375 +v 0.349307 -0.195662 -0.158001 +v 0.348381 -0.224398 -0.112199 +v 0.349307 -0.243798 -0.0617288 +v 0.352048 -0.253116 -0.00852977 +v 0.356499 -0.251995 0.0453535 +v 0.36249 -0.240476 0.0978502 +v 0.36979 -0.219003 0.146943 +v 0.378118 -0.188401 0.190745 +v 0.387154 -0.149846 0.227574 +v 0.396552 -0.10482 0.256013 +v 0.405949 -0.0550527 0.274971 +v 0.414986 -0.00245694 0.283717 +v 0.423314 0.050946 0.281918 +v 0.430614 0.103104 0.26964 +v 0.436604 0.152013 0.247357 +v 0.441056 0.195792 0.215925 +v 0.443797 0.232761 0.176551 +v 0.481618 0.247549 0.123774 +v 0.480646 0.266355 0.0748875 +v 0.477767 0.275419 0.0233694 +v 0.473093 0.274392 -0.0288 +v 0.466802 0.263314 -0.0796159 +v 0.459137 0.24261 -0.127125 +v 0.450392 0.213077 -0.169503 +v 0.440903 0.175848 -0.20512 +v 0.431034 0.132356 -0.232607 +v 0.421166 0.0842703 -0.250909 +v 0.411677 0.0334399 -0.259321 +v 0.402932 -0.0181822 -0.257522 +v 0.395267 -0.068612 -0.245579 +v 0.388976 -0.115912 -0.223952 +v 0.384301 -0.158263 -0.193472 +v 0.381423 -0.194039 -0.15531 +v 0.380451 -0.221865 -0.110933 +v 0.381423 -0.240671 -0.0620457 +v 0.384301 -0.249735 -0.0105276 +v 0.388976 -0.248708 0.0416418 +v 0.395267 -0.23763 0.0924577 +v 0.402932 -0.216927 0.139967 +v 0.411677 -0.187393 0.182345 +v 0.421166 -0.150165 0.217961 +v 0.431034 -0.106672 0.245449 +v 0.440903 -0.0585866 0.263751 +v 0.450392 -0.00775615 0.272163 +v 0.459137 0.0438659 0.270364 +v 0.466802 0.0942957 0.258421 +v 0.473093 0.141595 0.236794 +v 0.477767 0.183947 0.206314 +v 0.480646 0.219723 0.168152 +v 0.518228 0.233121 0.11656 +v 0.517215 0.251333 0.0692568 +v 0.514216 0.260143 0.0194198 +v 0.509345 0.259211 -0.0310356 +v 0.50279 0.248574 -0.0801704 +v 0.494802 0.228641 -0.126096 +v 0.485689 0.200177 -0.167048 +v 0.475801 0.164276 -0.201453 +v 0.465517 0.122317 -0.227988 +v 0.455234 0.0759146 -0.245634 +v 0.445346 0.0268502 -0.253712 +v 0.436233 -0.02299 -0.251912 +v 0.428245 -0.0716909 -0.240303 +v 0.42169 -0.117381 -0.219332 +v 0.416819 -0.158304 -0.189804 +v 0.413819 -0.192888 -0.152854 +v 0.412806 -0.219803 -0.109902 +v 0.413819 -0.238016 -0.0625981 +v 0.416819 -0.246825 -0.012761 +v 0.42169 -0.245894 0.0376943 +v 0.428245 -0.235257 0.0868291 +v 0.436233 -0.215323 0.132755 +v 0.445346 -0.186859 0.173707 +v 0.455234 -0.150958 0.208112 +v 0.465517 -0.109 0.234647 +v 0.475801 -0.0625971 0.252292 +v 0.485689 -0.0135328 0.26037 +v 0.494802 0.0363075 0.25857 +v 0.50279 0.0850084 0.246962 +v 0.509345 0.130698 0.22599 +v 0.514216 0.171622 0.196462 +v 0.517215 0.206205 0.159512 +v 0.554554 0.218218 0.109109 +v 0.553506 0.235837 0.0633889 +v 0.550402 0.244392 0.0152329 +v 0.54536 0.243556 -0.0335085 +v 0.538576 0.23336 -0.0809622 +v 0.530309 0.214196 -0.125305 +v 0.520877 0.186801 -0.164832 +v 0.510643 0.152227 -0.198024 +v 0.5 0.111803 -0.223607 +v 0.489357 0.0670829 -0.240596 +v 0.479123 0.0197845 -0.24834 +v 0.469691 -0.0282742 -0.24654 +v 0.461424 -0.0752464 -0.235266 +v 0.45464 -0.119327 -0.21495 +v 0.449598 -0.158822 -0.186374 +v 0.446494 -0.192213 -0.150636 +v 0.445446 -0.218218 -0.109109 +v 0.446494 -0.235837 -0.0633889 +v 0.449598 -0.244392 -0.0152329 +v 0.45464 -0.243556 0.0335085 +v 0.461424 -0.23336 0.0809622 +v 0.469691 -0.214196 0.125305 +v 0.479123 -0.186801 0.164832 +v 0.489357 -0.152227 0.198024 +v 0.5 -0.111803 0.223607 +v 0.510643 -0.0670829 0.240596 +v 0.520877 -0.0197845 0.24834 +v 0.530309 0.0282742 0.24654 +v 0.538576 0.0752464 0.235266 +v 0.54536 0.119327 0.21495 +v 0.550402 0.158822 0.186374 +v 0.553506 0.192213 0.150636 +f 1 34 2 +f 1 33 34 +f 2 35 3 +f 2 34 35 +f 3 36 4 +f 3 35 36 +f 4 37 5 +f 4 36 37 +f 5 38 6 +f 5 37 38 +f 6 39 7 +f 6 38 39 +f 7 40 8 +f 7 39 40 +f 8 41 9 +f 8 40 41 +f 9 42 10 +f 9 41 42 +f 10 43 11 +f 10 42 43 +f 11 44 12 +f 11 43 44 +f 12 45 13 +f 12 44 45 +f 13 46 14 +f 13 45 46 +f 14 47 15 +f 14 46 47 +f 15 48 16 +f 15 47 48 +f 16 49 17 +f 16 48 49 +f 17 50 18 +f 17 49 50 +f 18 51 19 +f 18 50 51 +f 19 52 20 +f 19 51 52 +f 20 53 21 +f 20 52 53 +f 21 54 22 +f 21 53 54 +f 22 55 23 +f 22 54 55 +f 23 56 24 +f 23 55 56 +f 24 57 25 +f 24 56 57 +f 25 58 26 +f 25 57 58 +f 26 59 27 +f 26 58 59 +f 27 60 28 +f 27 59 60 +f 28 61 29 +f 28 60 61 +f 29 62 30 +f 29 61 62 +f 30 63 31 +f 30 62 63 +f 31 64 32 +f 31 63 64 +f 32 33 1 +f 32 64 33 +f 33 66 34 +f 33 65 66 +f 34 67 35 +f 34 66 67 +f 35 68 36 +f 35 67 68 +f 36 69 37 +f 36 68 69 +f 37 70 38 +f 37 69 70 +f 38 71 39 +f 38 70 71 +f 39 72 40 +f 39 71 72 +f 40 73 41 +f 40 72 73 +f 41 74 42 +f 41 73 74 +f 42 75 43 +f 42 74 75 +f 43 76 44 +f 43 75 76 +f 44 77 45 +f 44 76 77 +f 45 78 46 +f 45 77 78 +f 46 79 47 +f 46 78 79 +f 47 80 48 +f 47 79 80 +f 48 81 49 +f 48 80 81 +f 49 82 50 +f 49 81 82 +f 50 83 51 +f 50 82 83 +f 51 84 52 +f 51 83 84 +f 52 85 53 +f 52 84 85 +f 53 86 54 +f 53 85 86 +f 54 87 55 +f 54 86 87 +f 55 88 56 +f 55 87 88 +f 56 89 57 +f 56 88 89 +f 57 90 58 +f 57 89 90 +f 58 91 59 +f 58 90 91 +f 59 92 60 +f 59 91 92 +f 60 93 61 +f 60 92 93 +f 61 94 62 +f 61 93 94 +f 62 95 63 +f 62 94 95 +f 63 96 64 +f 63 95 96 +f 64 65 33 +f 64 96 65 +f 65 98 66 +f 65 97 98 +f 66 99 67 +f 66 98 99 +f 67 100 68 +f 67 99 100 +f 68 101 69 +f 68 100 101 +f 69 102 70 +f 69 101 102 +f 70 103 71 +f 70 102 103 +f 71 104 72 +f 71 103 104 +f 72 105 73 +f 72 104 105 +f 73 106 74 +f 73 105 106 +f 74 107 75 +f 74 106 107 +f 75 108 76 +f 75 107 108 +f 76 109 77 +f 76 108 109 +f 77 110 78 +f 77 109 110 +f 78 111 79 +f 78 110 111 +f 79 112 80 +f 79 111 112 +f 80 113 81 +f 80 112 113 +f 81 114 82 +f 81 113 114 +f 82 115 83 +f 82 114 115 +f 83 116 84 +f 83 115 116 +f 84 117 85 +f 84 116 117 +f 85 118 86 +f 85 117 118 +f 86 119 87 +f 86 118 119 +f 87 120 88 +f 87 119 120 +f 88 121 89 +f 88 120 121 +f 89 122 90 +f 89 121 122 +f 90 123 91 +f 90 122 123 +f 91 124 92 +f 91 123 124 +f 92 125 93 +f 92 124 125 +f 93 126 94 +f 93 125 126 +f 94 127 95 +f 94 126 127 +f 95 128 96 +f 95 127 128 +f 96 97 65 +f 96 128 97 +f 97 130 98 +f 97 129 130 +f 98 131 99 +f 98 130 131 +f 99 132 100 +f 99 131 132 +f 100 133 101 +f 100 132 133 +f 101 134 102 +f 101 133 134 +f 102 135 103 +f 102 134 135 +f 103 136 104 +f 103 135 136 +f 104 137 105 +f 104 136 137 +f 105 138 106 +f 105 137 138 +f 106 139 107 +f 106 138 139 +f 107 140 108 +f 107 139 140 +f 108 141 109 +f 108 140 141 +f 109 142 110 +f 109 141 142 +f 110 143 111 +f 110 142 143 +f 111 144 112 +f 111 143 144 +f 112 145 113 +f 112 144 145 +f 113 146 114 +f 113 145 146 +f 114 147 115 +f 114 146 147 +f 115 148 116 +f 115 147 148 +f 116 149 117 +f 116 148 149 +f 117 150 118 +f 117 149 150 +f 118 151 119 +f 118 150 151 +f 119 152 120 +f 119 151 152 +f 120 153 121 +f 120 152 153 +f 121 154 122 +f 121 153 154 +f 122 155 123 +f 122 154 155 +f 123 156 124 +f 123 155 156 +f 124 157 125 +f 124 156 157 +f 125 158 126 +f 125 157 158 +f 126 159 127 +f 126 158 159 +f 127 160 128 +f 127 159 160 +f 128 129 97 +f 128 160 129 +f 129 162 130 +f 129 161 162 +f 130 163 131 +f 130 162 163 +f 131 164 132 +f 131 163 164 +f 132 165 133 +f 132 164 165 +f 133 166 134 +f 133 165 166 +f 134 167 135 +f 134 166 167 +f 135 168 136 +f 135 167 168 +f 136 169 137 +f 136 168 169 +f 137 170 138 +f 137 169 170 +f 138 171 139 +f 138 170 171 +f 139 172 140 +f 139 171 172 +f 140 173 141 +f 140 172 173 +f 141 174 142 +f 141 173 174 +f 142 175 143 +f 142 174 175 +f 143 176 144 +f 143 175 176 +f 144 177 145 +f 144 176 177 +f 145 178 146 +f 145 177 178 +f 146 179 147 +f 146 178 179 +f 147 180 148 +f 147 179 180 +f 148 181 149 +f 148 180 181 +f 149 182 150 +f 149 181 182 +f 150 183 151 +f 150 182 183 +f 151 184 152 +f 151 183 184 +f 152 185 153 +f 152 184 185 +f 153 186 154 +f 153 185 186 +f 154 187 155 +f 154 186 187 +f 155 188 156 +f 155 187 188 +f 156 189 157 +f 156 188 189 +f 157 190 158 +f 157 189 190 +f 158 191 159 +f 158 190 191 +f 159 192 160 +f 159 191 192 +f 160 161 129 +f 160 192 161 +f 161 194 162 +f 161 193 194 +f 162 195 163 +f 162 194 195 +f 163 196 164 +f 163 195 196 +f 164 197 165 +f 164 196 197 +f 165 198 166 +f 165 197 198 +f 166 199 167 +f 166 198 199 +f 167 200 168 +f 167 199 200 +f 168 201 169 +f 168 200 201 +f 169 202 170 +f 169 201 202 +f 170 203 171 +f 170 202 203 +f 171 204 172 +f 171 203 204 +f 172 205 173 +f 172 204 205 +f 173 206 174 +f 173 205 206 +f 174 207 175 +f 174 206 207 +f 175 208 176 +f 175 207 208 +f 176 209 177 +f 176 208 209 +f 177 210 178 +f 177 209 210 +f 178 211 179 +f 178 210 211 +f 179 212 180 +f 179 211 212 +f 180 213 181 +f 180 212 213 +f 181 214 182 +f 181 213 214 +f 182 215 183 +f 182 214 215 +f 183 216 184 +f 183 215 216 +f 184 217 185 +f 184 216 217 +f 185 218 186 +f 185 217 218 +f 186 219 187 +f 186 218 219 +f 187 220 188 +f 187 219 220 +f 188 221 189 +f 188 220 221 +f 189 222 190 +f 189 221 222 +f 190 223 191 +f 190 222 223 +f 191 224 192 +f 191 223 224 +f 192 193 161 +f 192 224 193 +f 193 226 194 +f 193 225 226 +f 194 227 195 +f 194 226 227 +f 195 228 196 +f 195 227 228 +f 196 229 197 +f 196 228 229 +f 197 230 198 +f 197 229 230 +f 198 231 199 +f 198 230 231 +f 199 232 200 +f 199 231 232 +f 200 233 201 +f 200 232 233 +f 201 234 202 +f 201 233 234 +f 202 235 203 +f 202 234 235 +f 203 236 204 +f 203 235 236 +f 204 237 205 +f 204 236 237 +f 205 238 206 +f 205 237 238 +f 206 239 207 +f 206 238 239 +f 207 240 208 +f 207 239 240 +f 208 241 209 +f 208 240 241 +f 209 242 210 +f 209 241 242 +f 210 243 211 +f 210 242 243 +f 211 244 212 +f 211 243 244 +f 212 245 213 +f 212 244 245 +f 213 246 214 +f 213 245 246 +f 214 247 215 +f 214 246 247 +f 215 248 216 +f 215 247 248 +f 216 249 217 +f 216 248 249 +f 217 250 218 +f 217 249 250 +f 218 251 219 +f 218 250 251 +f 219 252 220 +f 219 251 252 +f 220 253 221 +f 220 252 253 +f 221 254 222 +f 221 253 254 +f 222 255 223 +f 222 254 255 +f 223 256 224 +f 223 255 256 +f 224 225 193 +f 224 256 225 +f 225 258 226 +f 225 257 258 +f 226 259 227 +f 226 258 259 +f 227 260 228 +f 227 259 260 +f 228 261 229 +f 228 260 261 +f 229 262 230 +f 229 261 262 +f 230 263 231 +f 230 262 263 +f 231 264 232 +f 231 263 264 +f 232 265 233 +f 232 264 265 +f 233 266 234 +f 233 265 266 +f 234 267 235 +f 234 266 267 +f 235 268 236 +f 235 267 268 +f 236 269 237 +f 236 268 269 +f 237 270 238 +f 237 269 270 +f 238 271 239 +f 238 270 271 +f 239 272 240 +f 239 271 272 +f 240 273 241 +f 240 272 273 +f 241 274 242 +f 241 273 274 +f 242 275 243 +f 242 274 275 +f 243 276 244 +f 243 275 276 +f 244 277 245 +f 244 276 277 +f 245 278 246 +f 245 277 278 +f 246 279 247 +f 246 278 279 +f 247 280 248 +f 247 279 280 +f 248 281 249 +f 248 280 281 +f 249 282 250 +f 249 281 282 +f 250 283 251 +f 250 282 283 +f 251 284 252 +f 251 283 284 +f 252 285 253 +f 252 284 285 +f 253 286 254 +f 253 285 286 +f 254 287 255 +f 254 286 287 +f 255 288 256 +f 255 287 288 +f 256 257 225 +f 256 288 257 +f 257 290 258 +f 257 289 290 +f 258 291 259 +f 258 290 291 +f 259 292 260 +f 259 291 292 +f 260 293 261 +f 260 292 293 +f 261 294 262 +f 261 293 294 +f 262 295 263 +f 262 294 295 +f 263 296 264 +f 263 295 296 +f 264 297 265 +f 264 296 297 +f 265 298 266 +f 265 297 298 +f 266 299 267 +f 266 298 299 +f 267 300 268 +f 267 299 300 +f 268 301 269 +f 268 300 301 +f 269 302 270 +f 269 301 302 +f 270 303 271 +f 270 302 303 +f 271 304 272 +f 271 303 304 +f 272 305 273 +f 272 304 305 +f 273 306 274 +f 273 305 306 +f 274 307 275 +f 274 306 307 +f 275 308 276 +f 275 307 308 +f 276 309 277 +f 276 308 309 +f 277 310 278 +f 277 309 310 +f 278 311 279 +f 278 310 311 +f 279 312 280 +f 279 311 312 +f 280 313 281 +f 280 312 313 +f 281 314 282 +f 281 313 314 +f 282 315 283 +f 282 314 315 +f 283 316 284 +f 283 315 316 +f 284 317 285 +f 284 316 317 +f 285 318 286 +f 285 317 318 +f 286 319 287 +f 286 318 319 +f 287 320 288 +f 287 319 320 +f 288 289 257 +f 288 320 289 +f 289 322 290 +f 289 321 322 +f 290 323 291 +f 290 322 323 +f 291 324 292 +f 291 323 324 +f 292 325 293 +f 292 324 325 +f 293 326 294 +f 293 325 326 +f 294 327 295 +f 294 326 327 +f 295 328 296 +f 295 327 328 +f 296 329 297 +f 296 328 329 +f 297 330 298 +f 297 329 330 +f 298 331 299 +f 298 330 331 +f 299 332 300 +f 299 331 332 +f 300 333 301 +f 300 332 333 +f 301 334 302 +f 301 333 334 +f 302 335 303 +f 302 334 335 +f 303 336 304 +f 303 335 336 +f 304 337 305 +f 304 336 337 +f 305 338 306 +f 305 337 338 +f 306 339 307 +f 306 338 339 +f 307 340 308 +f 307 339 340 +f 308 341 309 +f 308 340 341 +f 309 342 310 +f 309 341 342 +f 310 343 311 +f 310 342 343 +f 311 344 312 +f 311 343 344 +f 312 345 313 +f 312 344 345 +f 313 346 314 +f 313 345 346 +f 314 347 315 +f 314 346 347 +f 315 348 316 +f 315 347 348 +f 316 349 317 +f 316 348 349 +f 317 350 318 +f 317 349 350 +f 318 351 319 +f 318 350 351 +f 319 352 320 +f 319 351 352 +f 320 321 289 +f 320 352 321 +f 321 354 322 +f 321 353 354 +f 322 355 323 +f 322 354 355 +f 323 356 324 +f 323 355 356 +f 324 357 325 +f 324 356 357 +f 325 358 326 +f 325 357 358 +f 326 359 327 +f 326 358 359 +f 327 360 328 +f 327 359 360 +f 328 361 329 +f 328 360 361 +f 329 362 330 +f 329 361 362 +f 330 363 331 +f 330 362 363 +f 331 364 332 +f 331 363 364 +f 332 365 333 +f 332 364 365 +f 333 366 334 +f 333 365 366 +f 334 367 335 +f 334 366 367 +f 335 368 336 +f 335 367 368 +f 336 369 337 +f 336 368 369 +f 337 370 338 +f 337 369 370 +f 338 371 339 +f 338 370 371 +f 339 372 340 +f 339 371 372 +f 340 373 341 +f 340 372 373 +f 341 374 342 +f 341 373 374 +f 342 375 343 +f 342 374 375 +f 343 376 344 +f 343 375 376 +f 344 377 345 +f 344 376 377 +f 345 378 346 +f 345 377 378 +f 346 379 347 +f 346 378 379 +f 347 380 348 +f 347 379 380 +f 348 381 349 +f 348 380 381 +f 349 382 350 +f 349 381 382 +f 350 383 351 +f 350 382 383 +f 351 384 352 +f 351 383 384 +f 352 353 321 +f 352 384 353 +f 353 386 354 +f 353 385 386 +f 354 387 355 +f 354 386 387 +f 355 388 356 +f 355 387 388 +f 356 389 357 +f 356 388 389 +f 357 390 358 +f 357 389 390 +f 358 391 359 +f 358 390 391 +f 359 392 360 +f 359 391 392 +f 360 393 361 +f 360 392 393 +f 361 394 362 +f 361 393 394 +f 362 395 363 +f 362 394 395 +f 363 396 364 +f 363 395 396 +f 364 397 365 +f 364 396 397 +f 365 398 366 +f 365 397 398 +f 366 399 367 +f 366 398 399 +f 367 400 368 +f 367 399 400 +f 368 401 369 +f 368 400 401 +f 369 402 370 +f 369 401 402 +f 370 403 371 +f 370 402 403 +f 371 404 372 +f 371 403 404 +f 372 405 373 +f 372 404 405 +f 373 406 374 +f 373 405 406 +f 374 407 375 +f 374 406 407 +f 375 408 376 +f 375 407 408 +f 376 409 377 +f 376 408 409 +f 377 410 378 +f 377 409 410 +f 378 411 379 +f 378 410 411 +f 379 412 380 +f 379 411 412 +f 380 413 381 +f 380 412 413 +f 381 414 382 +f 381 413 414 +f 382 415 383 +f 382 414 415 +f 383 416 384 +f 383 415 416 +f 384 385 353 +f 384 416 385 +f 385 418 386 +f 385 417 418 +f 386 419 387 +f 386 418 419 +f 387 420 388 +f 387 419 420 +f 388 421 389 +f 388 420 421 +f 389 422 390 +f 389 421 422 +f 390 423 391 +f 390 422 423 +f 391 424 392 +f 391 423 424 +f 392 425 393 +f 392 424 425 +f 393 426 394 +f 393 425 426 +f 394 427 395 +f 394 426 427 +f 395 428 396 +f 395 427 428 +f 396 429 397 +f 396 428 429 +f 397 430 398 +f 397 429 430 +f 398 431 399 +f 398 430 431 +f 399 432 400 +f 399 431 432 +f 400 433 401 +f 400 432 433 +f 401 434 402 +f 401 433 434 +f 402 435 403 +f 402 434 435 +f 403 436 404 +f 403 435 436 +f 404 437 405 +f 404 436 437 +f 405 438 406 +f 405 437 438 +f 406 439 407 +f 406 438 439 +f 407 440 408 +f 407 439 440 +f 408 441 409 +f 408 440 441 +f 409 442 410 +f 409 441 442 +f 410 443 411 +f 410 442 443 +f 411 444 412 +f 411 443 444 +f 412 445 413 +f 412 444 445 +f 413 446 414 +f 413 445 446 +f 414 447 415 +f 414 446 447 +f 415 448 416 +f 415 447 448 +f 416 417 385 +f 416 448 417 +f 417 450 418 +f 417 449 450 +f 418 451 419 +f 418 450 451 +f 419 452 420 +f 419 451 452 +f 420 453 421 +f 420 452 453 +f 421 454 422 +f 421 453 454 +f 422 455 423 +f 422 454 455 +f 423 456 424 +f 423 455 456 +f 424 457 425 +f 424 456 457 +f 425 458 426 +f 425 457 458 +f 426 459 427 +f 426 458 459 +f 427 460 428 +f 427 459 460 +f 428 461 429 +f 428 460 461 +f 429 462 430 +f 429 461 462 +f 430 463 431 +f 430 462 463 +f 431 464 432 +f 431 463 464 +f 432 465 433 +f 432 464 465 +f 433 466 434 +f 433 465 466 +f 434 467 435 +f 434 466 467 +f 435 468 436 +f 435 467 468 +f 436 469 437 +f 436 468 469 +f 437 470 438 +f 437 469 470 +f 438 471 439 +f 438 470 471 +f 439 472 440 +f 439 471 472 +f 440 473 441 +f 440 472 473 +f 441 474 442 +f 441 473 474 +f 442 475 443 +f 442 474 475 +f 443 476 444 +f 443 475 476 +f 444 477 445 +f 444 476 477 +f 445 478 446 +f 445 477 478 +f 446 479 447 +f 446 478 479 +f 447 480 448 +f 447 479 480 +f 448 449 417 +f 448 480 449 +f 449 482 450 +f 449 481 482 +f 450 483 451 +f 450 482 483 +f 451 484 452 +f 451 483 484 +f 452 485 453 +f 452 484 485 +f 453 486 454 +f 453 485 486 +f 454 487 455 +f 454 486 487 +f 455 488 456 +f 455 487 488 +f 456 489 457 +f 456 488 489 +f 457 490 458 +f 457 489 490 +f 458 491 459 +f 458 490 491 +f 459 492 460 +f 459 491 492 +f 460 493 461 +f 460 492 493 +f 461 494 462 +f 461 493 494 +f 462 495 463 +f 462 494 495 +f 463 496 464 +f 463 495 496 +f 464 497 465 +f 464 496 497 +f 465 498 466 +f 465 497 498 +f 466 499 467 +f 466 498 499 +f 467 500 468 +f 467 499 500 +f 468 501 469 +f 468 500 501 +f 469 502 470 +f 469 501 502 +f 470 503 471 +f 470 502 503 +f 471 504 472 +f 471 503 504 +f 472 505 473 +f 472 504 505 +f 473 506 474 +f 473 505 506 +f 474 507 475 +f 474 506 507 +f 475 508 476 +f 475 507 508 +f 476 509 477 +f 476 508 509 +f 477 510 478 +f 477 509 510 +f 478 511 479 +f 478 510 511 +f 479 512 480 +f 479 511 512 +f 480 481 449 +f 480 512 481 +f 481 514 482 +f 481 513 514 +f 482 515 483 +f 482 514 515 +f 483 516 484 +f 483 515 516 +f 484 517 485 +f 484 516 517 +f 485 518 486 +f 485 517 518 +f 486 519 487 +f 486 518 519 +f 487 520 488 +f 487 519 520 +f 488 521 489 +f 488 520 521 +f 489 522 490 +f 489 521 522 +f 490 523 491 +f 490 522 523 +f 491 524 492 +f 491 523 524 +f 492 525 493 +f 492 524 525 +f 493 526 494 +f 493 525 526 +f 494 527 495 +f 494 526 527 +f 495 528 496 +f 495 527 528 +f 496 529 497 +f 496 528 529 +f 497 530 498 +f 497 529 530 +f 498 531 499 +f 498 530 531 +f 499 532 500 +f 499 531 532 +f 500 533 501 +f 500 532 533 +f 501 534 502 +f 501 533 534 +f 502 535 503 +f 502 534 535 +f 503 536 504 +f 503 535 536 +f 504 537 505 +f 504 536 537 +f 505 538 506 +f 505 537 538 +f 506 539 507 +f 506 538 539 +f 507 540 508 +f 507 539 540 +f 508 541 509 +f 508 540 541 +f 509 542 510 +f 509 541 542 +f 510 543 511 +f 510 542 543 +f 511 544 512 +f 511 543 544 +f 512 513 481 +f 512 544 513 +f 513 546 514 +f 513 545 546 +f 514 547 515 +f 514 546 547 +f 515 548 516 +f 515 547 548 +f 516 549 517 +f 516 548 549 +f 517 550 518 +f 517 549 550 +f 518 551 519 +f 518 550 551 +f 519 552 520 +f 519 551 552 +f 520 553 521 +f 520 552 553 +f 521 554 522 +f 521 553 554 +f 522 555 523 +f 522 554 555 +f 523 556 524 +f 523 555 556 +f 524 557 525 +f 524 556 557 +f 525 558 526 +f 525 557 558 +f 526 559 527 +f 526 558 559 +f 527 560 528 +f 527 559 560 +f 528 561 529 +f 528 560 561 +f 529 562 530 +f 529 561 562 +f 530 563 531 +f 530 562 563 +f 531 564 532 +f 531 563 564 +f 532 565 533 +f 532 564 565 +f 533 566 534 +f 533 565 566 +f 534 567 535 +f 534 566 567 +f 535 568 536 +f 535 567 568 +f 536 569 537 +f 536 568 569 +f 537 570 538 +f 537 569 570 +f 538 571 539 +f 538 570 571 +f 539 572 540 +f 539 571 572 +f 540 573 541 +f 540 572 573 +f 541 574 542 +f 541 573 574 +f 542 575 543 +f 542 574 575 +f 543 576 544 +f 543 575 576 +f 544 545 513 +f 544 576 545 +f 545 578 546 +f 545 577 578 +f 546 579 547 +f 546 578 579 +f 547 580 548 +f 547 579 580 +f 548 581 549 +f 548 580 581 +f 549 582 550 +f 549 581 582 +f 550 583 551 +f 550 582 583 +f 551 584 552 +f 551 583 584 +f 552 585 553 +f 552 584 585 +f 553 586 554 +f 553 585 586 +f 554 587 555 +f 554 586 587 +f 555 588 556 +f 555 587 588 +f 556 589 557 +f 556 588 589 +f 557 590 558 +f 557 589 590 +f 558 591 559 +f 558 590 591 +f 559 592 560 +f 559 591 592 +f 560 593 561 +f 560 592 593 +f 561 594 562 +f 561 593 594 +f 562 595 563 +f 562 594 595 +f 563 596 564 +f 563 595 596 +f 564 597 565 +f 564 596 597 +f 565 598 566 +f 565 597 598 +f 566 599 567 +f 566 598 599 +f 567 600 568 +f 567 599 600 +f 568 601 569 +f 568 600 601 +f 569 602 570 +f 569 601 602 +f 570 603 571 +f 570 602 603 +f 571 604 572 +f 571 603 604 +f 572 605 573 +f 572 604 605 +f 573 606 574 +f 573 605 606 +f 574 607 575 +f 574 606 607 +f 575 608 576 +f 575 607 608 +f 576 577 545 +f 576 608 577 +f 577 610 578 +f 577 609 610 +f 578 611 579 +f 578 610 611 +f 579 612 580 +f 579 611 612 +f 580 613 581 +f 580 612 613 +f 581 614 582 +f 581 613 614 +f 582 615 583 +f 582 614 615 +f 583 616 584 +f 583 615 616 +f 584 617 585 +f 584 616 617 +f 585 618 586 +f 585 617 618 +f 586 619 587 +f 586 618 619 +f 587 620 588 +f 587 619 620 +f 588 621 589 +f 588 620 621 +f 589 622 590 +f 589 621 622 +f 590 623 591 +f 590 622 623 +f 591 624 592 +f 591 623 624 +f 592 625 593 +f 592 624 625 +f 593 626 594 +f 593 625 626 +f 594 627 595 +f 594 626 627 +f 595 628 596 +f 595 627 628 +f 596 629 597 +f 596 628 629 +f 597 630 598 +f 597 629 630 +f 598 631 599 +f 598 630 631 +f 599 632 600 +f 599 631 632 +f 600 633 601 +f 600 632 633 +f 601 634 602 +f 601 633 634 +f 602 635 603 +f 602 634 635 +f 603 636 604 +f 603 635 636 +f 604 637 605 +f 604 636 637 +f 605 638 606 +f 605 637 638 +f 606 639 607 +f 606 638 639 +f 607 640 608 +f 607 639 640 +f 608 609 577 +f 608 640 609 +f 609 642 610 +f 609 641 642 +f 610 643 611 +f 610 642 643 +f 611 644 612 +f 611 643 644 +f 612 645 613 +f 612 644 645 +f 613 646 614 +f 613 645 646 +f 614 647 615 +f 614 646 647 +f 615 648 616 +f 615 647 648 +f 616 649 617 +f 616 648 649 +f 617 650 618 +f 617 649 650 +f 618 651 619 +f 618 650 651 +f 619 652 620 +f 619 651 652 +f 620 653 621 +f 620 652 653 +f 621 654 622 +f 621 653 654 +f 622 655 623 +f 622 654 655 +f 623 656 624 +f 623 655 656 +f 624 657 625 +f 624 656 657 +f 625 658 626 +f 625 657 658 +f 626 659 627 +f 626 658 659 +f 627 660 628 +f 627 659 660 +f 628 661 629 +f 628 660 661 +f 629 662 630 +f 629 661 662 +f 630 663 631 +f 630 662 663 +f 631 664 632 +f 631 663 664 +f 632 665 633 +f 632 664 665 +f 633 666 634 +f 633 665 666 +f 634 667 635 +f 634 666 667 +f 635 668 636 +f 635 667 668 +f 636 669 637 +f 636 668 669 +f 637 670 638 +f 637 669 670 +f 638 671 639 +f 638 670 671 +f 639 672 640 +f 639 671 672 +f 640 641 609 +f 640 672 641 +f 641 674 642 +f 641 673 674 +f 642 675 643 +f 642 674 675 +f 643 676 644 +f 643 675 676 +f 644 677 645 +f 644 676 677 +f 645 678 646 +f 645 677 678 +f 646 679 647 +f 646 678 679 +f 647 680 648 +f 647 679 680 +f 648 681 649 +f 648 680 681 +f 649 682 650 +f 649 681 682 +f 650 683 651 +f 650 682 683 +f 651 684 652 +f 651 683 684 +f 652 685 653 +f 652 684 685 +f 653 686 654 +f 653 685 686 +f 654 687 655 +f 654 686 687 +f 655 688 656 +f 655 687 688 +f 656 689 657 +f 656 688 689 +f 657 690 658 +f 657 689 690 +f 658 691 659 +f 658 690 691 +f 659 692 660 +f 659 691 692 +f 660 693 661 +f 660 692 693 +f 661 694 662 +f 661 693 694 +f 662 695 663 +f 662 694 695 +f 663 696 664 +f 663 695 696 +f 664 697 665 +f 664 696 697 +f 665 698 666 +f 665 697 698 +f 666 699 667 +f 666 698 699 +f 667 700 668 +f 667 699 700 +f 668 701 669 +f 668 700 701 +f 669 702 670 +f 669 701 702 +f 670 703 671 +f 670 702 703 +f 671 704 672 +f 671 703 704 +f 672 673 641 +f 672 704 673 +f 673 706 674 +f 673 705 706 +f 674 707 675 +f 674 706 707 +f 675 708 676 +f 675 707 708 +f 676 709 677 +f 676 708 709 +f 677 710 678 +f 677 709 710 +f 678 711 679 +f 678 710 711 +f 679 712 680 +f 679 711 712 +f 680 713 681 +f 680 712 713 +f 681 714 682 +f 681 713 714 +f 682 715 683 +f 682 714 715 +f 683 716 684 +f 683 715 716 +f 684 717 685 +f 684 716 717 +f 685 718 686 +f 685 717 718 +f 686 719 687 +f 686 718 719 +f 687 720 688 +f 687 719 720 +f 688 721 689 +f 688 720 721 +f 689 722 690 +f 689 721 722 +f 690 723 691 +f 690 722 723 +f 691 724 692 +f 691 723 724 +f 692 725 693 +f 692 724 725 +f 693 726 694 +f 693 725 726 +f 694 727 695 +f 694 726 727 +f 695 728 696 +f 695 727 728 +f 696 729 697 +f 696 728 729 +f 697 730 698 +f 697 729 730 +f 698 731 699 +f 698 730 731 +f 699 732 700 +f 699 731 732 +f 700 733 701 +f 700 732 733 +f 701 734 702 +f 701 733 734 +f 702 735 703 +f 702 734 735 +f 703 736 704 +f 703 735 736 +f 704 705 673 +f 704 736 705 +f 705 738 706 +f 705 737 738 +f 706 739 707 +f 706 738 739 +f 707 740 708 +f 707 739 740 +f 708 741 709 +f 708 740 741 +f 709 742 710 +f 709 741 742 +f 710 743 711 +f 710 742 743 +f 711 744 712 +f 711 743 744 +f 712 745 713 +f 712 744 745 +f 713 746 714 +f 713 745 746 +f 714 747 715 +f 714 746 747 +f 715 748 716 +f 715 747 748 +f 716 749 717 +f 716 748 749 +f 717 750 718 +f 717 749 750 +f 718 751 719 +f 718 750 751 +f 719 752 720 +f 719 751 752 +f 720 753 721 +f 720 752 753 +f 721 754 722 +f 721 753 754 +f 722 755 723 +f 722 754 755 +f 723 756 724 +f 723 755 756 +f 724 757 725 +f 724 756 757 +f 725 758 726 +f 725 757 758 +f 726 759 727 +f 726 758 759 +f 727 760 728 +f 727 759 760 +f 728 761 729 +f 728 760 761 +f 729 762 730 +f 729 761 762 +f 730 763 731 +f 730 762 763 +f 731 764 732 +f 731 763 764 +f 732 765 733 +f 732 764 765 +f 733 766 734 +f 733 765 766 +f 734 767 735 +f 734 766 767 +f 735 768 736 +f 735 767 768 +f 736 737 705 +f 736 768 737 +f 737 770 738 +f 737 769 770 +f 738 771 739 +f 738 770 771 +f 739 772 740 +f 739 771 772 +f 740 773 741 +f 740 772 773 +f 741 774 742 +f 741 773 774 +f 742 775 743 +f 742 774 775 +f 743 776 744 +f 743 775 776 +f 744 777 745 +f 744 776 777 +f 745 778 746 +f 745 777 778 +f 746 779 747 +f 746 778 779 +f 747 780 748 +f 747 779 780 +f 748 781 749 +f 748 780 781 +f 749 782 750 +f 749 781 782 +f 750 783 751 +f 750 782 783 +f 751 784 752 +f 751 783 784 +f 752 785 753 +f 752 784 785 +f 753 786 754 +f 753 785 786 +f 754 787 755 +f 754 786 787 +f 755 788 756 +f 755 787 788 +f 756 789 757 +f 756 788 789 +f 757 790 758 +f 757 789 790 +f 758 791 759 +f 758 790 791 +f 759 792 760 +f 759 791 792 +f 760 793 761 +f 760 792 793 +f 761 794 762 +f 761 793 794 +f 762 795 763 +f 762 794 795 +f 763 796 764 +f 763 795 796 +f 764 797 765 +f 764 796 797 +f 765 798 766 +f 765 797 798 +f 766 799 767 +f 766 798 799 +f 767 800 768 +f 767 799 800 +f 768 769 737 +f 768 800 769 +f 769 802 770 +f 769 801 802 +f 770 803 771 +f 770 802 803 +f 771 804 772 +f 771 803 804 +f 772 805 773 +f 772 804 805 +f 773 806 774 +f 773 805 806 +f 774 807 775 +f 774 806 807 +f 775 808 776 +f 775 807 808 +f 776 809 777 +f 776 808 809 +f 777 810 778 +f 777 809 810 +f 778 811 779 +f 778 810 811 +f 779 812 780 +f 779 811 812 +f 780 813 781 +f 780 812 813 +f 781 814 782 +f 781 813 814 +f 782 815 783 +f 782 814 815 +f 783 816 784 +f 783 815 816 +f 784 817 785 +f 784 816 817 +f 785 818 786 +f 785 817 818 +f 786 819 787 +f 786 818 819 +f 787 820 788 +f 787 819 820 +f 788 821 789 +f 788 820 821 +f 789 822 790 +f 789 821 822 +f 790 823 791 +f 790 822 823 +f 791 824 792 +f 791 823 824 +f 792 825 793 +f 792 824 825 +f 793 826 794 +f 793 825 826 +f 794 827 795 +f 794 826 827 +f 795 828 796 +f 795 827 828 +f 796 829 797 +f 796 828 829 +f 797 830 798 +f 797 829 830 +f 798 831 799 +f 798 830 831 +f 799 832 800 +f 799 831 832 +f 800 801 769 +f 800 832 801 +f 801 834 802 +f 801 833 834 +f 802 835 803 +f 802 834 835 +f 803 836 804 +f 803 835 836 +f 804 837 805 +f 804 836 837 +f 805 838 806 +f 805 837 838 +f 806 839 807 +f 806 838 839 +f 807 840 808 +f 807 839 840 +f 808 841 809 +f 808 840 841 +f 809 842 810 +f 809 841 842 +f 810 843 811 +f 810 842 843 +f 811 844 812 +f 811 843 844 +f 812 845 813 +f 812 844 845 +f 813 846 814 +f 813 845 846 +f 814 847 815 +f 814 846 847 +f 815 848 816 +f 815 847 848 +f 816 849 817 +f 816 848 849 +f 817 850 818 +f 817 849 850 +f 818 851 819 +f 818 850 851 +f 819 852 820 +f 819 851 852 +f 820 853 821 +f 820 852 853 +f 821 854 822 +f 821 853 854 +f 822 855 823 +f 822 854 855 +f 823 856 824 +f 823 855 856 +f 824 857 825 +f 824 856 857 +f 825 858 826 +f 825 857 858 +f 826 859 827 +f 826 858 859 +f 827 860 828 +f 827 859 860 +f 828 861 829 +f 828 860 861 +f 829 862 830 +f 829 861 862 +f 830 863 831 +f 830 862 863 +f 831 864 832 +f 831 863 864 +f 832 833 801 +f 832 864 833 +f 833 866 834 +f 833 865 866 +f 834 867 835 +f 834 866 867 +f 835 868 836 +f 835 867 868 +f 836 869 837 +f 836 868 869 +f 837 870 838 +f 837 869 870 +f 838 871 839 +f 838 870 871 +f 839 872 840 +f 839 871 872 +f 840 873 841 +f 840 872 873 +f 841 874 842 +f 841 873 874 +f 842 875 843 +f 842 874 875 +f 843 876 844 +f 843 875 876 +f 844 877 845 +f 844 876 877 +f 845 878 846 +f 845 877 878 +f 846 879 847 +f 846 878 879 +f 847 880 848 +f 847 879 880 +f 848 881 849 +f 848 880 881 +f 849 882 850 +f 849 881 882 +f 850 883 851 +f 850 882 883 +f 851 884 852 +f 851 883 884 +f 852 885 853 +f 852 884 885 +f 853 886 854 +f 853 885 886 +f 854 887 855 +f 854 886 887 +f 855 888 856 +f 855 887 888 +f 856 889 857 +f 856 888 889 +f 857 890 858 +f 857 889 890 +f 858 891 859 +f 858 890 891 +f 859 892 860 +f 859 891 892 +f 860 893 861 +f 860 892 893 +f 861 894 862 +f 861 893 894 +f 862 895 863 +f 862 894 895 +f 863 896 864 +f 863 895 896 +f 864 865 833 +f 864 896 865 +f 865 898 866 +f 865 897 898 +f 866 899 867 +f 866 898 899 +f 867 900 868 +f 867 899 900 +f 868 901 869 +f 868 900 901 +f 869 902 870 +f 869 901 902 +f 870 903 871 +f 870 902 903 +f 871 904 872 +f 871 903 904 +f 872 905 873 +f 872 904 905 +f 873 906 874 +f 873 905 906 +f 874 907 875 +f 874 906 907 +f 875 908 876 +f 875 907 908 +f 876 909 877 +f 876 908 909 +f 877 910 878 +f 877 909 910 +f 878 911 879 +f 878 910 911 +f 879 912 880 +f 879 911 912 +f 880 913 881 +f 880 912 913 +f 881 914 882 +f 881 913 914 +f 882 915 883 +f 882 914 915 +f 883 916 884 +f 883 915 916 +f 884 917 885 +f 884 916 917 +f 885 918 886 +f 885 917 918 +f 886 919 887 +f 886 918 919 +f 887 920 888 +f 887 919 920 +f 888 921 889 +f 888 920 921 +f 889 922 890 +f 889 921 922 +f 890 923 891 +f 890 922 923 +f 891 924 892 +f 891 923 924 +f 892 925 893 +f 892 924 925 +f 893 926 894 +f 893 925 926 +f 894 927 895 +f 894 926 927 +f 895 928 896 +f 895 927 928 +f 896 897 865 +f 896 928 897 +f 897 930 898 +f 897 929 930 +f 898 931 899 +f 898 930 931 +f 899 932 900 +f 899 931 932 +f 900 933 901 +f 900 932 933 +f 901 934 902 +f 901 933 934 +f 902 935 903 +f 902 934 935 +f 903 936 904 +f 903 935 936 +f 904 937 905 +f 904 936 937 +f 905 938 906 +f 905 937 938 +f 906 939 907 +f 906 938 939 +f 907 940 908 +f 907 939 940 +f 908 941 909 +f 908 940 941 +f 909 942 910 +f 909 941 942 +f 910 943 911 +f 910 942 943 +f 911 944 912 +f 911 943 944 +f 912 945 913 +f 912 944 945 +f 913 946 914 +f 913 945 946 +f 914 947 915 +f 914 946 947 +f 915 948 916 +f 915 947 948 +f 916 949 917 +f 916 948 949 +f 917 950 918 +f 917 949 950 +f 918 951 919 +f 918 950 951 +f 919 952 920 +f 919 951 952 +f 920 953 921 +f 920 952 953 +f 921 954 922 +f 921 953 954 +f 922 955 923 +f 922 954 955 +f 923 956 924 +f 923 955 956 +f 924 957 925 +f 924 956 957 +f 925 958 926 +f 925 957 958 +f 926 959 927 +f 926 958 959 +f 927 960 928 +f 927 959 960 +f 928 929 897 +f 928 960 929 diff --git a/marshall/Blender/generate_3d.py b/marshall/Blender/generate_3d.py new file mode 100644 index 0000000..3e55294 --- /dev/null +++ b/marshall/Blender/generate_3d.py @@ -0,0 +1,76 @@ +import bpy +import bmesh +import os +import numpy as np +import camera as c +import params as p +from random import randint +from mathutils import Vector, Matrix, Euler +from math import radians +import matplotlib.pyplot as plt +from scipy.spatial.transform import Rotation as R +from curve_fitting import BezierBasedDetection, Bezier +from bpy_extras.io_utils import unpack_list + + + +class Generate_3D: + def __init__(self, full_arr, x, y, z, num_pix): + self.full_arr = full_arr + self.rad = [] + self.y = y + self.x = x + self.num_pix = num_pix + self.z = z + + def create_mesh(self): + self.set_y_x_rad() + + #bpy.data.objects.remove(bpy.data.objects['Cube']) + + crv = bpy.data.curves.new('crv', 'CURVE') + crv.dimensions = '3D' + crv.fill_mode = 'FULL' + crv.bevel_depth = 0.045 + crv.resolution_u = 1 + obj = bpy.data.objects.new('crv', crv) + bpy.context.scene.collection.objects.link(obj) + spline = crv.splines.new(type='BEZIER') + + spline.bezier_points.add(len(self.full_arr)-1) + for i in range(len(self.full_arr)): + + + spline.bezier_points[i].co = self.full_arr[i] + + spline.bezier_points[i].radius = self.rad[i] + + print(spline.bezier_points[i].radius) + + + fig = plt.figure() + ax = fig.add_subplot(projection='3d') + ax.plot(*self.full_arr.T) + ax.axis('equal') + plt.show() + + blend_file_path = bpy.data.filepath + directory = os.path.dirname(blend_file_path) + target_file = os.path.join(directory, 'thisisatest.obj') + bpy.ops.export_scene.obj(filepath=target_file) + + def set_y_x_rad(self): + camera = c.PinholeCameraModel() + camera.from_npz(p.cam) + assert isinstance(camera, c.PinholeCameraModel) + + + for i in range(len(self.full_arr)): + self.full_arr[i][0] = camera.getDeltaX(self.x[i], self.z[i]) + self.full_arr[i][1] = camera.getDeltaY(self.y[i], self.z[i]) + self.rad.append(camera.getDeltaX(self.num_pix[i], self.z[i])) + print(self.num_pix[i]) + + + + diff --git a/marshall/D435_640x480.camera.npz b/marshall/D435_640x480.camera.npz new file mode 100644 index 0000000..9f9051c Binary files /dev/null and b/marshall/D435_640x480.camera.npz differ diff --git a/marshall/README.md b/marshall/README.md new file mode 100644 index 0000000..8590555 --- /dev/null +++ b/marshall/README.md @@ -0,0 +1,56 @@ +# internship_summer_2023 +Work and documentation from my summer 2023 AgAID internship. + +# What it is +The test_connectivity.py code takes in masks and depth images of trees, builds 3D cylinders along a bezier curve following a branch, and determines which side branches are connected to which main or "leader" branches. +The pull depth and rgb data file takes a .mkv video and extracts depth and rgb data in whatever format you wish.--> may require changes to test_connectivity to work with different formats. + +# How it works +1. Builds a Bezier curve by determining the medial axis of the white space in a mask + - This returns the radii, "t" value and the curve points at which the curve is evaluated, as well as a curve +2. Finds average depth in a cross-space of the tree branch + - Uses numpy and opencv to do this by first drawing singular blue squares that align with the limits of the mask and the curve points, then by reading the depth image at those points +3. Determines the closest point and distance from the end points of the side branch to the curve of the leader and picks the closest two points +4. Determines the difference in depth between the two points +5. Determines the angle between the two tangent lines of each points +6. Returns a score based in those aspects that refers to how likely it is that the branches are connected (lower is better) +7. Plots curves and points it is evaluating +8. Uses bezier cyl 3d to generate cylinders along the curve +9. Merges cylinder files to create a tree + +# Assumptions +- Leader and side branches are labeled as such +- Points are ordered +- There is a .mkv video file to work with +- There are masks to work with + +# Notes for Running +- After cloning the repository, just run connection_test.py +- Adjust any of the parameters to include your own depth and mask images as well as a video file (uploaded files do not currently contain the mkv file used for generation) +- Requires OpenCV, Matplotlib, Skimage, Scipy, PyK4A, and Networkx libraries--> see Documentation for install PyK4A +- To pull RGB and Depth data, copy the python file to the directory where the .mkv video is stored(or alter code to specify a path) + +# General Notes +- The curve_fitting and camera files are contribution from [Alex You](https://github.com/osu-youa) +- Azure camera depth data needs to be tested to confirm its conversion to meters +- generate_3d.py works with and requires Blender to run. It uses Blender to generate a Bezier curve rather than using cylinders. Unless scaled up, it generates a small curve in meters. Radius does not currently operate as expected. + +# Output +The cylinders generated produce: +![alt text](generated_tree.png) +As compared to: +![alt text](leader_mask.png) +![alt text](follower_mask.png) +It displays in the terminal: +![alt text](output.png) +This shows the total score for how likely a side branch is to match to a leader branch(lower is better). + +# Instructions for Installing PyK4A +- See: [Kinect on Ubuntu](https://github.com/juancarlosmiranda/azure_kinect_notes) +- And: [PyK4A](https://github.com/etiennedub/pyk4a) + +# TODO: +- Image annotations for model +- Test camera to confirm conversion between depth data and meters +- Implement loop to manage all files that need to be tested +- Implement loop to manage multiple frames from video footage diff --git a/marshall/__pycache__/camera.cpython-310.pyc b/marshall/__pycache__/camera.cpython-310.pyc new file mode 100644 index 0000000..c2d4762 Binary files /dev/null and b/marshall/__pycache__/camera.cpython-310.pyc differ diff --git a/marshall/__pycache__/curve_fitting.cpython-310.pyc b/marshall/__pycache__/curve_fitting.cpython-310.pyc new file mode 100644 index 0000000..1109697 Binary files /dev/null and b/marshall/__pycache__/curve_fitting.cpython-310.pyc differ diff --git a/marshall/__pycache__/params.cpython-310.pyc b/marshall/__pycache__/params.cpython-310.pyc new file mode 100644 index 0000000..c9d362c Binary files /dev/null and b/marshall/__pycache__/params.cpython-310.pyc differ diff --git a/marshall/build/.built_by b/marshall/build/.built_by new file mode 100644 index 0000000..06e74ac --- /dev/null +++ b/marshall/build/.built_by @@ -0,0 +1 @@ +colcon diff --git a/marshall/build/COLCON_IGNORE b/marshall/build/COLCON_IGNORE new file mode 100644 index 0000000..e69de29 diff --git a/marshall/camera.py b/marshall/camera.py new file mode 100644 index 0000000..9bd20e4 --- /dev/null +++ b/marshall/camera.py @@ -0,0 +1,280 @@ +import copy +import cv2 +import numpy +import math +from skimage import io + +def mkmat(rows, cols, L): + mat = numpy.matrix(L, dtype='float64') + mat.resize((rows,cols)) + return mat + + +class PinholeCameraModel: + + """ + A pinhole camera is an idealized monocular camera. + """ + + def __init__(self): + self.K = None + self.D = None + self.R = None + self.P = None + self.full_K = None + self.full_P = None + self.width = None + self.height = None + self.binning_x = None + self.binning_y = None + self.raw_roi = None + self.tf_frame = None + self.stamp = None + + def fromCameraInfo(self, msg): + """ + :param msg: camera parameters + :type msg: sensor_msgs.msg.CameraInfo + + Set the camera parameters from the :class:`sensor_msgs.msg.CameraInfo` message. + """ + self.K = mkmat(3, 3, msg.k) + if msg.d: + self.D = mkmat(len(msg.d), 1, msg.d) + else: + self.D = None + self.R = mkmat(3, 3, msg.r) + self.P = mkmat(3, 4, msg.p) + self.full_K = mkmat(3, 3, msg.k) + self.full_P = mkmat(3, 4, msg.p) + self.width = msg.width + self.height = msg.height + self.binning_x = max(1, msg.binning_x) + self.binning_y = max(1, msg.binning_y) + self.resolution = (msg.width, msg.height) + + self.raw_roi = copy.copy(msg.roi) + # ROI all zeros is considered the same as full resolution + if (self.raw_roi.x_offset == 0 and self.raw_roi.y_offset == 0 and + self.raw_roi.width == 0 and self.raw_roi.height == 0): + self.raw_roi.width = self.width + self.raw_roi.height = self.height + + # Adjust K and P for binning and ROI + self.K[0,0] /= self.binning_x + self.K[1,1] /= self.binning_y + self.K[0,2] = (self.K[0,2] - self.raw_roi.x_offset) / self.binning_x + self.K[1,2] = (self.K[1,2] - self.raw_roi.y_offset) / self.binning_y + self.P[0,0] /= self.binning_x + self.P[1,1] /= self.binning_y + self.P[0,2] = (self.P[0,2] - self.raw_roi.x_offset) / self.binning_x + self.P[1,2] = (self.P[1,2] - self.raw_roi.y_offset) / self.binning_y + + def to_npz(self, output_path): + attribs = ['K', 'D', 'R', 'P', 'full_K', 'full_P', 'width', 'height', 'binning_x', 'binning_y', + 'resolution'] + vals = {attrib: getattr(self, attrib) for attrib in attribs} + numpy.savez(output_path, **vals) + + def from_npz(self, path): + for attrib, val in numpy.load(path).items(): + setattr(self, attrib, val) + + def rectifyImage(self, raw, rectified): + """ + :param raw: input image + :type raw: :class:`CvMat` or :class:`IplImage` + :param rectified: rectified output image + :type rectified: :class:`CvMat` or :class:`IplImage` + + Applies the rectification specified by camera parameters :math:`K` and and :math:`D` to image `raw` and writes the resulting image `rectified`. + """ + + self.mapx = numpy.ndarray(shape=(self.height, self.width, 1), + dtype='float32') + self.mapy = numpy.ndarray(shape=(self.height, self.width, 1), + dtype='float32') + cv2.initUndistortRectifyMap(self.K, self.D, self.R, self.P, + (self.width, self.height), cv2.CV_32FC1, self.mapx, self.mapy) + cv2.remap(raw, self.mapx, self.mapy, cv2.INTER_CUBIC, rectified) + + def rectifyPoint(self, uv_raw): + """ + :param uv_raw: pixel coordinates + :type uv_raw: (u, v) + + Applies the rectification specified by camera parameters + :math:`K` and and :math:`D` to point (u, v) and returns the + pixel coordinates of the rectified point. + """ + + src = mkmat(1, 2, list(uv_raw)) + src.resize((1,1,2)) + dst = cv2.undistortPoints(src, self.K, self.D, R=self.R, P=self.P) + return dst[0,0] + + def project3dToPixel(self, point): + """ + :param point: 3D point + :type point: (x, y, z) + + Returns the rectified pixel coordinates (u, v) of the 3D point, + using the camera :math:`P` matrix. + This is the inverse of :meth:`projectPixelTo3dRay`. + """ + src = mkmat(4, 1, [point[0], point[1], point[2], 1.0]) + dst = self.P * src + x = dst[0,0] + y = dst[1,0] + w = dst[2,0] + if w != 0: + return (x / w, y / w) + else: + return (float('nan'), float('nan')) + + def projectPixelTo3dRay(self, uv): + """ + :param uv: rectified pixel coordinates + :type uv: (u, v) + + Returns the unit vector which passes from the camera center to through rectified pixel (u, v), + using the camera :math:`P` matrix. + This is the inverse of :meth:`project3dToPixel`. + """ + x = (uv[0] - self.cx()) / self.fx() + y = (uv[1] - self.cy()) / self.fy() + norm = math.sqrt(x*x + y*y + 1) + x /= norm + y /= norm + z = 1.0 / norm + return (x, y, z) + + def getDeltaU(self, deltaX, Z): + """ + :param deltaX: delta X, in cartesian space + :type deltaX: float + :param Z: Z, in cartesian space + :type Z: float + :rtype: float + + Compute delta u, given Z and delta X in Cartesian space. + For given Z, this is the inverse of :meth:`getDeltaX`. + """ + fx = self.P[0, 0] + if Z == 0: + return float('inf') + else: + return fx * deltaX / Z + + def getDeltaV(self, deltaY, Z): + """ + :param deltaY: delta Y, in cartesian space + :type deltaY: float + :param Z: Z, in cartesian space + :type Z: float + :rtype: float + + Compute delta v, given Z and delta Y in Cartesian space. + For given Z, this is the inverse of :meth:`getDeltaY`. + """ + fy = self.P[1, 1] + if Z == 0: + return float('inf') + else: + return fy * deltaY / Z + + def getDeltaX(self, deltaU, Z): + """ + :param deltaU: delta u in pixels + :type deltaU: float + :param Z: Z, in cartesian space + :type Z: float + :rtype: float + + Compute delta X, given Z in cartesian space and delta u in pixels. + For given Z, this is the inverse of :meth:`getDeltaU`. + """ + fx = self.P[0, 0] + return Z * deltaU / fx + + def getDeltaY(self, deltaV, Z): + """ + :param deltaV: delta v in pixels + :type deltaV: float + :param Z: Z, in cartesian space + :type Z: float + :rtype: float + + Compute delta Y, given Z in cartesian space and delta v in pixels. + For given Z, this is the inverse of :meth:`getDeltaV`. + """ + fy = self.P[1, 1] + return Z * deltaV / fy + + def fullResolution(self): + """Returns the full resolution of the camera""" + return self.resolution + + def intrinsicMatrix(self): + """ Returns :math:`K`, also called camera_matrix in cv docs """ + return self.K + def distortionCoeffs(self): + """ Returns :math:`D` """ + return self.D + def rotationMatrix(self): + """ Returns :math:`R` """ + return self.R + def projectionMatrix(self): + """ Returns :math:`P` """ + return self.P + def fullIntrinsicMatrix(self): + """ Return the original camera matrix for full resolution """ + return self.full_K + def fullProjectionMatrix(self): + """ Return the projection matrix for full resolution """ + return self.full_P + + def cx(self): + """ Returns x center """ + return self.P[0,2] + def cy(self): + """ Returns y center """ + return self.P[1,2] + def fx(self): + """ Returns x focal length """ + return self.P[0,0] + def fy(self): + """ Returns y focal length """ + return self.P[1,1] + + def Tx(self): + """ Return the x-translation term of the projection matrix """ + return self.P[0,3] + + def Ty(self): + """ Return the y-translation term of the projection matrix """ + return self.P[1,3] + + def tfFrame(self): + """ Returns the tf frame name - a string - of the camera. + This is the frame of the :class:`sensor_msgs.msg.CameraInfo` message. + """ + return self.tf_frame + + + + +# IGNORE THIS STUFF +def run_test_node(): + import rclpy + from follow_the_leader.utils.ros_utils import TFNode + import pickle + class Temp(TFNode): + def _handle_cam_info(self, msg): + cam = PinholeCameraModel() + cam.fromCameraInfo(msg) + cam.to_npz('D435_640x480.camera.npz') + rclpy.init() + bla = Temp('temp', cam_info_topic='/camera/color/camera_info') + rclpy.spin(bla) + diff --git a/marshall/connection_test.py b/marshall/connection_test.py new file mode 100644 index 0000000..0b45dd7 --- /dev/null +++ b/marshall/connection_test.py @@ -0,0 +1,341 @@ +import cv2 +import math +import params as p +import camera as c +import numpy as np +import sys +import random +from pyk4a import PyK4APlayback +import curve_fitting as cf +import matplotlib.pyplot as plt +from skimage import io, color, img_as_bool +from curve_fitting import BezierBasedDetection, Bezier +#from generate_3d import Generate_3D +sys.path.insert(1, '../') +import bezier_cyl_3d as bc3 + +class Depths_Average: + """ + Parameters: + depth_img: Currently uses a frame from Envy orchard, the depth image of a single tree. + bin_msk: Binary mask of a tree, corresponds with depth data. + selected_end_pointiables: + my_mask: reads binary mask + my_depth: reads depth image using skimage, which gets the depth values of the image + lined_mask: commented, used for visualization + radii: radii of branch at evaluated points along curve + curve_pts: evaluated points along Bezier curve + + """ + + def __init__(self, bin_msk): + self.my_mask = np.asarray(img_as_bool(cv2.resize(color.rgb2gray(cv2.imread(bin_msk).astype('uint8')),(640,576)))) + self.my_mask2 = np.asarray(cv2.resize(color.rgb2gray(cv2.imread(bin_msk).astype('uint8')),(640,576))) + k4a = PyK4APlayback(p.video_file) #specify video file you wish to open in params + k4a.open() + capture = k4a.get_next_capture() + self.my_depth = capture.depth + self.lined_mask = None + self.radii = None + self.curve_pts = None + + def get_radii(self): + """ + Uses curve_fitting to get Bezier curve by first fitting a curve and then determining radii along evaluated points. + Currently evaluates for 11 points. Returns radii, points along the curve, the curve object, and the "t" values. + """ + detector = cf.BezierBasedDetection(self.my_mask, use_medial_axis=True) + curve = detector.fit() + radius_interpolator = detector.get_radius_interpolator_on_path() + ds = np.linspace(0, 1, p.num_cyl) + self.radii = radius_interpolator(ds) + self.curve_pts, ts = curve.eval_by_arclen(ds, normalized=True) + + return self.radii, self.curve_pts, curve, ts + + def find_average(self): + """ + Finds the average depth across a rectangular contour. Returns array of average depths and pixel width of tree. + """ + depths = [] + depths_average = [] + + for i in range(len(self.curve_pts) - 1): + right_bottom_pt = ( + self.curve_pts[i][0].astype(int) + (self.radii[i]/2).astype(int), self.curve_pts[i][1].astype(int)) + left_bottom_point = ( + self.curve_pts[i][0].astype(int) - (self.radii[i]/2).astype(int), self.curve_pts[i][1].astype(int)) + right_top_point = ( + self.curve_pts[i + 1][0].astype(int) + (self.radii[i + 1]/2).astype(int), self.curve_pts[i + 1][1].astype(int)) + left_top_pt = ( + self.curve_pts[i + 1][0].astype(int) - (self.radii[i + 1]/2).astype(int), self.curve_pts[i + 1][1].astype(int)) + + arr = np.array([right_bottom_pt, left_bottom_point, left_top_pt, right_top_point]) + img = cv2.cvtColor((self.my_mask2.copy().astype('uint8')), cv2.COLOR_GRAY2BGR) + img = cv2.drawContours(img, [arr.astype(int)], -1, color=(0,0,255), thickness=-1) + + pts = np.asarray(np.where(img == 255)) + + arry=self.my_depth[pts[0],pts[1]] + + arr = arry[np.where(arry!=0)] + + depths.append(arr[~np.isnan(arr).any(axis=0) and arr<10000]) + + ar2 = (np.mean(depths[i]))*0.0001 #need to figure out the correct conversion between depth data and meters + if np.isnan(ar2): #replaces empty array values with 0 + depths_average.append(p.nan_value) + else: + depths_average.append(ar2) + + return depths_average, self.radii + + +class Determine_Match: + """ + Determines if a side branch matches a leader branch. + """ + def __init__(self): + self.angle_limit = p.angle_limit + + def return_closest(self, curve_pts, end_pt_1, end_pt_2): + """ + Returns the closest distance between evaluated points on leader curve and end points of side branch curve. + Parameters: + curve_pts: all points evaluated on leader curve + end_pt_1: an end point on side branch curve + end_pt_2: other end point on side branch curve + Returns: + ind: index of matching points + selected_end_point: the matching end point + dist: minimum distance between selected points + """ + distance_arr = [] + prev_dist = math.inf + for i, point in enumerate(curve_pts): + dist1 = math.dist(point, end_pt_1) + dist2 = math.dist(point, end_pt_2) + + if dist1 <= dist2: + distance_arr.append(dist1) + if prev_dist >= dist1: + ind, selected_end_point, dist = self.get_values(end_pt_1, i, dist1) + + else: + distance_arr.append(dist2) + if prev_dist >= dist2: + ind, selected_end_point, dist = self.get_values(end_pt_2, i, dist2) + + prev_dist = dist + + return ind, selected_end_point, dist + + + def get_values(self, end_point, ind, dist): + """ + returns index, end_point, and dist after conditions of return_closest are satisfied + """ + return ind, end_point, dist + + def depth_scoring(self, closest_depth, end_depth): + """ + Parameters: + closest_depth: depth of closest point on leader curve + end_depth: depth of selected end point + Returns: + the difference between the two (the difference in depth) + """ + return abs(closest_depth - end_depth) + + + def check_angle_match(self, vec_1, vec_2): + """ + Checks if the angle falls within the given angle parameters. + Parameters: + vec_1: a tangent line to one of the selected points + vec_2: a tangent line to the other selected point + Returns: + a score based on if the angle between the two vectors falls in an acceptable range. Currently set to arbitrary numbers. + """ + angle = np.arccos( + np.clip(np.dot((vec_1 / np.linalg.norm(vec_1)), (vec_2 / np.linalg.norm(vec_2))), -1.0, 1.0)) * ( + 180 / np.pi) + + if angle < self.angle_limit: + return 1 + + elif angle > self.angle_limit: + return 0 + + else: + return 0.5 + + +class Build_3D: + """ + Constructs 3D cylinders for a given curve + Parameters: + curve_points: given points along a Bezier curve + radii: radii at curve_points + name: whether the branch is a follower or leader + """ + def __init__(self, curve_points, radii, name): + self.radii = radii + self.curve_points = curve_points + self.name = name + self.n_along = 10 * p.cyls #parameter for faces + self.n_around = 64 #parameter for faces + + def set_real_measurements(self): + """ + Takes curve_points and converts to size in meters, scales up for visibility + """ + camera = c.PinholeCameraModel() + camera.from_npz(p.cam) + assert isinstance(camera, c.PinholeCameraModel) + for i in range(len(self.curve_points)): + self.curve_points[i][0] = camera.getDeltaX(self.curve_points[i][0], self.curve_points[i][2])*p.scale_factor + self.curve_points[i][1] = camera.getDeltaY(self.curve_points[i][1], self.curve_points[i][2])*p.scale_factor + self.radii[i] = camera.getDeltaX(self.radii[i], self.curve_points[i][2])*p.scale_factor + + def build(self): + """ + Passes in beginning, middle, and end curve points and beginning and end radii to a class that builds a 3D mesh for each cylinder + merges all cylinders by altering obj files + """ + self.set_real_measurements() + + for i in range(len(self.curve_points)-2): + b = bc3.BezierCyl3D(self.curve_points[i], self.curve_points[i+1], self.curve_points[i+2], self.radii[i], self.radii[i+2]) + b.make_mesh() + b.write_mesh(f"{self.name}_{i}.obj") + self.write_verts(f"{self.name}_{i}.obj") + self.write_f() + self.merge_files() + + def write_verts(self, fi): + """ + Passes in generated cylinder file and appends vertices to a list + """ + count = 0 + with open(fi, 'r') as f, open(f"v_lines{self.name}.obj", 'a') as vl: + data = f.readlines() + for line in data: + if "v" in line: + vl.write(line) + + def write_f(self): + """ + writes faces to a file + """ + with open(f"f_lines{self.name}.obj", 'w') as fl: + for it in range(0, self.n_along - 1): + i_curr = it * self.n_around + 1 + i_next = (it+1) * self.n_around + 1 + for ir in range(0, self.n_around): + ir_next = (ir + 1) % self.n_around + fl.write(f"f {i_curr + ir} {i_next + ir_next} {i_curr + ir_next} \n") + fl.write(f"f {i_curr + ir} {i_next + ir} {i_next + ir_next} \n") + + def merge_files(self): + """ + merges object files based on faces and verts + """ + with open(f"curve{self.name}.obj", 'w') as c, open(f"v_lines{self.name}.obj", 'r') as vl, open(f"f_lines{self.name}.obj", 'r') as fl: + file1 = vl.read() + file2 = fl.read() + c.write(file1) + c.write(file2) + +def make_tree(file1, file2): + """ + constructs the tree by merging generated verticies files + """ + n_along = 10 * p.cyls + n_around = 64 + with open(file1, "r") as f1, open(file2, "r") as f2, open("treefile.obj", "w") as tf: + data1 = f1.readlines() + tf.writelines(data1) + data2 = f2.readlines() + tf.writelines(data2) + for it in range(0, (n_along*2) - 1): + i_curr = it * (n_around) + 1 + i_next = (it+1) * (n_around) + 1 + for ir in range(0, (n_around)): + ir_next = (ir + 1) % (n_around) + tf.write(f"f {i_curr + ir} {i_next + ir_next} {i_curr + ir_next} \n") + tf.write(f"f {i_curr + ir} {i_next + ir} {i_next + ir_next} \n") + +def manage_arrs(curve_2d, depth_arr): + """ + Splits curve_2D and depth_arr to their components, as well as merging them + Parameters: + curve_2d: 2D Bezier points in x and y from a mask + depth_arr: depth at those points + """ + split_curve = np.split(curve_2d, 2, 1) + _x = np.delete(split_curve[0], -1) + _y = np.delete(split_curve[1], -1) + _z = np.asarray(depth_arr) + full_arr = np.array([_x, _y, _z]).T + + return _x, _y, _z, full_arr + + +if __name__ == '__main__': + + d = Depths_Average(p.mask_img) + rad, curve_pts, curve, ts = d.get_radii() + depth, num_pix = d.find_average() + + d2 = Depths_Average(p.follower_msk) + rad2, curve_pts2, curve2, ts2 = d2.get_radii() + depth2, num_pix2 = d2.find_average() + + x1, y1, z1, leader_pts = manage_arrs(curve_pts, depth) + x2, y2, z2, follower_pts = manage_arrs(curve_pts2, depth2) + + dm = Determine_Match() + + end1 = follower_pts[0] + end2 = follower_pts[-1] + + index, end_pt, minimum_distance = dm.return_closest(leader_pts, end1, end2) + depth_score = dm.depth_scoring(z1[index], end_pt[2]) + leader_tan = curve.tangent(ts[index]) + follower_tan = curve2.tangent(ts2[index]) + + angle_score = dm.check_angle_match(leader_tan, follower_tan) + total_score = angle_score + depth_score + minimum_distance + + b = Build_3D(leader_pts, rad, "leader") + b.build() + + b2 = Build_3D(follower_pts, rad2, "follower") + b2.build() + + make_tree("v_linesleader.obj", "v_linesfollower.obj") + + #g2 = Generate_3D(follower_pts, x2, y2, z2, num_pix2) + #g2.create_mesh() + + fig = plt.figure() + ax = fig.add_subplot(projection='3d') + + print("Total: ", total_score) + print("Angle Score: ", angle_score) + print("Min Dist: ", minimum_distance) + print("Depth Difference: ", depth_score) + + #Uncomment below if you wish to visualize both curves + """ + ax.scatter(x1, y1, z1) + ax.scatter(x2, y2, z2) + + ax.plot(x1, y1, z1) + ax.plot(x2, y2, z2) + ax.scatter(*np.asarray(end1).T) + ax.scatter(*np.asarray(end2).T) + ax.axis('equal') + plt.show() + """ diff --git a/marshall/curve_fitting.py b/marshall/curve_fitting.py new file mode 100644 index 0000000..9f425a0 --- /dev/null +++ b/marshall/curve_fitting.py @@ -0,0 +1,479 @@ +import numpy as np +import os +from matplotlib import pyplot as plt +from scipy.special import comb +from skimage.morphology import skeletonize, medial_axis +from skimage import io, img_as_bool, color +import networkx as nx +from scipy.spatial import KDTree +from scipy.interpolate import interp1d +import cv2 + +class BezierBasedDetection: + def __init__(self, mask, outlier_threshold=4, use_medial_axis=False): + self.mask = mask + self.skel = None + self.dists = None + self.stats = {} + self.outlier_threshold = outlier_threshold + self.use_medial_axis = use_medial_axis + + self.subsampled_graph = None + self.selected_path = None + self.selected_curve = None + + def construct_skeletal_graph(self, trim=0): + graph = nx.Graph() + if self.use_medial_axis: + skel, dists = medial_axis(self.mask, return_distance=True) + else: + skel = skeletonize(self.mask) + dists = None + + if trim: + skel[:trim] = 0 + skel[-trim:] = 0 + skel[:,:trim] = 0 + skel[:,-trim:] = 0 + + self.skel = skel + self.dists = dists + pxs = np.array(np.where(skel)).T[:, [1, 0]] + for px in pxs: + graph.add_node(tuple(px)) + for dir in np.array([[-1,0],[1,0],[0,1],[0,-1],[-1,-1],[-1,1],[1,-1],[1,1]]): + new_px = dir + px + if (0 <= new_px[0] < self.mask.shape[1]) and (0 <= new_px[1] < self.mask.shape[0]) and skel[new_px[1], new_px[0]]: + graph.add_node(tuple(new_px)) + graph.add_edge(tuple(px), tuple(new_px), distance=np.linalg.norm(dir)) + + subgraph = nx.minimum_spanning_tree(graph.subgraph(max(nx.connected_components(graph), key=len))) + deg_1_nodes = [n for n, deg in subgraph.degree if deg == 1] + + downsampled = nx.Graph() + # Process the edges to form a downsampled graph + + node = deg_1_nodes[0] + downsampled.add_node(node) + path = [node] + for edge in nx.dfs_edges(subgraph): + node = path[-1] + if edge[0] == node: + path.append(edge[1]) + else: + path = [edge[0], edge[1]] + + if subgraph.degree(edge[1]) != 2: + downsampled.add_node(edge[1]) + downsampled.add_edge(path[0], path[-1], path=path) + path = [edge[1]] + + return downsampled + + def do_curve_search(self, graph, start_nodes, min_len=0, filter_mask=None, return_stats=False): + most_matches = 0 + best_curve = None + best_path = None + stats = {} + + for node in start_nodes: + + path_dict = {node: None} + def retrieve_path_pts(n): + edges = [] + path = [n] + while path_dict[n] is not None: + edges.append((path_dict[n], n)) + n = path_dict[n] + path.append(n) + edges = edges[::-1] + path = path[::-1] + + px_list = [] + for edge in edges: + px_path = graph.edges[edge]['path'] + if px_path[0] != edge[0]: + px_path = px_path[::-1] + px_list.extend(px_path) + + pts = np.array(px_list) + return path, pts + + for edge in nx.dfs_edges(graph, source=node): + path_dict[edge[1]] = edge[0] + node_path, pts = retrieve_path_pts(edge[1]) + if filter_mask is not None: + pts = pts[~filter_mask[pts[:,1], pts[:,0]]] + if not len(pts): + continue + cum_dists = np.zeros(pts.shape[0]) + offsets = np.linalg.norm(pts[1:] - pts[:-1], axis=1) + cum_dists[1:] = np.cumsum(offsets) + if cum_dists[-1] < min_len: + continue + + curve = Bezier.fit(pts, 3) + new_dists = curve.arclen * cum_dists / cum_dists[-1] + new_dists[-1] = curve.arclen + eval_bezier, _ = curve.eval_by_arclen(new_dists) + matched_pts = np.linalg.norm(pts - eval_bezier, axis=1) < self.outlier_threshold + matches = matched_pts.sum() + + if matches > most_matches: + most_matches = matches + best_curve = curve + best_path = node_path + stats = { + 'pts': pts, + 'matched_idx': matched_pts, + 'matches': matches, + 'consistency': matched_pts.mean(), + } + + if return_stats: + return best_curve, best_path, stats + + return best_curve, best_path + + def fit(self, vec=None, trim=30): + + if vec is None: + # Run SVD to find the most significant direction + pxs = np.fliplr(np.array(np.where(self.mask)).T) + pxs = pxs - pxs.mean(axis=0) + # SVD takes a lot of memory - we subsample points as we only need an estimate + pxs = pxs[np.random.choice(len(pxs), 100, replace=False)] + u, s, v = np.linalg.svd(pxs, full_matrices=True) + + vec = (0,1) + #vec = np.array(vec) / np.linalg.norm(vec) + # Iterate through the edges and use the vec to determine the orientation + + graph = self.construct_skeletal_graph(trim=trim) + directed_graph = nx.DiGraph() + directed_graph.add_nodes_from(graph.nodes) + + for p1, p2 in graph.edges: + path = graph.edges[p1, p2]['path'] + if np.dot(np.array(p2) - p1, vec) < 0: + p1, p2 = p2, p1 + if path[0] != p1: + path = path[::-1] + directed_graph.add_edge(p1, p2, path=path) + + start_nodes = [n for n in graph.nodes if directed_graph.out_degree(n) == 1 and directed_graph.in_degree(n) == 0] + best_curve, best_path, stats = self.do_curve_search(directed_graph, start_nodes, return_stats=True) + + self.subsampled_graph = graph + self.selected_path = best_path + self.selected_curve = best_curve + self.stats = stats + + return best_curve + + def run_side_branch_search(self, min_len=80, filter_mask=None, visualize=''): + if self.selected_path is None: + raise Exception('Please run the fit function first') + + graph = self.subsampled_graph + assert isinstance(graph, nx.Graph) + + # Subgraph pre-processing + main_path = self.selected_path + for edge in zip(main_path[:-1], main_path[1:]): + graph.remove_edge(*edge) + + candidate_edges = [] + to_remove = [] + for i, node in enumerate(main_path): + + for neighbor in graph[node]: + edge = (node, neighbor) + path = graph.edges[edge]['path'] + if path[0] != node: + path = path[::-1] # Orient the path from the main branch outwards + + to_remove.append(edge) + if 0 < i < len(main_path) - 1: + candidate_edges.append((edge, path)) + + graph.remove_edges_from(to_remove) + + side_branches = [] + stats = [] + for candidate_edge, path in candidate_edges: + graph.add_edge(*candidate_edge, path=path) + + best_curve, best_path, match_stats = self.do_curve_search(graph, start_nodes=[candidate_edge[0]], + min_len=min_len, filter_mask=filter_mask, + return_stats=True) + if best_curve is not None: + info = {'curve': best_curve, 'path': best_path, 'stats': match_stats} + side_branches.append(info) + if visualize: + stats.append(match_stats) + + graph.remove_edge(*candidate_edge) + + if visualize: + import cv2 + from PIL import Image + + base_img = np.dstack([self.mask * 255] * 3).astype(np.uint8) + ts = np.linspace(0, 1, 201) + eval_bezier = self.selected_curve(ts) + + cv2.polylines(base_img, [eval_bezier.reshape((-1, 1, 2)).astype(int)], False, (0, 0, 255), 4) + for info, stat in zip(side_branches, stats): + + curve = info['curve'] + eval_bezier = curve(ts) + msg = 'Matches: {}, {:.1f}%'.format(stat['matches'], stat['consistency'] * 100) + cv2.polylines(base_img, [eval_bezier.reshape((-1, 1, 2)).astype(int)], False, (0, 128, 0), 4) + draw_pt = eval_bezier[len(eval_bezier) // 2].astype(int) + text_size = cv2.getTextSize(msg, cv2.FONT_HERSHEY_SIMPLEX, 0.5, 2)[0] + if draw_pt[0] + text_size[0] > base_img.shape[1]: + draw_pt[0] -= text_size[1] + + cv2.putText(base_img, msg, draw_pt, cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 255), 2) + + Image.fromarray(base_img).save(visualize) + + return side_branches + + def get_radius_interpolator_on_path(self, path=None, min_quant=0.25, max_quant=0.75): + if self.dists is None: + raise Exception('Please run the medial axis transform before running this function') + + if path is None: + path = self.stats['pts'] + + radii = self.dists[path[:,1], path[:,0]].copy() + if 0 in radii: + raise Exception('Some pixels in the specified path were not part of the skeleton!') + q_min = np.quantile(radii, min_quant) + q_max = np.quantile(radii, max_quant) + min_bound = q_min - min_quant * (q_max - q_min) / (max_quant - min_quant) + max_bound = q_max + max_quant * (q_max - q_min) / (max_quant - min_quant) + radii[(radii < min_bound) | (radii > max_bound)] = np.median(radii) + + cum_dists = np.zeros(len(path)) + cum_dists[1:] = np.linalg.norm(path[1:] - path[:-1], axis=1).cumsum() + cum_dists /= cum_dists[-1] + + return interp1d(cum_dists, radii) + + + +class Bezier: + # https://stackoverflow.com/questions/12643079/b%c3%a9zier-curve-fitting-with-scipy + + def __init__(self, ctrl_pts, approx_eval=201): + self.pts = ctrl_pts + self.approx_eval = approx_eval + self._kd_tree = None + self._ts = None + + # Arc length-based interpolation tools + self._len_approx = None + self._dist_t_interpolator = None + self._t_dist_interpolator = None + + @property + def n(self): + return len(self.pts) + + @property + def deg(self): + return len(self.pts) - 1 + + @staticmethod + def bpoly(i, n, t): + return comb(n, i) * t ** (n-i) * (1 - t) ** i + + def __call__(self, t): + t = np.array(t) + polys = [self.bpoly(i, self.deg, t)[..., np.newaxis] * pt for i, pt in enumerate(self.pts)] + return np.sum(polys, axis=0) + + def _load_arclen_tools(self): + if self._len_approx is not None: + return + ts_approx = np.linspace(0, 1, self.approx_eval) + eval_pts = self(ts_approx) + cum_dists = np.zeros(self.approx_eval) + cum_dists[1:] = np.linalg.norm(eval_pts[:-1] - eval_pts[1:], axis=1).cumsum() + self._len_approx = cum_dists[-1] + + self._dist_t_interpolator = interp1d(cum_dists, ts_approx) + self._t_dist_interpolator = interp1d(ts_approx, cum_dists) + + @property + def arclen(self): + self._load_arclen_tools() + return self._len_approx + + def eval_by_arclen(self, dists, normalized=False): + # Evaluates the curve, but with the ts parametrized by the distance along the curve (using an approximation) + self._load_arclen_tools() + if normalized: + dists = np.array(dists) * self.arclen + ts = self._dist_t_interpolator(dists) + return self(ts), ts + + def t_to_curve_dist(self, ts): + self._load_arclen_tools() + return self._t_dist_interpolator(ts) + + def tangent(self, t): + t = np.array(t) + polys = [self.deg * self.bpoly(i, self.deg - 1, t)[..., np.newaxis] * (p2 - p1) + for i, (p1, p2) in enumerate(zip(self.pts[:-1], self.pts[1:]))] + return -np.sum(polys, axis=0) + + def visualize(self, other_pts=None): + eval_pts = self(np.linspace(0, 1, 100)) + if other_pts is not None: + plt.scatter(*other_pts.T, color='grey', marker='x', s=3) + plt.scatter(*self.pts.T, color='red', marker='*', s=10) + plt.scatter(*eval_pts.T, color='blue', s=5) + plt.show() + + @classmethod + def fit(cls, pts, degree=3): + # Assumes pts[0] and pts[-1] represent the respective endpoints of the Bezier curve + n = len(pts) + t = np.linspace(0, 1, n) + b_mat = np.array([cls.bpoly(i, degree, t) for i in range(degree+1)]).T + fit = np.linalg.pinv(b_mat) @ pts + return cls(fit) + + @classmethod + def iterative_fit(cls, pts, degree=3, inlier_threshold=0.05, resample_p=0.5, exclude_furthest=0.10, + max_iters=10, stop_threshold=0.75): + """ + Attempts to fit a Bezier curve to noisy data by with a RANSAC-like approach. + Iteratively estimates a model, identifies inliers, and reestimates the model until the desired number of + inliers has been met. + inlier_threshold: Distance from point to curve to be considered an inlier + resample_p: Proportion of points that are resampled to fit a new model + exclude_furthest: This proportion of points furthest from the current model will not be considered for model fitting + stop_threshold: Process terminates once this proportion of inliers has been met + """ + + stats = { + 'success': False, + 'iters': 0, + 'inliers': 0, + 'inlier_idx': [], + 'init_inliers': 0, + } + + current_model = cls.fit(pts, degree=degree) + best_model = None + best_inlier_p = 0.0 + + for i in range(max_iters): + stats['iters'] += 1 + dists, _ = current_model.query_pt_distance(pts) + inliers = dists < inlier_threshold + inlier_p = inliers.mean() + stats['inliers'] = inlier_p + if i == 0: + stats['init_inliers'] = inlier_p + + if inlier_p > best_inlier_p: + best_model = current_model + best_inlier_p = inlier_p + stats['inlier_idx'] = inliers + + if inlier_p >= stop_threshold: + stats['success'] = True + return current_model, stats + + # Using the current model, exclude the furthest points and subsample a new selection of points + eligible = np.argsort(dists)[:int((1-exclude_furthest) * len(pts))] + to_sample = np.random.choice(eligible, int(resample_p * len(pts)), replace=False) + to_use = np.zeros(len(pts), dtype=bool) + to_use[0] = to_use[-1] = True + to_use[to_sample] = True + current_model = cls.fit(pts[to_use]) + + print('Warning: Iterative fit maxed out!') + return best_model, stats + + def query_pt_distance(self, pts): + + if self._kd_tree is None: + self._ts = np.linspace(0, 1, self.approx_eval, endpoint=True) + curve_eval = self(self._ts) + self._kd_tree = KDTree(curve_eval) + + dists, idxs = self._kd_tree.query(pts) + return dists, self._ts[idxs] + + +# TESTS +def side_branch_test(): + from PIL import Image + import cv2 + + + proc_dir = os.path.join(os.path.expanduser('~'), 'Pictures', 'masks') + output_dir = os.path.join(proc_dir, 'outputs') + files = [x for x in os.listdir(proc_dir) if x.endswith('.png')] + + for file in files: + input_file = os.path.join(proc_dir, file) + output_file = os.path.join(output_dir, file) + img = np.array(Image.open(input_file))[:, :, :3].copy() + mask = img.mean(axis=2) > 128 + + detection = BezierBasedDetection(mask, outlier_threshold=6, use_medial_axis=True) + curve = detection.fit(vec=(0, -1)) + if curve is None: + continue + + radius_interpolator = detection.get_radius_interpolator_on_path() + detection.run_side_branch_search(visualize=output_file, min_len=40, radius_interpolator=radius_interpolator) + + +def ransac_fit_test(): + + import matplotlib.pyplot as plt + import time + + for _ in range(100): + rand_pts = np.random.uniform(-1, 1, (4,3)) + curve = Bezier(rand_pts) + num_ts = np.random.randint(10, 50) + ts = np.random.uniform(0, 1, num_ts) + ts.sort() + + vals = curve(ts) + np.random.uniform(-0.01, 0.01, (num_ts, 3)) + + super_noisy_pts = int(np.random.uniform(0.1, 0.2) * num_ts) + idxs_to_modify = np.random.choice(num_ts - 2, super_noisy_pts, replace=False) + 1 # Don't modify the start/end points + vals[idxs_to_modify] += np.random.uniform(-2.0, 2.0, (super_noisy_pts, 3)) + + start = time.time() + fit_curve, stats = Bezier.iterative_fit(vals, max_iters=100) + end = time.time() + + print('Fit of {} points took {:.3f}s ({} iters)'.format(num_ts, end-start, stats['iters'])) + print('Percent inliers: {:.2f}% (init {:.2f}%)'.format(stats['inliers'] * 100, stats['init_inliers'] * 100)) + + ax = plt.figure().add_subplot(projection='3d') + + ts = np.linspace(0, 1, 51) + real_pts = curve(ts) + est_pts = fit_curve(ts) + naive_pts = Bezier.fit(vals)(ts) + + ax.plot(*real_pts.T, color='green', linestyle='dashed') + ax.plot(*est_pts.T, color='blue') + ax.plot(*naive_pts.T, color='red', linestyle='dotted') + ax.scatter(*vals[stats['inlier_idx']].T, color='green') + ax.scatter(*vals[~stats['inlier_idx']].T, color='red') + + plt.show() diff --git a/marshall/follower_mask.png b/marshall/follower_mask.png new file mode 100644 index 0000000..727cdc2 Binary files /dev/null and b/marshall/follower_mask.png differ diff --git a/marshall/generated.png b/marshall/generated.png new file mode 100644 index 0000000..a2edaf7 Binary files /dev/null and b/marshall/generated.png differ diff --git a/marshall/generated_tree.png b/marshall/generated_tree.png new file mode 100644 index 0000000..79a810a Binary files /dev/null and b/marshall/generated_tree.png differ diff --git a/marshall/install/.colcon_install_layout b/marshall/install/.colcon_install_layout new file mode 100644 index 0000000..3aad533 --- /dev/null +++ b/marshall/install/.colcon_install_layout @@ -0,0 +1 @@ +isolated diff --git a/marshall/install/COLCON_IGNORE b/marshall/install/COLCON_IGNORE new file mode 100644 index 0000000..e69de29 diff --git a/marshall/install/_local_setup_util_ps1.py b/marshall/install/_local_setup_util_ps1.py new file mode 100644 index 0000000..98348ee --- /dev/null +++ b/marshall/install/_local_setup_util_ps1.py @@ -0,0 +1,404 @@ +# Copyright 2016-2019 Dirk Thomas +# Licensed under the Apache License, Version 2.0 + +import argparse +from collections import OrderedDict +import os +from pathlib import Path +import sys + + +FORMAT_STR_COMMENT_LINE = '# {comment}' +FORMAT_STR_SET_ENV_VAR = 'Set-Item -Path "Env:{name}" -Value "{value}"' +FORMAT_STR_USE_ENV_VAR = '$env:{name}' +FORMAT_STR_INVOKE_SCRIPT = '_colcon_prefix_powershell_source_script "{script_path}"' +FORMAT_STR_REMOVE_LEADING_SEPARATOR = '' +FORMAT_STR_REMOVE_TRAILING_SEPARATOR = '' + +DSV_TYPE_APPEND_NON_DUPLICATE = 'append-non-duplicate' +DSV_TYPE_PREPEND_NON_DUPLICATE = 'prepend-non-duplicate' +DSV_TYPE_PREPEND_NON_DUPLICATE_IF_EXISTS = 'prepend-non-duplicate-if-exists' +DSV_TYPE_SET = 'set' +DSV_TYPE_SET_IF_UNSET = 'set-if-unset' +DSV_TYPE_SOURCE = 'source' + + +def main(argv=sys.argv[1:]): # noqa: D103 + parser = argparse.ArgumentParser( + description='Output shell commands for the packages in topological ' + 'order') + parser.add_argument( + 'primary_extension', + help='The file extension of the primary shell') + parser.add_argument( + 'additional_extension', nargs='?', + help='The additional file extension to be considered') + parser.add_argument( + '--merged-install', action='store_true', + help='All install prefixes are merged into a single location') + args = parser.parse_args(argv) + + packages = get_packages(Path(__file__).parent, args.merged_install) + + ordered_packages = order_packages(packages) + for pkg_name in ordered_packages: + if _include_comments(): + print( + FORMAT_STR_COMMENT_LINE.format_map( + {'comment': 'Package: ' + pkg_name})) + prefix = os.path.abspath(os.path.dirname(__file__)) + if not args.merged_install: + prefix = os.path.join(prefix, pkg_name) + for line in get_commands( + pkg_name, prefix, args.primary_extension, + args.additional_extension + ): + print(line) + + for line in _remove_ending_separators(): + print(line) + + +def get_packages(prefix_path, merged_install): + """ + Find packages based on colcon-specific files created during installation. + + :param Path prefix_path: The install prefix path of all packages + :param bool merged_install: The flag if the packages are all installed + directly in the prefix or if each package is installed in a subdirectory + named after the package + :returns: A mapping from the package name to the set of runtime + dependencies + :rtype: dict + """ + packages = {} + # since importing colcon_core isn't feasible here the following constant + # must match colcon_core.location.get_relative_package_index_path() + subdirectory = 'share/colcon-core/packages' + if merged_install: + # return if workspace is empty + if not (prefix_path / subdirectory).is_dir(): + return packages + # find all files in the subdirectory + for p in (prefix_path / subdirectory).iterdir(): + if not p.is_file(): + continue + if p.name.startswith('.'): + continue + add_package_runtime_dependencies(p, packages) + else: + # for each subdirectory look for the package specific file + for p in prefix_path.iterdir(): + if not p.is_dir(): + continue + if p.name.startswith('.'): + continue + p = p / subdirectory / p.name + if p.is_file(): + add_package_runtime_dependencies(p, packages) + + # remove unknown dependencies + pkg_names = set(packages.keys()) + for k in packages.keys(): + packages[k] = {d for d in packages[k] if d in pkg_names} + + return packages + + +def add_package_runtime_dependencies(path, packages): + """ + Check the path and if it exists extract the packages runtime dependencies. + + :param Path path: The resource file containing the runtime dependencies + :param dict packages: A mapping from package names to the sets of runtime + dependencies to add to + """ + content = path.read_text() + dependencies = set(content.split(os.pathsep) if content else []) + packages[path.name] = dependencies + + +def order_packages(packages): + """ + Order packages topologically. + + :param dict packages: A mapping from package name to the set of runtime + dependencies + :returns: The package names + :rtype: list + """ + # select packages with no dependencies in alphabetical order + to_be_ordered = list(packages.keys()) + ordered = [] + while to_be_ordered: + pkg_names_without_deps = [ + name for name in to_be_ordered if not packages[name]] + if not pkg_names_without_deps: + reduce_cycle_set(packages) + raise RuntimeError( + 'Circular dependency between: ' + ', '.join(sorted(packages))) + pkg_names_without_deps.sort() + pkg_name = pkg_names_without_deps[0] + to_be_ordered.remove(pkg_name) + ordered.append(pkg_name) + # remove item from dependency lists + for k in list(packages.keys()): + if pkg_name in packages[k]: + packages[k].remove(pkg_name) + return ordered + + +def reduce_cycle_set(packages): + """ + Reduce the set of packages to the ones part of the circular dependency. + + :param dict packages: A mapping from package name to the set of runtime + dependencies which is modified in place + """ + last_depended = None + while len(packages) > 0: + # get all remaining dependencies + depended = set() + for pkg_name, dependencies in packages.items(): + depended = depended.union(dependencies) + # remove all packages which are not dependent on + for name in list(packages.keys()): + if name not in depended: + del packages[name] + if last_depended: + # if remaining packages haven't changed return them + if last_depended == depended: + return packages.keys() + # otherwise reduce again + last_depended = depended + + +def _include_comments(): + # skipping comment lines when COLCON_TRACE is not set speeds up the + # processing especially on Windows + return bool(os.environ.get('COLCON_TRACE')) + + +def get_commands(pkg_name, prefix, primary_extension, additional_extension): + commands = [] + package_dsv_path = os.path.join(prefix, 'share', pkg_name, 'package.dsv') + if os.path.exists(package_dsv_path): + commands += process_dsv_file( + package_dsv_path, prefix, primary_extension, additional_extension) + return commands + + +def process_dsv_file( + dsv_path, prefix, primary_extension=None, additional_extension=None +): + commands = [] + if _include_comments(): + commands.append(FORMAT_STR_COMMENT_LINE.format_map({'comment': dsv_path})) + with open(dsv_path, 'r') as h: + content = h.read() + lines = content.splitlines() + + basenames = OrderedDict() + for i, line in enumerate(lines): + # skip over empty or whitespace-only lines + if not line.strip(): + continue + try: + type_, remainder = line.split(';', 1) + except ValueError: + raise RuntimeError( + "Line %d in '%s' doesn't contain a semicolon separating the " + 'type from the arguments' % (i + 1, dsv_path)) + if type_ != DSV_TYPE_SOURCE: + # handle non-source lines + try: + commands += handle_dsv_types_except_source( + type_, remainder, prefix) + except RuntimeError as e: + raise RuntimeError( + "Line %d in '%s' %s" % (i + 1, dsv_path, e)) from e + else: + # group remaining source lines by basename + path_without_ext, ext = os.path.splitext(remainder) + if path_without_ext not in basenames: + basenames[path_without_ext] = set() + assert ext.startswith('.') + ext = ext[1:] + if ext in (primary_extension, additional_extension): + basenames[path_without_ext].add(ext) + + # add the dsv extension to each basename if the file exists + for basename, extensions in basenames.items(): + if not os.path.isabs(basename): + basename = os.path.join(prefix, basename) + if os.path.exists(basename + '.dsv'): + extensions.add('dsv') + + for basename, extensions in basenames.items(): + if not os.path.isabs(basename): + basename = os.path.join(prefix, basename) + if 'dsv' in extensions: + # process dsv files recursively + commands += process_dsv_file( + basename + '.dsv', prefix, primary_extension=primary_extension, + additional_extension=additional_extension) + elif primary_extension in extensions and len(extensions) == 1: + # source primary-only files + commands += [ + FORMAT_STR_INVOKE_SCRIPT.format_map({ + 'prefix': prefix, + 'script_path': basename + '.' + primary_extension})] + elif additional_extension in extensions: + # source non-primary files + commands += [ + FORMAT_STR_INVOKE_SCRIPT.format_map({ + 'prefix': prefix, + 'script_path': basename + '.' + additional_extension})] + + return commands + + +def handle_dsv_types_except_source(type_, remainder, prefix): + commands = [] + if type_ in (DSV_TYPE_SET, DSV_TYPE_SET_IF_UNSET): + try: + env_name, value = remainder.split(';', 1) + except ValueError: + raise RuntimeError( + "doesn't contain a semicolon separating the environment name " + 'from the value') + try_prefixed_value = os.path.join(prefix, value) if value else prefix + if os.path.exists(try_prefixed_value): + value = try_prefixed_value + if type_ == DSV_TYPE_SET: + commands += _set(env_name, value) + elif type_ == DSV_TYPE_SET_IF_UNSET: + commands += _set_if_unset(env_name, value) + else: + assert False + elif type_ in ( + DSV_TYPE_APPEND_NON_DUPLICATE, + DSV_TYPE_PREPEND_NON_DUPLICATE, + DSV_TYPE_PREPEND_NON_DUPLICATE_IF_EXISTS + ): + try: + env_name_and_values = remainder.split(';') + except ValueError: + raise RuntimeError( + "doesn't contain a semicolon separating the environment name " + 'from the values') + env_name = env_name_and_values[0] + values = env_name_and_values[1:] + for value in values: + if not value: + value = prefix + elif not os.path.isabs(value): + value = os.path.join(prefix, value) + if ( + type_ == DSV_TYPE_PREPEND_NON_DUPLICATE_IF_EXISTS and + not os.path.exists(value) + ): + comment = f'skip extending {env_name} with not existing ' \ + f'path: {value}' + if _include_comments(): + commands.append( + FORMAT_STR_COMMENT_LINE.format_map({'comment': comment})) + elif type_ == DSV_TYPE_APPEND_NON_DUPLICATE: + commands += _append_unique_value(env_name, value) + else: + commands += _prepend_unique_value(env_name, value) + else: + raise RuntimeError( + 'contains an unknown environment hook type: ' + type_) + return commands + + +env_state = {} + + +def _append_unique_value(name, value): + global env_state + if name not in env_state: + if os.environ.get(name): + env_state[name] = set(os.environ[name].split(os.pathsep)) + else: + env_state[name] = set() + # append even if the variable has not been set yet, in case a shell script sets the + # same variable without the knowledge of this Python script. + # later _remove_ending_separators() will cleanup any unintentional leading separator + extend = FORMAT_STR_USE_ENV_VAR.format_map({'name': name}) + os.pathsep + line = FORMAT_STR_SET_ENV_VAR.format_map( + {'name': name, 'value': extend + value}) + if value not in env_state[name]: + env_state[name].add(value) + else: + if not _include_comments(): + return [] + line = FORMAT_STR_COMMENT_LINE.format_map({'comment': line}) + return [line] + + +def _prepend_unique_value(name, value): + global env_state + if name not in env_state: + if os.environ.get(name): + env_state[name] = set(os.environ[name].split(os.pathsep)) + else: + env_state[name] = set() + # prepend even if the variable has not been set yet, in case a shell script sets the + # same variable without the knowledge of this Python script. + # later _remove_ending_separators() will cleanup any unintentional trailing separator + extend = os.pathsep + FORMAT_STR_USE_ENV_VAR.format_map({'name': name}) + line = FORMAT_STR_SET_ENV_VAR.format_map( + {'name': name, 'value': value + extend}) + if value not in env_state[name]: + env_state[name].add(value) + else: + if not _include_comments(): + return [] + line = FORMAT_STR_COMMENT_LINE.format_map({'comment': line}) + return [line] + + +# generate commands for removing prepended underscores +def _remove_ending_separators(): + # do nothing if the shell extension does not implement the logic + if FORMAT_STR_REMOVE_TRAILING_SEPARATOR is None: + return [] + + global env_state + commands = [] + for name in env_state: + # skip variables that already had values before this script started prepending + if name in os.environ: + continue + commands += [ + FORMAT_STR_REMOVE_LEADING_SEPARATOR.format_map({'name': name}), + FORMAT_STR_REMOVE_TRAILING_SEPARATOR.format_map({'name': name})] + return commands + + +def _set(name, value): + global env_state + env_state[name] = value + line = FORMAT_STR_SET_ENV_VAR.format_map( + {'name': name, 'value': value}) + return [line] + + +def _set_if_unset(name, value): + global env_state + line = FORMAT_STR_SET_ENV_VAR.format_map( + {'name': name, 'value': value}) + if env_state.get(name, os.environ.get(name)): + line = FORMAT_STR_COMMENT_LINE.format_map({'comment': line}) + return [line] + + +if __name__ == '__main__': # pragma: no cover + try: + rc = main() + except RuntimeError as e: + print(str(e), file=sys.stderr) + rc = 1 + sys.exit(rc) diff --git a/marshall/install/_local_setup_util_sh.py b/marshall/install/_local_setup_util_sh.py new file mode 100644 index 0000000..35c017b --- /dev/null +++ b/marshall/install/_local_setup_util_sh.py @@ -0,0 +1,404 @@ +# Copyright 2016-2019 Dirk Thomas +# Licensed under the Apache License, Version 2.0 + +import argparse +from collections import OrderedDict +import os +from pathlib import Path +import sys + + +FORMAT_STR_COMMENT_LINE = '# {comment}' +FORMAT_STR_SET_ENV_VAR = 'export {name}="{value}"' +FORMAT_STR_USE_ENV_VAR = '${name}' +FORMAT_STR_INVOKE_SCRIPT = 'COLCON_CURRENT_PREFIX="{prefix}" _colcon_prefix_sh_source_script "{script_path}"' +FORMAT_STR_REMOVE_LEADING_SEPARATOR = 'if [ "$(echo -n ${name} | head -c 1)" = ":" ]; then export {name}=${{{name}#?}} ; fi' +FORMAT_STR_REMOVE_TRAILING_SEPARATOR = 'if [ "$(echo -n ${name} | tail -c 1)" = ":" ]; then export {name}=${{{name}%?}} ; fi' + +DSV_TYPE_APPEND_NON_DUPLICATE = 'append-non-duplicate' +DSV_TYPE_PREPEND_NON_DUPLICATE = 'prepend-non-duplicate' +DSV_TYPE_PREPEND_NON_DUPLICATE_IF_EXISTS = 'prepend-non-duplicate-if-exists' +DSV_TYPE_SET = 'set' +DSV_TYPE_SET_IF_UNSET = 'set-if-unset' +DSV_TYPE_SOURCE = 'source' + + +def main(argv=sys.argv[1:]): # noqa: D103 + parser = argparse.ArgumentParser( + description='Output shell commands for the packages in topological ' + 'order') + parser.add_argument( + 'primary_extension', + help='The file extension of the primary shell') + parser.add_argument( + 'additional_extension', nargs='?', + help='The additional file extension to be considered') + parser.add_argument( + '--merged-install', action='store_true', + help='All install prefixes are merged into a single location') + args = parser.parse_args(argv) + + packages = get_packages(Path(__file__).parent, args.merged_install) + + ordered_packages = order_packages(packages) + for pkg_name in ordered_packages: + if _include_comments(): + print( + FORMAT_STR_COMMENT_LINE.format_map( + {'comment': 'Package: ' + pkg_name})) + prefix = os.path.abspath(os.path.dirname(__file__)) + if not args.merged_install: + prefix = os.path.join(prefix, pkg_name) + for line in get_commands( + pkg_name, prefix, args.primary_extension, + args.additional_extension + ): + print(line) + + for line in _remove_ending_separators(): + print(line) + + +def get_packages(prefix_path, merged_install): + """ + Find packages based on colcon-specific files created during installation. + + :param Path prefix_path: The install prefix path of all packages + :param bool merged_install: The flag if the packages are all installed + directly in the prefix or if each package is installed in a subdirectory + named after the package + :returns: A mapping from the package name to the set of runtime + dependencies + :rtype: dict + """ + packages = {} + # since importing colcon_core isn't feasible here the following constant + # must match colcon_core.location.get_relative_package_index_path() + subdirectory = 'share/colcon-core/packages' + if merged_install: + # return if workspace is empty + if not (prefix_path / subdirectory).is_dir(): + return packages + # find all files in the subdirectory + for p in (prefix_path / subdirectory).iterdir(): + if not p.is_file(): + continue + if p.name.startswith('.'): + continue + add_package_runtime_dependencies(p, packages) + else: + # for each subdirectory look for the package specific file + for p in prefix_path.iterdir(): + if not p.is_dir(): + continue + if p.name.startswith('.'): + continue + p = p / subdirectory / p.name + if p.is_file(): + add_package_runtime_dependencies(p, packages) + + # remove unknown dependencies + pkg_names = set(packages.keys()) + for k in packages.keys(): + packages[k] = {d for d in packages[k] if d in pkg_names} + + return packages + + +def add_package_runtime_dependencies(path, packages): + """ + Check the path and if it exists extract the packages runtime dependencies. + + :param Path path: The resource file containing the runtime dependencies + :param dict packages: A mapping from package names to the sets of runtime + dependencies to add to + """ + content = path.read_text() + dependencies = set(content.split(os.pathsep) if content else []) + packages[path.name] = dependencies + + +def order_packages(packages): + """ + Order packages topologically. + + :param dict packages: A mapping from package name to the set of runtime + dependencies + :returns: The package names + :rtype: list + """ + # select packages with no dependencies in alphabetical order + to_be_ordered = list(packages.keys()) + ordered = [] + while to_be_ordered: + pkg_names_without_deps = [ + name for name in to_be_ordered if not packages[name]] + if not pkg_names_without_deps: + reduce_cycle_set(packages) + raise RuntimeError( + 'Circular dependency between: ' + ', '.join(sorted(packages))) + pkg_names_without_deps.sort() + pkg_name = pkg_names_without_deps[0] + to_be_ordered.remove(pkg_name) + ordered.append(pkg_name) + # remove item from dependency lists + for k in list(packages.keys()): + if pkg_name in packages[k]: + packages[k].remove(pkg_name) + return ordered + + +def reduce_cycle_set(packages): + """ + Reduce the set of packages to the ones part of the circular dependency. + + :param dict packages: A mapping from package name to the set of runtime + dependencies which is modified in place + """ + last_depended = None + while len(packages) > 0: + # get all remaining dependencies + depended = set() + for pkg_name, dependencies in packages.items(): + depended = depended.union(dependencies) + # remove all packages which are not dependent on + for name in list(packages.keys()): + if name not in depended: + del packages[name] + if last_depended: + # if remaining packages haven't changed return them + if last_depended == depended: + return packages.keys() + # otherwise reduce again + last_depended = depended + + +def _include_comments(): + # skipping comment lines when COLCON_TRACE is not set speeds up the + # processing especially on Windows + return bool(os.environ.get('COLCON_TRACE')) + + +def get_commands(pkg_name, prefix, primary_extension, additional_extension): + commands = [] + package_dsv_path = os.path.join(prefix, 'share', pkg_name, 'package.dsv') + if os.path.exists(package_dsv_path): + commands += process_dsv_file( + package_dsv_path, prefix, primary_extension, additional_extension) + return commands + + +def process_dsv_file( + dsv_path, prefix, primary_extension=None, additional_extension=None +): + commands = [] + if _include_comments(): + commands.append(FORMAT_STR_COMMENT_LINE.format_map({'comment': dsv_path})) + with open(dsv_path, 'r') as h: + content = h.read() + lines = content.splitlines() + + basenames = OrderedDict() + for i, line in enumerate(lines): + # skip over empty or whitespace-only lines + if not line.strip(): + continue + try: + type_, remainder = line.split(';', 1) + except ValueError: + raise RuntimeError( + "Line %d in '%s' doesn't contain a semicolon separating the " + 'type from the arguments' % (i + 1, dsv_path)) + if type_ != DSV_TYPE_SOURCE: + # handle non-source lines + try: + commands += handle_dsv_types_except_source( + type_, remainder, prefix) + except RuntimeError as e: + raise RuntimeError( + "Line %d in '%s' %s" % (i + 1, dsv_path, e)) from e + else: + # group remaining source lines by basename + path_without_ext, ext = os.path.splitext(remainder) + if path_without_ext not in basenames: + basenames[path_without_ext] = set() + assert ext.startswith('.') + ext = ext[1:] + if ext in (primary_extension, additional_extension): + basenames[path_without_ext].add(ext) + + # add the dsv extension to each basename if the file exists + for basename, extensions in basenames.items(): + if not os.path.isabs(basename): + basename = os.path.join(prefix, basename) + if os.path.exists(basename + '.dsv'): + extensions.add('dsv') + + for basename, extensions in basenames.items(): + if not os.path.isabs(basename): + basename = os.path.join(prefix, basename) + if 'dsv' in extensions: + # process dsv files recursively + commands += process_dsv_file( + basename + '.dsv', prefix, primary_extension=primary_extension, + additional_extension=additional_extension) + elif primary_extension in extensions and len(extensions) == 1: + # source primary-only files + commands += [ + FORMAT_STR_INVOKE_SCRIPT.format_map({ + 'prefix': prefix, + 'script_path': basename + '.' + primary_extension})] + elif additional_extension in extensions: + # source non-primary files + commands += [ + FORMAT_STR_INVOKE_SCRIPT.format_map({ + 'prefix': prefix, + 'script_path': basename + '.' + additional_extension})] + + return commands + + +def handle_dsv_types_except_source(type_, remainder, prefix): + commands = [] + if type_ in (DSV_TYPE_SET, DSV_TYPE_SET_IF_UNSET): + try: + env_name, value = remainder.split(';', 1) + except ValueError: + raise RuntimeError( + "doesn't contain a semicolon separating the environment name " + 'from the value') + try_prefixed_value = os.path.join(prefix, value) if value else prefix + if os.path.exists(try_prefixed_value): + value = try_prefixed_value + if type_ == DSV_TYPE_SET: + commands += _set(env_name, value) + elif type_ == DSV_TYPE_SET_IF_UNSET: + commands += _set_if_unset(env_name, value) + else: + assert False + elif type_ in ( + DSV_TYPE_APPEND_NON_DUPLICATE, + DSV_TYPE_PREPEND_NON_DUPLICATE, + DSV_TYPE_PREPEND_NON_DUPLICATE_IF_EXISTS + ): + try: + env_name_and_values = remainder.split(';') + except ValueError: + raise RuntimeError( + "doesn't contain a semicolon separating the environment name " + 'from the values') + env_name = env_name_and_values[0] + values = env_name_and_values[1:] + for value in values: + if not value: + value = prefix + elif not os.path.isabs(value): + value = os.path.join(prefix, value) + if ( + type_ == DSV_TYPE_PREPEND_NON_DUPLICATE_IF_EXISTS and + not os.path.exists(value) + ): + comment = f'skip extending {env_name} with not existing ' \ + f'path: {value}' + if _include_comments(): + commands.append( + FORMAT_STR_COMMENT_LINE.format_map({'comment': comment})) + elif type_ == DSV_TYPE_APPEND_NON_DUPLICATE: + commands += _append_unique_value(env_name, value) + else: + commands += _prepend_unique_value(env_name, value) + else: + raise RuntimeError( + 'contains an unknown environment hook type: ' + type_) + return commands + + +env_state = {} + + +def _append_unique_value(name, value): + global env_state + if name not in env_state: + if os.environ.get(name): + env_state[name] = set(os.environ[name].split(os.pathsep)) + else: + env_state[name] = set() + # append even if the variable has not been set yet, in case a shell script sets the + # same variable without the knowledge of this Python script. + # later _remove_ending_separators() will cleanup any unintentional leading separator + extend = FORMAT_STR_USE_ENV_VAR.format_map({'name': name}) + os.pathsep + line = FORMAT_STR_SET_ENV_VAR.format_map( + {'name': name, 'value': extend + value}) + if value not in env_state[name]: + env_state[name].add(value) + else: + if not _include_comments(): + return [] + line = FORMAT_STR_COMMENT_LINE.format_map({'comment': line}) + return [line] + + +def _prepend_unique_value(name, value): + global env_state + if name not in env_state: + if os.environ.get(name): + env_state[name] = set(os.environ[name].split(os.pathsep)) + else: + env_state[name] = set() + # prepend even if the variable has not been set yet, in case a shell script sets the + # same variable without the knowledge of this Python script. + # later _remove_ending_separators() will cleanup any unintentional trailing separator + extend = os.pathsep + FORMAT_STR_USE_ENV_VAR.format_map({'name': name}) + line = FORMAT_STR_SET_ENV_VAR.format_map( + {'name': name, 'value': value + extend}) + if value not in env_state[name]: + env_state[name].add(value) + else: + if not _include_comments(): + return [] + line = FORMAT_STR_COMMENT_LINE.format_map({'comment': line}) + return [line] + + +# generate commands for removing prepended underscores +def _remove_ending_separators(): + # do nothing if the shell extension does not implement the logic + if FORMAT_STR_REMOVE_TRAILING_SEPARATOR is None: + return [] + + global env_state + commands = [] + for name in env_state: + # skip variables that already had values before this script started prepending + if name in os.environ: + continue + commands += [ + FORMAT_STR_REMOVE_LEADING_SEPARATOR.format_map({'name': name}), + FORMAT_STR_REMOVE_TRAILING_SEPARATOR.format_map({'name': name})] + return commands + + +def _set(name, value): + global env_state + env_state[name] = value + line = FORMAT_STR_SET_ENV_VAR.format_map( + {'name': name, 'value': value}) + return [line] + + +def _set_if_unset(name, value): + global env_state + line = FORMAT_STR_SET_ENV_VAR.format_map( + {'name': name, 'value': value}) + if env_state.get(name, os.environ.get(name)): + line = FORMAT_STR_COMMENT_LINE.format_map({'comment': line}) + return [line] + + +if __name__ == '__main__': # pragma: no cover + try: + rc = main() + except RuntimeError as e: + print(str(e), file=sys.stderr) + rc = 1 + sys.exit(rc) diff --git a/marshall/install/local_setup.bash b/marshall/install/local_setup.bash new file mode 100644 index 0000000..efd5f8c --- /dev/null +++ b/marshall/install/local_setup.bash @@ -0,0 +1,107 @@ +# generated from colcon_bash/shell/template/prefix.bash.em + +# This script extends the environment with all packages contained in this +# prefix path. + +# a bash script is able to determine its own path if necessary +if [ -z "$COLCON_CURRENT_PREFIX" ]; then + _colcon_prefix_bash_COLCON_CURRENT_PREFIX="$(builtin cd "`dirname "${BASH_SOURCE[0]}"`" > /dev/null && pwd)" +else + _colcon_prefix_bash_COLCON_CURRENT_PREFIX="$COLCON_CURRENT_PREFIX" +fi + +# function to prepend a value to a variable +# which uses colons as separators +# duplicates as well as trailing separators are avoided +# first argument: the name of the result variable +# second argument: the value to be prepended +_colcon_prefix_bash_prepend_unique_value() { + # arguments + _listname="$1" + _value="$2" + + # get values from variable + eval _values=\"\$$_listname\" + # backup the field separator + _colcon_prefix_bash_prepend_unique_value_IFS="$IFS" + IFS=":" + # start with the new value + _all_values="$_value" + # iterate over existing values in the variable + for _item in $_values; do + # ignore empty strings + if [ -z "$_item" ]; then + continue + fi + # ignore duplicates of _value + if [ "$_item" = "$_value" ]; then + continue + fi + # keep non-duplicate values + _all_values="$_all_values:$_item" + done + unset _item + # restore the field separator + IFS="$_colcon_prefix_bash_prepend_unique_value_IFS" + unset _colcon_prefix_bash_prepend_unique_value_IFS + # export the updated variable + eval export $_listname=\"$_all_values\" + unset _all_values + unset _values + + unset _value + unset _listname +} + +# add this prefix to the COLCON_PREFIX_PATH +_colcon_prefix_bash_prepend_unique_value COLCON_PREFIX_PATH "$_colcon_prefix_bash_COLCON_CURRENT_PREFIX" +unset _colcon_prefix_bash_prepend_unique_value + +# check environment variable for custom Python executable +if [ -n "$COLCON_PYTHON_EXECUTABLE" ]; then + if [ ! -f "$COLCON_PYTHON_EXECUTABLE" ]; then + echo "error: COLCON_PYTHON_EXECUTABLE '$COLCON_PYTHON_EXECUTABLE' doesn't exist" + return 1 + fi + _colcon_python_executable="$COLCON_PYTHON_EXECUTABLE" +else + # try the Python executable known at configure time + _colcon_python_executable="/usr/bin/python3" + # if it doesn't exist try a fall back + if [ ! -f "$_colcon_python_executable" ]; then + if ! /usr/bin/env python3 --version > /dev/null 2> /dev/null; then + echo "error: unable to find python3 executable" + return 1 + fi + _colcon_python_executable=`/usr/bin/env python3 -c "import sys; print(sys.executable)"` + fi +fi + +# function to source another script with conditional trace output +# first argument: the path of the script +_colcon_prefix_sh_source_script() { + if [ -f "$1" ]; then + if [ -n "$COLCON_TRACE" ]; then + echo ". \"$1\"" + fi + . "$1" + else + echo "not found: \"$1\"" 1>&2 + fi +} + +# get all commands in topological order +_colcon_ordered_commands="$($_colcon_python_executable "$_colcon_prefix_bash_COLCON_CURRENT_PREFIX/_local_setup_util_sh.py" sh bash)" +unset _colcon_python_executable +if [ -n "$COLCON_TRACE" ]; then + echo "Execute generated script:" + echo "<<<" + echo "${_colcon_ordered_commands}" + echo ">>>" +fi +eval "${_colcon_ordered_commands}" +unset _colcon_ordered_commands + +unset _colcon_prefix_sh_source_script + +unset _colcon_prefix_bash_COLCON_CURRENT_PREFIX diff --git a/marshall/install/local_setup.ps1 b/marshall/install/local_setup.ps1 new file mode 100644 index 0000000..6f68c8d --- /dev/null +++ b/marshall/install/local_setup.ps1 @@ -0,0 +1,55 @@ +# generated from colcon_powershell/shell/template/prefix.ps1.em + +# This script extends the environment with all packages contained in this +# prefix path. + +# check environment variable for custom Python executable +if ($env:COLCON_PYTHON_EXECUTABLE) { + if (!(Test-Path "$env:COLCON_PYTHON_EXECUTABLE" -PathType Leaf)) { + echo "error: COLCON_PYTHON_EXECUTABLE '$env:COLCON_PYTHON_EXECUTABLE' doesn't exist" + exit 1 + } + $_colcon_python_executable="$env:COLCON_PYTHON_EXECUTABLE" +} else { + # use the Python executable known at configure time + $_colcon_python_executable="/usr/bin/python3" + # if it doesn't exist try a fall back + if (!(Test-Path "$_colcon_python_executable" -PathType Leaf)) { + if (!(Get-Command "python3" -ErrorAction SilentlyContinue)) { + echo "error: unable to find python3 executable" + exit 1 + } + $_colcon_python_executable="python3" + } +} + +# function to source another script with conditional trace output +# first argument: the path of the script +function _colcon_prefix_powershell_source_script { + param ( + $_colcon_prefix_powershell_source_script_param + ) + # source script with conditional trace output + if (Test-Path $_colcon_prefix_powershell_source_script_param) { + if ($env:COLCON_TRACE) { + echo ". '$_colcon_prefix_powershell_source_script_param'" + } + . "$_colcon_prefix_powershell_source_script_param" + } else { + Write-Error "not found: '$_colcon_prefix_powershell_source_script_param'" + } +} + +# get all commands in topological order +$_colcon_ordered_commands = & "$_colcon_python_executable" "$(Split-Path $PSCommandPath -Parent)/_local_setup_util_ps1.py" ps1 + +# execute all commands in topological order +if ($env:COLCON_TRACE) { + echo "Execute generated script:" + echo "<<<" + $_colcon_ordered_commands.Split([Environment]::NewLine, [StringSplitOptions]::RemoveEmptyEntries) | Write-Output + echo ">>>" +} +if ($_colcon_ordered_commands) { + $_colcon_ordered_commands.Split([Environment]::NewLine, [StringSplitOptions]::RemoveEmptyEntries) | Invoke-Expression +} diff --git a/marshall/install/local_setup.sh b/marshall/install/local_setup.sh new file mode 100644 index 0000000..7be8813 --- /dev/null +++ b/marshall/install/local_setup.sh @@ -0,0 +1,137 @@ +# generated from colcon_core/shell/template/prefix.sh.em + +# This script extends the environment with all packages contained in this +# prefix path. + +# since a plain shell script can't determine its own path when being sourced +# either use the provided COLCON_CURRENT_PREFIX +# or fall back to the build time prefix (if it exists) +_colcon_prefix_sh_COLCON_CURRENT_PREFIX="/home/grimmlins/Documents/GitHub/treefitting/marshall/install" +if [ -z "$COLCON_CURRENT_PREFIX" ]; then + if [ ! -d "$_colcon_prefix_sh_COLCON_CURRENT_PREFIX" ]; then + echo "The build time path \"$_colcon_prefix_sh_COLCON_CURRENT_PREFIX\" doesn't exist. Either source a script for a different shell or set the environment variable \"COLCON_CURRENT_PREFIX\" explicitly." 1>&2 + unset _colcon_prefix_sh_COLCON_CURRENT_PREFIX + return 1 + fi +else + _colcon_prefix_sh_COLCON_CURRENT_PREFIX="$COLCON_CURRENT_PREFIX" +fi + +# function to prepend a value to a variable +# which uses colons as separators +# duplicates as well as trailing separators are avoided +# first argument: the name of the result variable +# second argument: the value to be prepended +_colcon_prefix_sh_prepend_unique_value() { + # arguments + _listname="$1" + _value="$2" + + # get values from variable + eval _values=\"\$$_listname\" + # backup the field separator + _colcon_prefix_sh_prepend_unique_value_IFS="$IFS" + IFS=":" + # start with the new value + _all_values="$_value" + _contained_value="" + # iterate over existing values in the variable + for _item in $_values; do + # ignore empty strings + if [ -z "$_item" ]; then + continue + fi + # ignore duplicates of _value + if [ "$_item" = "$_value" ]; then + _contained_value=1 + continue + fi + # keep non-duplicate values + _all_values="$_all_values:$_item" + done + unset _item + if [ -z "$_contained_value" ]; then + if [ -n "$COLCON_TRACE" ]; then + if [ "$_all_values" = "$_value" ]; then + echo "export $_listname=$_value" + else + echo "export $_listname=$_value:\$$_listname" + fi + fi + fi + unset _contained_value + # restore the field separator + IFS="$_colcon_prefix_sh_prepend_unique_value_IFS" + unset _colcon_prefix_sh_prepend_unique_value_IFS + # export the updated variable + eval export $_listname=\"$_all_values\" + unset _all_values + unset _values + + unset _value + unset _listname +} + +# add this prefix to the COLCON_PREFIX_PATH +_colcon_prefix_sh_prepend_unique_value COLCON_PREFIX_PATH "$_colcon_prefix_sh_COLCON_CURRENT_PREFIX" +unset _colcon_prefix_sh_prepend_unique_value + +# check environment variable for custom Python executable +if [ -n "$COLCON_PYTHON_EXECUTABLE" ]; then + if [ ! -f "$COLCON_PYTHON_EXECUTABLE" ]; then + echo "error: COLCON_PYTHON_EXECUTABLE '$COLCON_PYTHON_EXECUTABLE' doesn't exist" + return 1 + fi + _colcon_python_executable="$COLCON_PYTHON_EXECUTABLE" +else + # try the Python executable known at configure time + _colcon_python_executable="/usr/bin/python3" + # if it doesn't exist try a fall back + if [ ! -f "$_colcon_python_executable" ]; then + if ! /usr/bin/env python3 --version > /dev/null 2> /dev/null; then + echo "error: unable to find python3 executable" + return 1 + fi + _colcon_python_executable=`/usr/bin/env python3 -c "import sys; print(sys.executable)"` + fi +fi + +# function to source another script with conditional trace output +# first argument: the path of the script +_colcon_prefix_sh_source_script() { + if [ -f "$1" ]; then + if [ -n "$COLCON_TRACE" ]; then + echo "# . \"$1\"" + fi + . "$1" + else + echo "not found: \"$1\"" 1>&2 + fi +} + +# get all commands in topological order +_colcon_ordered_commands="$($_colcon_python_executable "$_colcon_prefix_sh_COLCON_CURRENT_PREFIX/_local_setup_util_sh.py" sh)" +unset _colcon_python_executable +if [ -n "$COLCON_TRACE" ]; then + echo "_colcon_prefix_sh_source_script() { + if [ -f \"\$1\" ]; then + if [ -n \"\$COLCON_TRACE\" ]; then + echo \"# . \\\"\$1\\\"\" + fi + . \"\$1\" + else + echo \"not found: \\\"\$1\\\"\" 1>&2 + fi + }" + echo "# Execute generated script:" + echo "# <<<" + echo "${_colcon_ordered_commands}" + echo "# >>>" + echo "unset _colcon_prefix_sh_source_script" +fi +eval "${_colcon_ordered_commands}" +unset _colcon_ordered_commands + +unset _colcon_prefix_sh_source_script + +unset _colcon_prefix_sh_COLCON_CURRENT_PREFIX diff --git a/marshall/install/local_setup.zsh b/marshall/install/local_setup.zsh new file mode 100644 index 0000000..f7a8d90 --- /dev/null +++ b/marshall/install/local_setup.zsh @@ -0,0 +1,120 @@ +# generated from colcon_zsh/shell/template/prefix.zsh.em + +# This script extends the environment with all packages contained in this +# prefix path. + +# a zsh script is able to determine its own path if necessary +if [ -z "$COLCON_CURRENT_PREFIX" ]; then + _colcon_prefix_zsh_COLCON_CURRENT_PREFIX="$(builtin cd -q "`dirname "${(%):-%N}"`" > /dev/null && pwd)" +else + _colcon_prefix_zsh_COLCON_CURRENT_PREFIX="$COLCON_CURRENT_PREFIX" +fi + +# function to convert array-like strings into arrays +# to workaround SH_WORD_SPLIT not being set +_colcon_prefix_zsh_convert_to_array() { + local _listname=$1 + local _dollar="$" + local _split="{=" + local _to_array="(\"$_dollar$_split$_listname}\")" + eval $_listname=$_to_array +} + +# function to prepend a value to a variable +# which uses colons as separators +# duplicates as well as trailing separators are avoided +# first argument: the name of the result variable +# second argument: the value to be prepended +_colcon_prefix_zsh_prepend_unique_value() { + # arguments + _listname="$1" + _value="$2" + + # get values from variable + eval _values=\"\$$_listname\" + # backup the field separator + _colcon_prefix_zsh_prepend_unique_value_IFS="$IFS" + IFS=":" + # start with the new value + _all_values="$_value" + # workaround SH_WORD_SPLIT not being set + _colcon_prefix_zsh_convert_to_array _values + # iterate over existing values in the variable + for _item in $_values; do + # ignore empty strings + if [ -z "$_item" ]; then + continue + fi + # ignore duplicates of _value + if [ "$_item" = "$_value" ]; then + continue + fi + # keep non-duplicate values + _all_values="$_all_values:$_item" + done + unset _item + # restore the field separator + IFS="$_colcon_prefix_zsh_prepend_unique_value_IFS" + unset _colcon_prefix_zsh_prepend_unique_value_IFS + # export the updated variable + eval export $_listname=\"$_all_values\" + unset _all_values + unset _values + + unset _value + unset _listname +} + +# add this prefix to the COLCON_PREFIX_PATH +_colcon_prefix_zsh_prepend_unique_value COLCON_PREFIX_PATH "$_colcon_prefix_zsh_COLCON_CURRENT_PREFIX" +unset _colcon_prefix_zsh_prepend_unique_value +unset _colcon_prefix_zsh_convert_to_array + +# check environment variable for custom Python executable +if [ -n "$COLCON_PYTHON_EXECUTABLE" ]; then + if [ ! -f "$COLCON_PYTHON_EXECUTABLE" ]; then + echo "error: COLCON_PYTHON_EXECUTABLE '$COLCON_PYTHON_EXECUTABLE' doesn't exist" + return 1 + fi + _colcon_python_executable="$COLCON_PYTHON_EXECUTABLE" +else + # try the Python executable known at configure time + _colcon_python_executable="/usr/bin/python3" + # if it doesn't exist try a fall back + if [ ! -f "$_colcon_python_executable" ]; then + if ! /usr/bin/env python3 --version > /dev/null 2> /dev/null; then + echo "error: unable to find python3 executable" + return 1 + fi + _colcon_python_executable=`/usr/bin/env python3 -c "import sys; print(sys.executable)"` + fi +fi + +# function to source another script with conditional trace output +# first argument: the path of the script +_colcon_prefix_sh_source_script() { + if [ -f "$1" ]; then + if [ -n "$COLCON_TRACE" ]; then + echo ". \"$1\"" + fi + . "$1" + else + echo "not found: \"$1\"" 1>&2 + fi +} + +# get all commands in topological order +_colcon_ordered_commands="$($_colcon_python_executable "$_colcon_prefix_zsh_COLCON_CURRENT_PREFIX/_local_setup_util_sh.py" sh zsh)" +unset _colcon_python_executable +if [ -n "$COLCON_TRACE" ]; then + echo "Execute generated script:" + echo "<<<" + echo "${_colcon_ordered_commands}" + echo ">>>" +fi +eval "${_colcon_ordered_commands}" +unset _colcon_ordered_commands + +unset _colcon_prefix_sh_source_script + +unset _colcon_prefix_zsh_COLCON_CURRENT_PREFIX diff --git a/marshall/install/setup.bash b/marshall/install/setup.bash new file mode 100644 index 0000000..4c55244 --- /dev/null +++ b/marshall/install/setup.bash @@ -0,0 +1,31 @@ +# generated from colcon_bash/shell/template/prefix_chain.bash.em + +# This script extends the environment with the environment of other prefix +# paths which were sourced when this file was generated as well as all packages +# contained in this prefix path. + +# function to source another script with conditional trace output +# first argument: the path of the script +_colcon_prefix_chain_bash_source_script() { + if [ -f "$1" ]; then + if [ -n "$COLCON_TRACE" ]; then + echo ". \"$1\"" + fi + . "$1" + else + echo "not found: \"$1\"" 1>&2 + fi +} + +# source chained prefixes +# setting COLCON_CURRENT_PREFIX avoids determining the prefix in the sourced script +COLCON_CURRENT_PREFIX="/opt/ros/humble" +_colcon_prefix_chain_bash_source_script "$COLCON_CURRENT_PREFIX/local_setup.bash" + +# source this prefix +# setting COLCON_CURRENT_PREFIX avoids determining the prefix in the sourced script +COLCON_CURRENT_PREFIX="$(builtin cd "`dirname "${BASH_SOURCE[0]}"`" > /dev/null && pwd)" +_colcon_prefix_chain_bash_source_script "$COLCON_CURRENT_PREFIX/local_setup.bash" + +unset COLCON_CURRENT_PREFIX +unset _colcon_prefix_chain_bash_source_script diff --git a/marshall/install/setup.ps1 b/marshall/install/setup.ps1 new file mode 100644 index 0000000..558e9b9 --- /dev/null +++ b/marshall/install/setup.ps1 @@ -0,0 +1,29 @@ +# generated from colcon_powershell/shell/template/prefix_chain.ps1.em + +# This script extends the environment with the environment of other prefix +# paths which were sourced when this file was generated as well as all packages +# contained in this prefix path. + +# function to source another script with conditional trace output +# first argument: the path of the script +function _colcon_prefix_chain_powershell_source_script { + param ( + $_colcon_prefix_chain_powershell_source_script_param + ) + # source script with conditional trace output + if (Test-Path $_colcon_prefix_chain_powershell_source_script_param) { + if ($env:COLCON_TRACE) { + echo ". '$_colcon_prefix_chain_powershell_source_script_param'" + } + . "$_colcon_prefix_chain_powershell_source_script_param" + } else { + Write-Error "not found: '$_colcon_prefix_chain_powershell_source_script_param'" + } +} + +# source chained prefixes +_colcon_prefix_chain_powershell_source_script "/opt/ros/humble\local_setup.ps1" + +# source this prefix +$env:COLCON_CURRENT_PREFIX=(Split-Path $PSCommandPath -Parent) +_colcon_prefix_chain_powershell_source_script "$env:COLCON_CURRENT_PREFIX\local_setup.ps1" diff --git a/marshall/install/setup.sh b/marshall/install/setup.sh new file mode 100644 index 0000000..7bf631b --- /dev/null +++ b/marshall/install/setup.sh @@ -0,0 +1,45 @@ +# generated from colcon_core/shell/template/prefix_chain.sh.em + +# This script extends the environment with the environment of other prefix +# paths which were sourced when this file was generated as well as all packages +# contained in this prefix path. + +# since a plain shell script can't determine its own path when being sourced +# either use the provided COLCON_CURRENT_PREFIX +# or fall back to the build time prefix (if it exists) +_colcon_prefix_chain_sh_COLCON_CURRENT_PREFIX=/home/grimmlins/Documents/GitHub/treefitting/marshall/install +if [ ! -z "$COLCON_CURRENT_PREFIX" ]; then + _colcon_prefix_chain_sh_COLCON_CURRENT_PREFIX="$COLCON_CURRENT_PREFIX" +elif [ ! -d "$_colcon_prefix_chain_sh_COLCON_CURRENT_PREFIX" ]; then + echo "The build time path \"$_colcon_prefix_chain_sh_COLCON_CURRENT_PREFIX\" doesn't exist. Either source a script for a different shell or set the environment variable \"COLCON_CURRENT_PREFIX\" explicitly." 1>&2 + unset _colcon_prefix_chain_sh_COLCON_CURRENT_PREFIX + return 1 +fi + +# function to source another script with conditional trace output +# first argument: the path of the script +_colcon_prefix_chain_sh_source_script() { + if [ -f "$1" ]; then + if [ -n "$COLCON_TRACE" ]; then + echo "# . \"$1\"" + fi + . "$1" + else + echo "not found: \"$1\"" 1>&2 + fi +} + +# source chained prefixes +# setting COLCON_CURRENT_PREFIX avoids relying on the build time prefix of the sourced script +COLCON_CURRENT_PREFIX="/opt/ros/humble" +_colcon_prefix_chain_sh_source_script "$COLCON_CURRENT_PREFIX/local_setup.sh" + + +# source this prefix +# setting COLCON_CURRENT_PREFIX avoids relying on the build time prefix of the sourced script +COLCON_CURRENT_PREFIX="$_colcon_prefix_chain_sh_COLCON_CURRENT_PREFIX" +_colcon_prefix_chain_sh_source_script "$COLCON_CURRENT_PREFIX/local_setup.sh" + +unset _colcon_prefix_chain_sh_COLCON_CURRENT_PREFIX +unset _colcon_prefix_chain_sh_source_script +unset COLCON_CURRENT_PREFIX diff --git a/marshall/install/setup.zsh b/marshall/install/setup.zsh new file mode 100644 index 0000000..990d171 --- /dev/null +++ b/marshall/install/setup.zsh @@ -0,0 +1,31 @@ +# generated from colcon_zsh/shell/template/prefix_chain.zsh.em + +# This script extends the environment with the environment of other prefix +# paths which were sourced when this file was generated as well as all packages +# contained in this prefix path. + +# function to source another script with conditional trace output +# first argument: the path of the script +_colcon_prefix_chain_zsh_source_script() { + if [ -f "$1" ]; then + if [ -n "$COLCON_TRACE" ]; then + echo ". \"$1\"" + fi + . "$1" + else + echo "not found: \"$1\"" 1>&2 + fi +} + +# source chained prefixes +# setting COLCON_CURRENT_PREFIX avoids determining the prefix in the sourced script +COLCON_CURRENT_PREFIX="/opt/ros/humble" +_colcon_prefix_chain_zsh_source_script "$COLCON_CURRENT_PREFIX/local_setup.zsh" + +# source this prefix +# setting COLCON_CURRENT_PREFIX avoids determining the prefix in the sourced script +COLCON_CURRENT_PREFIX="$(builtin cd -q "`dirname "${(%):-%N}"`" > /dev/null && pwd)" +_colcon_prefix_chain_zsh_source_script "$COLCON_CURRENT_PREFIX/local_setup.zsh" + +unset COLCON_CURRENT_PREFIX +unset _colcon_prefix_chain_zsh_source_script diff --git a/marshall/leader_mask.png b/marshall/leader_mask.png new file mode 100644 index 0000000..39000bb Binary files /dev/null and b/marshall/leader_mask.png differ diff --git a/marshall/log/COLCON_IGNORE b/marshall/log/COLCON_IGNORE new file mode 100644 index 0000000..e69de29 diff --git a/marshall/log/build_2023-09-02_12-15-53/events.log b/marshall/log/build_2023-09-02_12-15-53/events.log new file mode 100644 index 0000000..a5b1e71 --- /dev/null +++ b/marshall/log/build_2023-09-02_12-15-53/events.log @@ -0,0 +1,2 @@ +[0.000000] (-) TimerEvent: {} +[0.000517] (-) EventReactorShutdown: {} diff --git a/marshall/log/build_2023-09-02_12-15-53/logger_all.log b/marshall/log/build_2023-09-02_12-15-53/logger_all.log new file mode 100644 index 0000000..c365ecd --- /dev/null +++ b/marshall/log/build_2023-09-02_12-15-53/logger_all.log @@ -0,0 +1,90 @@ +[0.314s] DEBUG:colcon:Command line arguments: ['/usr/bin/colcon', 'build'] +[0.314s] DEBUG:colcon:Parsed command line arguments: Namespace(log_base=None, log_level=None, verb_name='build', build_base='build', install_base='install', merge_install=False, symlink_install=False, test_result_base=None, continue_on_error=False, executor='parallel', parallel_workers=16, event_handlers=None, ignore_user_meta=False, metas=['./colcon.meta'], base_paths=['.'], packages_ignore=None, packages_ignore_regex=None, paths=None, packages_up_to=None, packages_up_to_regex=None, packages_above=None, packages_above_and_dependencies=None, packages_above_depth=None, packages_select_by_dep=None, packages_skip_by_dep=None, packages_skip_up_to=None, packages_select_build_failed=False, packages_skip_build_finished=False, packages_select_test_failures=False, packages_skip_test_passed=False, packages_select=None, packages_skip=None, packages_select_regex=None, packages_skip_regex=None, packages_start=None, packages_end=None, allow_overriding=[], cmake_args=None, cmake_target=None, cmake_target_skip_unavailable=False, cmake_clean_cache=False, cmake_clean_first=False, cmake_force_configure=False, ament_cmake_args=None, catkin_cmake_args=None, catkin_skip_building_tests=False, verb_parser=, verb_extension=, main=>) +[0.343s] Level 1:colcon.colcon_core.package_discovery:discover_packages(colcon_meta) check parameters +[0.343s] Level 1:colcon.colcon_core.package_discovery:discover_packages(recursive) check parameters +[0.343s] Level 1:colcon.colcon_core.package_discovery:discover_packages(ignore) check parameters +[0.343s] Level 1:colcon.colcon_core.package_discovery:discover_packages(path) check parameters +[0.343s] Level 1:colcon.colcon_core.package_discovery:discover_packages(colcon_meta) discover +[0.343s] Level 1:colcon.colcon_core.package_discovery:discover_packages(recursive) discover +[0.343s] INFO:colcon.colcon_core.package_discovery:Crawling recursively for packages in '/home/grimmlins/Documents/GitHub/treefitting/marshall' +[0.343s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['ignore', 'ignore_ament_install'] +[0.343s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'ignore' +[0.343s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'ignore_ament_install' +[0.343s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['colcon_pkg'] +[0.344s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'colcon_pkg' +[0.344s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['colcon_meta'] +[0.344s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'colcon_meta' +[0.344s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['ros'] +[0.344s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'ros' +[0.354s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['cmake', 'python'] +[0.354s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'cmake' +[0.354s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'python' +[0.354s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extensions ['python_setup_py'] +[0.354s] Level 1:colcon.colcon_core.package_identification:_identify(.) by extension 'python_setup_py' +[0.354s] Level 1:colcon.colcon_core.package_identification:_identify(Blender) by extensions ['ignore', 'ignore_ament_install'] +[0.355s] Level 1:colcon.colcon_core.package_identification:_identify(Blender) by extension 'ignore' +[0.355s] Level 1:colcon.colcon_core.package_identification:_identify(Blender) by extension 'ignore_ament_install' +[0.355s] Level 1:colcon.colcon_core.package_identification:_identify(Blender) by extensions ['colcon_pkg'] +[0.355s] Level 1:colcon.colcon_core.package_identification:_identify(Blender) by extension 'colcon_pkg' +[0.355s] Level 1:colcon.colcon_core.package_identification:_identify(Blender) by extensions ['colcon_meta'] +[0.355s] Level 1:colcon.colcon_core.package_identification:_identify(Blender) by extension 'colcon_meta' +[0.355s] Level 1:colcon.colcon_core.package_identification:_identify(Blender) by extensions ['ros'] +[0.355s] Level 1:colcon.colcon_core.package_identification:_identify(Blender) by extension 'ros' +[0.355s] Level 1:colcon.colcon_core.package_identification:_identify(Blender) by extensions ['cmake', 'python'] +[0.355s] Level 1:colcon.colcon_core.package_identification:_identify(Blender) by extension 'cmake' +[0.355s] Level 1:colcon.colcon_core.package_identification:_identify(Blender) by extension 'python' +[0.355s] Level 1:colcon.colcon_core.package_identification:_identify(Blender) by extensions ['python_setup_py'] +[0.355s] Level 1:colcon.colcon_core.package_identification:_identify(Blender) by extension 'python_setup_py' +[0.355s] Level 1:colcon.colcon_core.package_identification:_identify(__pycache__) by extensions ['ignore', 'ignore_ament_install'] +[0.355s] Level 1:colcon.colcon_core.package_identification:_identify(__pycache__) by extension 'ignore' +[0.355s] Level 1:colcon.colcon_core.package_identification:_identify(__pycache__) by extension 'ignore_ament_install' +[0.356s] Level 1:colcon.colcon_core.package_identification:_identify(__pycache__) by extensions ['colcon_pkg'] +[0.356s] Level 1:colcon.colcon_core.package_identification:_identify(__pycache__) by extension 'colcon_pkg' +[0.356s] Level 1:colcon.colcon_core.package_identification:_identify(__pycache__) by extensions ['colcon_meta'] +[0.356s] Level 1:colcon.colcon_core.package_identification:_identify(__pycache__) by extension 'colcon_meta' +[0.356s] Level 1:colcon.colcon_core.package_identification:_identify(__pycache__) by extensions ['ros'] +[0.356s] Level 1:colcon.colcon_core.package_identification:_identify(__pycache__) by extension 'ros' +[0.356s] Level 1:colcon.colcon_core.package_identification:_identify(__pycache__) by extensions ['cmake', 'python'] +[0.356s] Level 1:colcon.colcon_core.package_identification:_identify(__pycache__) by extension 'cmake' +[0.356s] Level 1:colcon.colcon_core.package_identification:_identify(__pycache__) by extension 'python' +[0.356s] Level 1:colcon.colcon_core.package_identification:_identify(__pycache__) by extensions ['python_setup_py'] +[0.356s] Level 1:colcon.colcon_core.package_identification:_identify(__pycache__) by extension 'python_setup_py' +[0.356s] Level 1:colcon.colcon_core.package_identification:_identify(build) by extensions ['ignore', 'ignore_ament_install'] +[0.356s] Level 1:colcon.colcon_core.package_identification:_identify(build) by extension 'ignore' +[0.356s] Level 1:colcon.colcon_core.package_identification:_identify(build) ignored +[0.356s] Level 1:colcon.colcon_core.package_identification:_identify(install) by extensions ['ignore', 'ignore_ament_install'] +[0.356s] Level 1:colcon.colcon_core.package_identification:_identify(install) by extension 'ignore' +[0.357s] Level 1:colcon.colcon_core.package_identification:_identify(install) ignored +[0.357s] Level 1:colcon.colcon_core.package_identification:_identify(log) by extensions ['ignore', 'ignore_ament_install'] +[0.357s] Level 1:colcon.colcon_core.package_identification:_identify(log) by extension 'ignore' +[0.357s] Level 1:colcon.colcon_core.package_identification:_identify(log) ignored +[0.357s] Level 1:colcon.colcon_core.package_discovery:discover_packages(recursive) using defaults +[0.357s] Level 1:colcon.colcon_core.package_discovery:discover_packages(ignore) discover +[0.357s] Level 1:colcon.colcon_core.package_discovery:discover_packages(ignore) using defaults +[0.357s] Level 1:colcon.colcon_core.package_discovery:discover_packages(path) discover +[0.357s] Level 1:colcon.colcon_core.package_discovery:discover_packages(path) using defaults +[0.380s] Level 1:colcon.colcon_core.package_discovery:discover_packages(prefix_path) check parameters +[0.380s] Level 1:colcon.colcon_core.package_discovery:discover_packages(prefix_path) discover +[0.383s] DEBUG:colcon.colcon_installed_package_information.package_discovery:Found 368 installed packages in /opt/ros/humble +[0.385s] Level 1:colcon.colcon_core.package_discovery:discover_packages(prefix_path) using defaults +[0.451s] INFO:colcon.colcon_core.executor:Executing jobs using 'parallel' executor +[0.454s] DEBUG:colcon.colcon_parallel_executor.executor.parallel:run_until_complete +[0.454s] DEBUG:colcon.colcon_parallel_executor.executor.parallel:closing loop +[0.454s] DEBUG:colcon.colcon_parallel_executor.executor.parallel:loop closed +[0.454s] DEBUG:colcon.colcon_parallel_executor.executor.parallel:run_until_complete finished with '0' +[0.455s] DEBUG:colcon.colcon_core.event_reactor:joining thread +[0.459s] INFO:colcon.colcon_core.plugin_system:Skipping extension 'colcon_notification.desktop_notification.terminal_notifier': Not used on non-Darwin systems +[0.459s] INFO:colcon.colcon_core.plugin_system:Skipping extension 'colcon_notification.desktop_notification.win32': Not used on non-Windows systems +[0.459s] INFO:colcon.colcon_notification.desktop_notification:Sending desktop notification using 'notify2' +[0.468s] DEBUG:colcon.colcon_core.event_reactor:joined thread +[0.472s] INFO:colcon.colcon_core.plugin_system:Skipping extension 'colcon_core.shell.bat': Not used on non-Windows systems +[0.472s] INFO:colcon.colcon_core.shell:Creating prefix script '/home/grimmlins/Documents/GitHub/treefitting/marshall/install/local_setup.ps1' +[0.473s] INFO:colcon.colcon_core.shell:Creating prefix util module '/home/grimmlins/Documents/GitHub/treefitting/marshall/install/_local_setup_util_ps1.py' +[0.474s] INFO:colcon.colcon_core.shell:Creating prefix chain script '/home/grimmlins/Documents/GitHub/treefitting/marshall/install/setup.ps1' +[0.475s] INFO:colcon.colcon_core.shell:Creating prefix script '/home/grimmlins/Documents/GitHub/treefitting/marshall/install/local_setup.sh' +[0.475s] INFO:colcon.colcon_core.shell:Creating prefix util module '/home/grimmlins/Documents/GitHub/treefitting/marshall/install/_local_setup_util_sh.py' +[0.476s] INFO:colcon.colcon_core.shell:Creating prefix chain script '/home/grimmlins/Documents/GitHub/treefitting/marshall/install/setup.sh' +[0.476s] INFO:colcon.colcon_core.shell:Creating prefix script '/home/grimmlins/Documents/GitHub/treefitting/marshall/install/local_setup.bash' +[0.477s] INFO:colcon.colcon_core.shell:Creating prefix chain script '/home/grimmlins/Documents/GitHub/treefitting/marshall/install/setup.bash' +[0.477s] INFO:colcon.colcon_core.shell:Creating prefix script '/home/grimmlins/Documents/GitHub/treefitting/marshall/install/local_setup.zsh' +[0.478s] INFO:colcon.colcon_core.shell:Creating prefix chain script '/home/grimmlins/Documents/GitHub/treefitting/marshall/install/setup.zsh' diff --git a/marshall/log/latest b/marshall/log/latest new file mode 120000 index 0000000..b57d247 --- /dev/null +++ b/marshall/log/latest @@ -0,0 +1 @@ +latest_build \ No newline at end of file diff --git a/marshall/log/latest_build b/marshall/log/latest_build new file mode 120000 index 0000000..14d2171 --- /dev/null +++ b/marshall/log/latest_build @@ -0,0 +1 @@ +build_2023-09-02_12-15-53 \ No newline at end of file diff --git a/marshall/output.png b/marshall/output.png new file mode 100644 index 0000000..f0a2555 Binary files /dev/null and b/marshall/output.png differ diff --git a/marshall/params.py b/marshall/params.py new file mode 100644 index 0000000..d4d45de --- /dev/null +++ b/marshall/params.py @@ -0,0 +1,10 @@ +scale_factor = 100 +cam = 'D435_640x480.camera.npz' +#depth_img = "depth0001.raw" +mask_img = "leader_mask.png" +follower_msk = "follower_mask.png" +angle_limit = 70 +nan_value = 1 +video_file = "output.mkv" +num_cyl = 16 +cyls = 13 #number of cylinders outputted, a set value for now but can be changed to detect it automatically from filenames diff --git a/marshall/pull_depth_and_rgb.py b/marshall/pull_depth_and_rgb.py new file mode 100644 index 0000000..bcb2f8f --- /dev/null +++ b/marshall/pull_depth_and_rgb.py @@ -0,0 +1,28 @@ +import os +import cv2 + +#extracts depth and rgb data from azure kinect video +#requires ffmpeg library: sudo apt install ffmpeg +""" +INSTRUCTIONS FOR RUNNING: +1. Install ffmpeg +2. Download folder containing video output file +3. Copy and paste this file into the downloaded folder +4. Navigate to downloaded folder in terminal +5. Run script and specify filename(excluding extension) you would like to extract data from. +""" +print("please type the file name(excluding extension) you would like to extract from: ") +inp = input() +filename = f'{inp}.mkv' +current_directory = os.getcwd() +rgb_folder = f'{inp}_rgb_data' +depth_folder = f'{inp}_depth_data' +path1 = os.path.join(current_directory, rgb_folder) +path2 = os.path.join(current_directory, depth_folder) +os.mkdir(path1) +os.mkdir(path2) + +cmd1 = f'ffmpeg -i {filename} -vf "select=not(mod(n\,10))" -map 0:0 -vsync 0 {path1}/rgb%04d.png' +cmd2 = f'ffmpeg -i {filename} -vf "select=not(mod(n\,10))" -map 0:1 -vsync 0 {path2}/depth%04d.pgm' #change to whichever file type is easiest to work with for depth +os.system(cmd1) +os.system(cmd2)