Example #1
0
def roundoff(tau, R_pz, dist_mod, xy, nd, n_t1, n_t2, vertexes, xyc):

    r_tc = R_pz / tau
    v_tc = np.add(np.array(dist_mod / tau * nd), xy)  #circle's center

    point1 = r_tc * np.array([-n_t1[1], n_t1[0]
                              ]) + v_tc  #intersection of leg2 with the circle
    point2 = r_tc * np.array([n_t2[1], -n_t2[0]
                              ]) + v_tc  #intersection of leg1 with the circle

    legs_points = [[point1[0], point1[1]], [point2[0], point2[1]],
                   list(vertexes[0]),
                   list(vertexes[1])]

    #Define the circle's coordinates
    circle_lst = [list(map(list, np.flipud(xyc * r_tc)))]
    circle1 = np.array(circle_lst[0])
    circle1 = np.add(circle1, v_tc)  #add center of circle

    legs = pyclipper.Pyclipper()
    legs.AddPath(pyclipper.scale_to_clipper(legs_points), pyclipper.PT_SUBJECT,
                 True)

    circle_cut = tuple(map(tuple, circle1))
    legs.AddPath(pyclipper.scale_to_clipper(circle_cut), pyclipper.PT_CLIP,
                 True)

    union = pyclipper.scale_from_clipper(
        legs.Execute(pyclipper.CT_UNION, pyclipper.PFT_NONZERO,
                     pyclipper.PFT_NONZERO))
    union = np.array(union[0])
    #PUT THE UNION IN TUPLE SO IT CAN BE ADDED AS AN OBJECT TO A PYCLIPPER OBJECT
    VO_round = tuple(map(tuple, union))

    return VO_round, legs_points
Example #2
0
    def basic_rib(self, le_size, te_size, sp_size, to_mm=1):
        '''
        defines a classic balsa model plane rib pattern with solid leading
        and tailing edges and one main spar at 33% of the chord.
        '''

        # Apply conversion to the spars sizes
        le_size = [to_mm * x for x in le_size]
        te_size = [to_mm * x for x in te_size]
        sp_size = [to_mm * x for x in sp_size]

        #  add_spar( surface, size, percent, aligment, pinned)
        #self.add_spar(self.lower, le_size, 0.00, (0,0), True)  # LE
        self.add_spar(self.upper, sp_size, 0.27, (0,1), False) # Spar
        self.add_spar(self.upper, te_size, 1.00, (1,0), True)  # TE

        # Optionally make LE a diamond
        self.add_diamond_le(self.upper, le_size[0], .5)

        # Add the profile to the clipper
        self.clipper.AddPath(pyclipper.scale_to_clipper(self.profile, self.SCALING_FACTOR), pyclipper.PT_SUBJECT, True)

        # The second operand is a list of spars
        self.clipper.AddPaths(pyclipper.scale_to_clipper(self.spars, self.SCALING_FACTOR), pyclipper.PT_CLIP, True)

        # Subtract the spar cutouts from the profile 
        rib_path = self.clipper.Execute(pyclipper.CT_DIFFERENCE, pyclipper.PFT_EVENODD, pyclipper.PFT_EVENODD)

        return(pyclipper.scale_from_clipper(rib_path, self.SCALING_FACTOR))
Example #3
0
    def generateHalfCircle(self, position, r, saddleDir, exPos, funcValue):
        x0 = position[0]
        y0 = position[1]
        r = r / float(self.maxContourSize) * self.scale

        items = 10 + int(
            3.14 * pyclipper.scale_to_clipper(r) / self.tessResolution)
        # print "generateHalfCircle:", items

        path = []
        #compute test dirVec
        sDirOrth = np.array([saddleDir[1], -saddleDir[0]])
        exDir = self.normalize(np.array(exPos) - np.array(position))

        if np.dot(sDirOrth, exDir) < 0.0:
            sDirOrth = -sDirOrth

        for i in range(items):
            x = x0 + r * math.cos(2 * math.pi * i / items)
            y = y0 + r * math.sin(2 * math.pi * i / items)
            p2Center = self.normalize(np.array([x, y]) - np.array(position))
            if np.dot(sDirOrth, p2Center) >= 0.0:
                path.append([x, y])

        path = pyclipper.scale_to_clipper(path)
        return path
Example #4
0
def shapely_to_clipper(polygon):
    ext = np.array(polygon.exterior.coords)
    ext = pyclipper.scale_to_clipper(ext)

    ints = [pyclipper.scale_to_clipper(np.array(inters.coords)) for inters in polygon.interiors]
    ints.insert(0, ext)
    return ints
Example #5
0
def offset_polygon(polygon, distance, join_type=JOIN_MITER):
    '''
    Offsets a the vertices of a `polygon` by `distance` units. Negative
    `distance` insets the polygon.
    
    See :py:func:`offset` for details.
    
    >>> offset_polygon([Point3d(0,0,0), Point3d(2,0,0), Point3d(2,2,0), Point3d(0,2,0), Point3d(0,0,0)], 0.5)
    [Point3d(2.5, 2.5, 0), Point3d(-0.5, 2.5, 0), Point3d(-0.5, -0.5, 0), Point3d(2.5, -0.5, 0), Point3d(2.5, 2.5, 0)]
    
    Note: The point order is not stable!
    
    >>> offset_polygon([Point3d(0,0,0), Point3d(2,0,0), Point3d(2,2,0), Point3d(0,2,0), Point3d(0,0,0)], -0.5)
    [Point3d(1.5, 1.5, 0), Point3d(0.5, 1.5, 0), Point3d(0.5, 0.5, 0), Point3d(1.5, 0.5, 0), Point3d(1.5, 1.5, 0)]
    '''
    poly2d = [p.xy for p in polygon]
    clipper = clip.PyclipperOffset()
    clipper.AddPath(clip.scale_to_clipper(poly2d), join_type,
                    clip.ET_CLOSEDPOLYGON)
    solution = clip.scale_from_clipper(
        clipper.Execute(clip.scale_to_clipper(distance)))
    try:
        return [Point3d(*p) for p in solution[0]] + [Point3d(*solution[0][0])]
    except IndexError:
        return []
def getroomcontour(origin, room):
    room_fname = os.path.join(suncg_root, "room", origin, room + "f.obj")
    if (not os.path.isfile(room_fname)):
        room_fname = os.path.join(
            os.path.split(housef)[0].replace(house_root, room_root),
            room["modelId"] + "c.obj")
    with open(room_fname, "r") as inf:
        lines = inf.read().split("\n")
        vertices_lines = lfilter(lambda x: x.startswith("v "), lines)
        vertices = np.array(
            lmap(lambda x: lmap(float,
                                x.split()[1:]), vertices_lines))[:, [0, 2]]
        faces_lines = lfilter(lambda x: x.startswith("f "), lines)
        faces = lmap(
            lambda x: lmap(lambda y: int(y.split("/")[0]) - 1,
                           x.split()[1:]), faces_lines)
        paths = pyclipper.scale_to_clipper([vertices[faces[0]]])
        for face in faces:
            if (np.abs(area(vertices[face])) < 1e-5):
                continue
            pc = pyclipper.Pyclipper()
            pc.AddPaths(paths, pyclipper.PT_SUBJECT, True)
            clipface = pyclipper.scale_to_clipper(vertices[face])
            pc.AddPath(clipface, pyclipper.PT_CLIP, True)
            paths = pc.Execute(pyclipper.CT_UNION, pyclipper.PFT_EVENODD,
                               pyclipper.PFT_EVENODD)
        paths = pyclipper.scale_from_clipper(paths)

    return paths
Example #7
0
def intersect_polygons(polygon1, polygon2):
    """
    Intersect two polygons.

    Parameters
    ----------
    polygon1 : list of arrays
        Vertices of the first polygon in counterclockwise order.
    polygon1 : list of arrays
        Vertices of the second polygon in counterclockwise order.

    Returns
    -------
    intersection : list of arrays
        Vertices of the intersection in counterclockwise order.
    """
    from pyclipper import Pyclipper, PT_CLIP, PT_SUBJECT, CT_INTERSECTION
    from pyclipper import scale_to_clipper, scale_from_clipper
    # could be accelerated by removing the scale_to/from_clipper()
    subj, clip = (polygon1,), polygon2
    pc = Pyclipper()
    pc.AddPath(scale_to_clipper(clip), PT_CLIP)
    pc.AddPaths(scale_to_clipper(subj), PT_SUBJECT)
    solution = pc.Execute(CT_INTERSECTION)
    if not solution:
        return []
    return scale_from_clipper(solution)[0]
Example #8
0
File: Rib.py Project: bobm123/maker
    def basic_rib(self, le_size, te_size, sp_size, to_mm=1):
        '''
        defines a classic balsa model plane rib pattern with solid leading
        and tailing edges and one main spar at 33% of the chord.
        '''

        # Apply conversion to the spars sizes
        le_size = [to_mm * x for x in le_size]
        te_size = [to_mm * x for x in te_size]
        sp_size = [to_mm * x for x in sp_size]

        #  add_spar( surface, size, percent, aligment, pinned)
        #self.add_spar(self.lower, le_size, 0.00, (0,0), True)  # LE
        self.add_spar(self.upper, sp_size, 0.33, (0,1), False) # Spar
        self.add_spar(self.upper, te_size, 1.00, (1,0), True)  # TE

        # Optionally make LE a diamond
        self.add_diamond_le(self.upper, le_size[0], .65)

        # Add the profile to the clipper
        self.clipper.AddPath(pyclipper.scale_to_clipper(self.profile, self.SCALING_FACTOR), pyclipper.PT_SUBJECT, True)

        # The second operand is a list of spars
        self.clipper.AddPaths(pyclipper.scale_to_clipper(self.spars, self.SCALING_FACTOR), pyclipper.PT_CLIP, True)

        # Subtract the spar cutouts from the profile 
        rib_path = self.clipper.Execute(pyclipper.CT_DIFFERENCE, pyclipper.PFT_EVENODD, pyclipper.PFT_EVENODD)

        return(pyclipper.scale_from_clipper(rib_path, self.SCALING_FACTOR))
Example #9
0
def prep_3D_polys(poly1, poly2):
    # type: (Polygon3D, Polygon3D) -> pc.Pyclipper
    """Prepare two 3D polygons for clipping operations.

    Parameters
    ----------
    poly1 : Polygon3D
        The subject polygon.
    poly2 : Polygon3D
        The clip polygon.

    Returns
    -------
    pc.Pyclipper object

    """
    if not poly1.is_coplanar(poly2):
        return False
    poly1 = poly1.project_to_2D()
    poly2 = poly2.project_to_2D()

    s1 = pc.scale_to_clipper(poly1.vertices_list)
    s2 = pc.scale_to_clipper(poly2.vertices_list)
    clipper = pc.Pyclipper()
    clipper.AddPath(s1, poly_type=pc.PT_SUBJECT, closed=True)
    clipper.AddPath(s2, poly_type=pc.PT_CLIP, closed=True)

    return clipper
Example #10
0
	def _offset_profile(poly):
		pco = pyclipper.PyclipperOffset()
		pco.AddPath(pyclipper.scale_to_clipper(poly), pyclipper.JT_ROUND, pyclipper.ET_CLOSEDPOLYGON)
		offset = pco.Execute(-pyclipper.scale_to_clipper(Layer.bead_width/2))
		offset = pyclipper.scale_from_clipper(offset)
		offset = np.reshape(offset, (-1,2))
		return offset
Example #11
0
def generate_offset_polygon(lot):
    nodes, ways = {}, {}
    subj = []
    for x, y in lot:
        subj.append((pyclipper.scale_to_clipper(x),
                     pyclipper.scale_to_clipper(y)))
    pco = pyclipper.PyclipperOffset()
    pco.AddPath(subj, pyclipper.JT_MITER, pyclipper.ET_CLOSEDPOLYGON)
    solution = pco.Execute(-150000.0)
    building_lot = [(pyclipper.scale_from_clipper(x),
                    pyclipper.scale_from_clipper(y)) for x, y in solution[0]]

    if len(building_lot) == 0:
        # failed to get offset polygon with the fixed param
        return nodes, ways

    building_nodes = []
    for x, y in building_lot:
        n = new_node(x, y)
        building_nodes.append(n.id)
        nodes[n.id] = n

    way = new_way()
    way.nodes = building_nodes+[building_nodes[0]]
    way.tags = {"building":"residential"}
    ways[way.id] = way

    return nodes, ways
Example #12
0
def paths_contain(pt, paths):
    cnt = 0
    pt = pyclipper.scale_to_clipper([pt], SCALING_FACTOR)[0]
    for path in paths:
        path = pyclipper.scale_to_clipper(path, SCALING_FACTOR)
        if pyclipper.PointInPolygon(pt, path):
            cnt = 1 - cnt
    return cnt % 2 != 0
Example #13
0
 def offset(self, r):
     r = pyclipper.scale_to_clipper(r)
     t = time.time()
     pco = pyclipper.PyclipperOffset()
     pco.AddPaths(pyclipper.scale_to_clipper(self.items),
                  pyclipper.JT_SQUARE, pyclipper.ET_CLOSEDPOLYGON)
     res = pyclipper.scale_from_clipper(pco.Execute(r))
     return res
Example #14
0
 def intersectionOfShapes(self, mask, polys):
     pc = pyclipper.Pyclipper()
     pc.AddPaths(pyclipper.scale_to_clipper(mask), pyclipper.PT_CLIP, True)
     pc.AddPaths(pyclipper.scale_to_clipper(polys), pyclipper.PT_SUBJECT,
                 True)
     solution = pyclipper.scale_from_clipper(
         pc.Execute(pyclipper.CT_INTERSECTION, pyclipper.PFT_EVENODD,
                    pyclipper.PFT_EVENODD))
     return solution
 def joinPolys(self, clip, subj):
     pc = pyclipper.Pyclipper()
     pc.AddPath(pyclipper.scale_to_clipper(clip), pyclipper.PT_CLIP, True)
     pc.AddPath(pyclipper.scale_to_clipper(subj), pyclipper.PT_SUBJECT,
                True)
     solution = pyclipper.scale_from_clipper(
         pc.Execute(pyclipper.CT_UNION, pyclipper.PFT_EVENODD,
                    pyclipper.PFT_EVENODD))
     return solution
Example #16
0
 def getClipSolutions(self, clip, subj):
     pc = pyclipper.Pyclipper()
     pc.AddPath(pyclipper.scale_to_clipper(clip), pyclipper.PT_CLIP, True)
     pc.AddPaths(pyclipper.scale_to_clipper(subj), pyclipper.PT_SUBJECT,
                 True)
     solution = pyclipper.scale_from_clipper(
         pc.Execute(pyclipper.CT_XOR, pyclipper.PFT_EVENODD,
                    pyclipper.PFT_EVENODD))
     return solution
Example #17
0
def find_common_coverage(locuses):
    clipper = Pyclipper()
    current_locus = locuses[0]
    for locus in locuses[1:]:
        clipper.AddPaths(scale_to_clipper(current_locus), PT_SUBJECT)
        clipper.AddPaths(scale_to_clipper(locus), PT_CLIP)
        current_locus = scale_from_clipper(clipper.Execute(CT_INTERSECTION))
        clipper.Clear()
    l_x, l_y = split_locus_lists([current_locus])
    return l_x, l_y
 def joinManyPolys(self, polys):
     pc = pyclipper.Pyclipper()
     pc.AddPath(pyclipper.scale_to_clipper(polys[0]), pyclipper.PT_CLIP,
                True)
     pc.AddPaths(pyclipper.scale_to_clipper(polys[1:]),
                 pyclipper.PT_SUBJECT, True)
     solution = pyclipper.scale_from_clipper(
         pc.Execute(pyclipper.CT_UNION, pyclipper.PFT_NONZERO,
                    pyclipper.PFT_NONZERO))
     return solution
Example #19
0
    def preprocess_obstacles(self, obstacle_list):
        inflation = pyclipper.scale_to_clipper(self.config.vehicle_width)
        inflated_obstacles = []
        for obs in obstacle_list:
            obstacle = pyclipper.scale_to_clipper(obs)
            inflated_obstacle = self.preprocess_obstacle(obstacle, inflation, boundary=False)
            inflated_obstacle.reverse() # obstacles are ordered clockwise
            inflated_obstacles.append(inflated_obstacle)

        return inflated_obstacles
Example #20
0
def computePath(leader_waypoints, offset_id = 1):
    leader_waypoints = [[w[0], w[1]] for w in leader_waypoints]
    OFFSET_CONSTANT = 2 * 70000
    ARC_TOLERANCE = 2000
    scaled_waypoints = []
    print leader_waypoints
    for wypt in leader_waypoints:
        scaled_waypoints.append([pyclipper.scale_to_clipper(wypt[0]), pyclipper.scale_to_clipper(wypt[1])])

    pco = pyclipper.PyclipperOffset(0, ARC_TOLERANCE)
    pco.AddPath(scaled_waypoints, pyclipper.JT_ROUND, pyclipper.ET_CLOSEDPOLYGON)
    
    scaled_path = pco.Execute(offset_id * OFFSET_CONSTANT) #pyclipper.scale_to_clipper(OFFSET_CONSTANT))
    unscaled_path = []
    for wypt in scaled_path[0]:
        unscaled_path.append([pyclipper.scale_from_clipper(wypt[0]), pyclipper.scale_from_clipper(wypt[1])])
    
    print scaled_path


    # gaphing here for visual check of correctness
    '''
    leader_x = []
    leader_y = []

    for waypoint in leader_waypoints:
        leader_x.append(waypoint[0])
        leader_y.append(waypoint[1])


    follower1_x = []
    follower1_y = []
    for waypoint in unscaled_path:
        follower1_x.append(waypoint[0])
        follower1_y.append(waypoint[1])

    for i in range(0, len(leader_x)):
        plt.plot(leader_x[i:i+2], leader_y[i:i+2], 'ro-')

    for i in range(0, len(follower1_x)):
        plt.plot(follower1_x[i:i+2], follower1_y[i:i+2], 'go-')

    plt.show()
    '''

    total_distance = 0
    for i in range(len(unscaled_path) - 1):
        total_distance += getDistanceMeters(unscaled_path[i][0], unscaled_path[i][1], unscaled_path[i + 1][0], unscaled_path[i + 1][1])
    
    shifted_unscaled_path = unscaled_path[16:] + unscaled_path[:16]
    output = {
        'waypoints': shifted_unscaled_path,
        'distance': total_distance
    }
    return output
Example #21
0
def diff(subj, clip_paths, subj_closed=True):
    pc = pyclipper.Pyclipper()
    if subj:
        subj = pyclipper.scale_to_clipper(subj, SCALING_FACTOR)
        pc.AddPaths(subj, pyclipper.PT_SUBJECT, subj_closed)
    if clip_paths:
        clip_paths = pyclipper.scale_to_clipper(clip_paths, SCALING_FACTOR)
        pc.AddPaths(clip_paths, pyclipper.PT_CLIP, True)
    outpaths = pc.Execute(pyclipper.CT_DIFFERENCE, pyclipper.PFT_EVENODD, pyclipper.PFT_EVENODD)
    outpaths = pyclipper.scale_from_clipper(outpaths, SCALING_FACTOR)
    return outpaths
Example #22
0
    def hatches(self, l=10, st=0.1, num=0):
        self.clean()
        b0 = self.bounds()
        b = [b0[0] - l, b0[1] - l, b0[2] + l, b0[3] + l]

        h = []
        ls = l / math.sqrt(2)
        sts = st / math.sqrt(2)
        i = 0

        if num % 2 == 0:
            x0 = b[0]
            while x0 < b[2] + b[3] - b[1]:
                x = x0
                y = b[1]
                while x > b[0] and y < b[3]:
                    x -= sts
                    y += sts
                    if i % 2 == 0:
                        h.append([[x, y], [x - ls, y - ls]])
                    else:
                        h.append([[x - ls, y - ls], [x, y]])
                    i += 1
                x0 += l * math.sqrt(2)
        else:
            x0 = b[0] - (b[3] - b[1])
            while x0 < b[2]:
                x = x0
                y = b[1]
                while y < b[3] and x < b[2]:
                    x += sts
                    y += sts
                    if i % 2 == 0:
                        h.append([[x, y], [x + ls, y - ls]])
                    else:
                        h.append([[x + ls, y - ls], [x, y]])
                    i += 1
                x0 += l * math.sqrt(2)

        def check_sp(sp, b):
            return b[0] < sp[0][0] < b[2] and b[1] < sp[0][1] < b[3] or b[
                0] < sp[1][0] < b[2] and b[1] < sp[1][1] < b[3]

        h = [sp for sp in h if check_sp(sp, b)]

        pc = pyclipper.Pyclipper()
        pc.AddPaths(pyclipper.scale_to_clipper(self.items), pyclipper.PT_CLIP,
                    True)
        pc.AddPaths(pyclipper.scale_to_clipper(h), pyclipper.PT_SUBJECT, False)
        solution = pc.Execute2(pyclipper.CT_INTERSECTION,
                               pyclipper.PFT_EVENODD, pyclipper.PFT_EVENODD)

        h = pyclipper.scale_from_clipper(pyclipper.PolyTreeToPaths(solution))
        return Path(h)
Example #23
0
 def offset(self, distance, offset_style=pyclipper.JT_MITER):
     # JT_MITER = 2
     # JT_ROUND = 1
     # JT_SQUARE = 0
     clipper_offset = pyclipper.PyclipperOffset()
     coordinates_scaled = pyclipper.scale_to_clipper(self.points)
     clipper_offset.AddPath(coordinates_scaled, offset_style,
                            pyclipper.ET_CLOSEDPOLYGON)
     new_coordinates = clipper_offset.Execute(
         pyclipper.scale_to_clipper(distance))
     new_coordinates_scaled = pyclipper.scale_from_clipper(new_coordinates)
     self.points = new_coordinates_scaled[0]
Example #24
0
def clip(subj_pts, clip_pts, scale=2**16):
    system = subj_pts[0].system
    clip_coords = [p.in_system(system).coords for p in clip_pts]
    subj_coords = [p.in_system(system).coords for p in subj_pts]

    pc = pyclipper.Pyclipper()
    pc.AddPath(pyclipper.scale_to_clipper(clip_coords, scale), pyclipper.PT_CLIP, True)
    pc.AddPath(pyclipper.scale_to_clipper(subj_coords, scale), pyclipper.PT_SUBJECT, True)

    solution = pc.Execute(pyclipper.CT_INTERSECTION, pyclipper.PFT_EVENODD, pyclipper.PFT_EVENODD)
    return [ImagePoint(coord, system)
            for coord in pyclipper.scale_from_clipper(solution, scale)[0]]
Example #25
0
def clip(subj, clip_paths, subj_closed=True):
    pc = pyclipper.Pyclipper()
    if subj:
        subj = pyclipper.scale_to_clipper(subj, SCALING_FACTOR)
        pc.AddPaths(subj, pyclipper.PT_SUBJECT, subj_closed)
    if clip_paths:
        clip_paths = pyclipper.scale_to_clipper(clip_paths, SCALING_FACTOR)
        pc.AddPaths(clip_paths, pyclipper.PT_CLIP, True)
    out_tree = pc.Execute2(pyclipper.CT_INTERSECTION, pyclipper.PFT_EVENODD, pyclipper.PFT_EVENODD)
    outpaths = pyclipper.PolyTreeToPaths(out_tree)
    outpaths = pyclipper.scale_from_clipper(outpaths, SCALING_FACTOR)
    return outpaths
def get_xor(first, second):
    """Takes two list of loops(list of(x, y) points), and returns the exclusive-or"""
    clipper = pyclipper.Pyclipper()  # pylint: disable=c-extension-no-member
    scaled_first = pyclipper.scale_to_clipper(first, SCALING_FACTOR)
    scaled_second = pyclipper.scale_to_clipper(second, SCALING_FACTOR)

    clipper.AddPaths(scaled_first, pyclipper.PT_SUBJECT)
    clipper.AddPaths(scaled_second, pyclipper.PT_CLIP)
    scaled_xor = clipper.Execute(pyclipper.CT_XOR)

    xor = pyclipper.scale_from_clipper(
        scaled_xor, SCALING_FACTOR)
    return xor
def get_union(first, second):
    """Takes two list of loops(list of(x, y) points), and returns the union"""
    clipper = pyclipper.Pyclipper()  # pylint: disable=c-extension-no-member
    scaled_first = pyclipper.scale_to_clipper(first, SCALING_FACTOR)
    scaled_second = pyclipper.scale_to_clipper(second, SCALING_FACTOR)

    clipper.AddPaths(scaled_first, pyclipper.PT_SUBJECT)
    clipper.AddPaths(scaled_second, pyclipper.PT_CLIP)
    scaled_union = clipper.Execute(pyclipper.CT_UNION)

    union = pyclipper.scale_from_clipper(
        scaled_union, SCALING_FACTOR)
    return union
Example #28
0
def InwardOffset(feature, output, thickness):
    coordinates = feature.points[:-1]
    pco = pyclipper.PyclipperOffset()
    coordsScaled = pyclipper.scale_to_clipper(coordinates)
    pco.AddPath(coordsScaled, pyclipper.JT_SQUARE, pyclipper.ET_CLOSEDPOLYGON)
    result = pco.Execute(pyclipper.scale_to_clipper(thickness))
    resultScaled = pyclipper.scale_from_clipper(result)

    resultScaledList = resultScaled[0]
    lastCoord = resultScaledList[0]

    resultScaledList.append(lastCoord)
    output.append(resultScaledList)
Example #29
0
    def _prepare_clipper(self, poly):
        """Prepare 2D polygons for clipping operations.

        :param poly: The clip polygon.
        :returns: A Pyclipper object.

        """
        s1 = pc.scale_to_clipper(self.vertices_list)
        s2 = pc.scale_to_clipper(poly.vertices_list)
        clipper = pc.Pyclipper()
        clipper.AddPath(s1, poly_type=pc.PT_SUBJECT, closed=True)
        clipper.AddPath(s2, poly_type=pc.PT_CLIP, closed=True)
        return clipper
Example #30
0
def prep_2D_polys(poly1, poly2):
    # type: (Polygon, Polygon) -> pc.Pyclipper
    """Prepare two 2D polygons for clipping operations.

    :param poly1: The subject polygon.
    :param poly2: The clip polygon.
    :returns: A Pyclipper object.
    """
    s1 = pc.scale_to_clipper(poly1.vertices_list)
    s2 = pc.scale_to_clipper(poly2.vertices_list)
    clipper = pc.Pyclipper()
    clipper.AddPath(s1, poly_type=pc.PT_SUBJECT, closed=True)
    clipper.AddPath(s2, poly_type=pc.PT_CLIP, closed=True)
    return clipper
Example #31
0
def bevel(curve, radius):
    """
    Imposes a minimum radius on a 2D curve.

    Args:
        curve (tuple): (x,y) points
        radius (int): the desired minimum radius

    Returns:
        beveled (tuple): (x,y) points with min radius
        """
    import pyclipper
    scale = 10000
    radius *= scale
    transposed = pyclipper.scale_to_clipper(list(zip(*curve)), scale=scale)

    pco = pyclipper.PyclipperOffset()
    pco.AddPath(transposed, pyclipper.JT_ROUND, pyclipper.ET_CLOSEDPOLYGON)
    inset = pco.Execute(-radius)[0]

    pco2 = pyclipper.PyclipperOffset()
    pco2.AddPath(inset, pyclipper.JT_ROUND, pyclipper.ET_CLOSEDPOLYGON)
    solution = pco2.Execute(radius)[0]
    # solution.pop(0) # TODO: decide if necessary

    beveled = pyclipper.scale_from_clipper(list(zip(*solution)), scale=scale)
    return beveled
def point_inside_loop(point, loop):
    """tests to see if a point is inside (1), on(-1), or outside (0) of a loop"""
    scaled_loop = pyclipper.scale_to_clipper(loop, SCALING_FACTOR)
    scaled_point = [int(point[0] * SCALING_FACTOR),
                    int(point[1] * SCALING_FACTOR)]
    is_point_inside = pyclipper.PointInPolygon(scaled_point, scaled_loop)
    return is_point_inside
Example #33
0
def bevel(curve, radius):
    """
    Imposes a minimum radius on a 2D curve.

    Args:
        curve (tuple): (x,y) points
        radius (int): the desired minimum radius

    Returns:
        beveled (tuple): (x,y) points with min radius
        """
    import pyclipper
    scale = 10000
    radius *= scale
    transposed = pyclipper.scale_to_clipper(list(zip(*curve)), scale=scale)

    pco = pyclipper.PyclipperOffset()
    pco.AddPath(transposed, pyclipper.JT_ROUND, pyclipper.ET_CLOSEDPOLYGON)
    inset = pco.Execute(-radius)[0]

    pco2 = pyclipper.PyclipperOffset()
    pco2.AddPath(inset, pyclipper.JT_ROUND, pyclipper.ET_CLOSEDPOLYGON)
    solution = pco2.Execute(radius)[0]
    # solution.pop(0) # TODO: decide if necessary

    beveled = pyclipper.scale_from_clipper(list(zip(*solution)), scale=scale)
    return beveled
def calculateImprint(tsf_file_left, tsf_file_right, path_to_write_left_segs, path_to_write_right_segs, th=0.5):
    paths_write = [path_to_write_left_segs,path_to_write_right_segs]

    for idx_path, path in enumerate([tsf_file_left, tsf_file_right]):
        file = open(path, 'r')
        reader = csv.DictReader(file, delimiter=',', quotechar='"')
        segs =[]
        currentSeg = []
        old_SID = 0
        for row in reader:
            SID = int(row['SID'])
            PID = int(row['PID'])
            cords = [float(row['x']), float(row['z']), float(row['y'])]
            if SID != old_SID:
                segs.append(currentSeg)
                currentSeg= []

            currentSeg.append(cords)
            old_SID = SID
        segs.append(currentSeg)
        file.close()

        segs = np.array(segs)
        segs = segs_cutoff(segs, th)

        segs = np.array([np.array([pts[:2] for pts in seg]) for seg in segs])

        signed_area = [sum((seg[np.r_[1:len(seg), 0],0]-seg[:,0])*(seg[np.r_[1:len(seg), 0],1]+seg[:,1]))/2. for seg in segs]
        to_reverse = [i for i,a in enumerate(signed_area) if a>0]
        for i in to_reverse:
            segs[i] = segs[i][::-1]


        union = pyclipper.scale_to_clipper(segs)
        clipper = pyclipper.Pyclipper()
        clipper.AddPaths(union, pyclipper.PT_CLIP, True)
        union = clipper.Execute(pyclipper.CT_UNION, pyclipper.PFT_NONZERO, pyclipper.PFT_NONZERO)
        union = pyclipper.scale_from_clipper(union)


        union2 = np.array(union)
        for i, u in enumerate(union2): union2[i]= np.array(union2[i])
        signed_area2 = [sum((seg[np.r_[1:len(seg), 0],0]-seg[:,0])*(seg[np.r_[1:len(seg), 0],1]+seg[:,1]))/2. for seg in union2]
        union_without_holes = union2[[i for i, a in enumerate(signed_area2) if a<0]]

        if idx_path == 0:
            segs_left = union_without_holes
        else:
            segs_right = union_without_holes

    for idx_side, segs in enumerate([segs_left, segs_right]):
        output_path = path_to_write_left_segs if idx_side==0 else path_to_write_right_segs
        write_segs_to_file(segs, output_path)


    return([path_to_write_left_segs, path_to_write_right_segs])
Example #35
0
def area(vset):
    """ This function calculates the area of the set of FRV or ARV """
    # Initialize A as it could be calculated iteratively
    A = 0
    # Check multiple exteriors
    if type(vset[0][0]) == list:
        # Calc every exterior separately
        for i in range(len(vset)):
            A += pyclipper.scale_from_clipper(pyclipper.scale_from_clipper(pyclipper.Area(pyclipper.scale_to_clipper(vset[i]))))
    else:
        # Single exterior
        A = pyclipper.scale_from_clipper(pyclipper.scale_from_clipper(pyclipper.Area(pyclipper.scale_to_clipper(vset))))
    return A
Example #36
0
def intersect_polygons(polygon1, polygon2):
    """
    Intersect two polygons.

    INPUT:

    - ``polygon1`` -- list of vertices in counterclockwise order
    - ``polygon2`` -- same

    OUTPUT:

    Vertices of the intersection in counterclockwise order.
    """
    # could be accelerated by removing the scale_to/from_clipper()
    subj, clip = (polygon1,), polygon2
    pc = Pyclipper()
    pc.AddPath(scale_to_clipper(clip), PT_CLIP)
    pc.AddPaths(scale_to_clipper(subj), PT_SUBJECT)
    solution = pc.Execute(CT_INTERSECTION)
    if not solution:
        return []
    return scale_from_clipper(solution)[0]
Example #37
0
def constructSSD(asas, traf, priocode = "RS1"):
    """ Calculates the FRV and ARV of the SSD """
    N = 0
    # Parameters
    N_angle = 180                   # [-] Number of points on circle (discretization)
    vmin    = asas.vmin             # [m/s] Defined in asas.py
    vmax    = asas.vmax             # [m/s] Defined in asas.py
    hsep    = asas.R                # [m] Horizontal separation (5 NM)
    margin  = asas.mar              # [-] Safety margin for evasion
    hsepm   = hsep * margin         # [m] Horizontal separation with safety margin
    alpham  = 0.4999 * np.pi        # [rad] Maximum half-angle for VO
    betalos = np.pi / 4             # [rad] Minimum divertion angle for LOS (45 deg seems optimal)
    adsbmax = 65. * nm              # [m] Maximum ADS-B range
    beta    =  np.pi/4 + betalos/2
    if priocode == "RS7" or priocode == "RS8":
        adsbmax /= 2

    # Relevant info from traf
    gsnorth = traf.gsnorth
    gseast  = traf.gseast
    lat     = traf.lat
    lon     = traf.lon
    ntraf   = traf.ntraf
    hdg     = traf.hdg
    gs_ap   = traf.ap.tas
    hdg_ap  = traf.ap.trk
    apnorth = np.cos(hdg_ap / 180 * np.pi) * gs_ap
    apeast  = np.sin(hdg_ap / 180 * np.pi) * gs_ap

    # Local variables, will be put into asas later
    FRV_loc          = [None] * traf.ntraf
    ARV_loc          = [None] * traf.ntraf
    # For calculation purposes
    ARV_calc_loc     = [None] * traf.ntraf
    FRV_area_loc     = np.zeros(traf.ntraf, dtype=np.float32)
    ARV_area_loc     = np.zeros(traf.ntraf, dtype=np.float32)

    # # Use velocity limits for the ring-shaped part of the SSD
    # Discretize the circles using points on circle
    angles = np.arange(0, 2 * np.pi, 2 * np.pi / N_angle)
    # Put points of unit-circle in a (180x2)-array (CW)
    xyc = np.transpose(np.reshape(np.concatenate((np.sin(angles), np.cos(angles))), (2, N_angle)))
    # Map them into the format pyclipper wants. Outercircle CCW, innercircle CW
    circle_tup = (tuple(map(tuple, np.flipud(xyc * vmax))), tuple(map(tuple , xyc * vmin)))
    circle_lst = [list(map(list, np.flipud(xyc * vmax))), list(map(list , xyc * vmin))]

    # If no traffic
    if ntraf == 0:
        return

    # If only one aircraft
    elif ntraf == 1:
        # Map them into the format ARV wants. Outercircle CCW, innercircle CW
        ARV_loc[0] = circle_lst
        FRV_loc[0] = []
        ARV_calc_loc[0] = ARV_loc[0]
        # Calculate areas and store in asas
        FRV_area_loc[0] = 0
        ARV_area_loc[0] = np.pi * (vmax **2 - vmin ** 2)
        return

    # Function qdrdist_matrix needs 4 vectors as input (lat1,lon1,lat2,lon2)
    # To be efficient, calculate all qdr and dist in one function call
    # Example with ntraf = 5:   ind1 = [0,0,0,0,1,1,1,2,2,3]
    #                           ind2 = [1,2,3,4,2,3,4,3,4,4]
    # This way the qdrdist is only calculated once between every aircraft
    # To get all combinations, use this function to get the indices
    ind1, ind2 = qdrdist_matrix_indices(ntraf)
    # Get absolute bearing [deg] and distance [nm]
    # Not sure abs/rel, but qdr is defined from [-180,180] deg, w.r.t. North
    [qdr, dist] = geo.qdrdist_matrix(lat[ind1], lon[ind1], lat[ind2], lon[ind2])
    # Put result of function from matrix to ndarray
    qdr  = np.reshape(np.array(qdr), np.shape(ind1))
    dist = np.reshape(np.array(dist), np.shape(ind1))
    # SI-units from [deg] to [rad]
    qdr  = np.deg2rad(qdr)
    # Get distance from [nm] to [m]
    dist = dist * nm

    # In LoS the VO can't be defined, act as if dist is on edge
    dist[dist < hsepm] = hsepm

    # Calculate vertices of Velocity Obstacle (CCW)
    # These are still in relative velocity space, see derivation in appendix
    # Half-angle of the Velocity obstacle [rad]
    # Include safety margin
    alpha = np.arcsin(hsepm / dist)
    # Limit half-angle alpha to 89.982 deg. Ensures that VO can be constructed
    alpha[alpha > alpham] = alpham
    # Relevant sin/cos/tan
    sinqdr = np.sin(qdr)
    cosqdr = np.cos(qdr)
    tanalpha = np.tan(alpha)
    cosqdrtanalpha = cosqdr * tanalpha
    sinqdrtanalpha = sinqdr * tanalpha

    # Relevant x1,y1,x2,y2 (x0 and y0 are zero in relative velocity space)
    x1 = (sinqdr + cosqdrtanalpha) * 2 * vmax
    x2 = (sinqdr - cosqdrtanalpha) * 2 * vmax
    y1 = (cosqdr - sinqdrtanalpha) * 2 * vmax
    y2 = (cosqdr + sinqdrtanalpha) * 2 * vmax

    # Consider every aircraft
    for i in range(ntraf):
        # Calculate SSD only for aircraft in conflict (See formulas appendix)
        if asas.inconf[i]:
            # SSD for aircraft i
            # Get indices that belong to aircraft i
            ind = np.where(np.logical_or(ind1 == i,ind2 == i))[0]
            # Check whether there are any aircraft in the vicinity
            if len(ind) == 0:
                # No aircraft in the vicinity
                # Map them into the format ARV wants. Outercircle CCW, innercircle CW
                ARV_loc[i] = circle_lst
                FRV_loc[i] = []
                ARV_calc_loc[i] = ARV_loc[i]
                # Calculate areas and store in asas
                FRV_area_loc[i] = 0
                ARV_area_loc[i] = np.pi * (vmax **2 - vmin ** 2)
            else:
                # The i's of the other aircraft
                i_other = np.delete(np.arange(0, ntraf), i)
                # Aircraft that are within ADS-B range
                ac_adsb = np.where(dist[ind] < adsbmax)[0]
                # Now account for ADS-B range in indices of other aircraft (i_other)
                ind = ind[ac_adsb]
                i_other = i_other[ac_adsb]
                if not priocode == "RS7" and not priocode == "RS8":
                    # Put it in class-object (not for RS7 and RS8)
                    asas.inrange[i]  = i_other
                else:
                    asas.inrange2[i] = i_other
                # VO from 2 to 1 is mirror of 1 to 2. Only 1 to 2 can be constructed in
                # this manner, so need a correction vector that will mirror the VO
                fix = np.ones(np.shape(i_other))
                fix[i_other < i] = -1
                # Relative bearing [deg] from [-180,180]
                # (less required conversions than rad in RotA)
                fix_ang = np.zeros(np.shape(i_other))
                fix_ang[i_other < i] = 180.


                # Get vertices in an x- and y-array of size (ntraf-1)*3x1
                x = np.concatenate((gseast[i_other],
                                    x1[ind] * fix + gseast[i_other],
                                    x2[ind] * fix + gseast[i_other]))
                y = np.concatenate((gsnorth[i_other],
                                    y1[ind] * fix + gsnorth[i_other],
                                    y2[ind] * fix + gsnorth[i_other]))
                # Reshape [(ntraf-1)x3] and put arrays in one array [(ntraf-1)x3x2]
                x = np.transpose(x.reshape(3, np.shape(i_other)[0]))
                y = np.transpose(y.reshape(3, np.shape(i_other)[0]))
                xy = np.dstack((x,y))

                # Make a clipper object
                pc = pyclipper.Pyclipper()
                # Add circles (ring-shape) to clipper as subject
                pc.AddPaths(pyclipper.scale_to_clipper(circle_tup), pyclipper.PT_SUBJECT, True)

                # Extra stuff needed for RotA
                if priocode == "RS6":
                    # Make another clipper object for RotA
                    pc_rota = pyclipper.Pyclipper()
                    pc_rota.AddPaths(pyclipper.scale_to_clipper(circle_tup), pyclipper.PT_SUBJECT, True)
                    # Bearing calculations from own view and other view
                    brg_own = np.mod((np.rad2deg(qdr[ind]) + fix_ang - hdg[i]) + 540., 360.) - 180.
                    brg_other = np.mod((np.rad2deg(qdr[ind]) + 180. - fix_ang - hdg[i_other]) + 540., 360.) - 180.

                # Add each other other aircraft to clipper as clip
                for j in range(np.shape(i_other)[0]):
                    ## Debug prints
                    ## print(traf.id[i] + " - " + traf.id[i_other[j]])
                    ## print(dist[ind[j]])
                    # Scale VO when not in LOS
                    if dist[ind[j]] > hsepm:
                        # Normally VO shall be added of this other a/c
                        VO = pyclipper.scale_to_clipper(tuple(map(tuple,xy[j,:,:])))
                    else:
                        # Pair is in LOS, instead of triangular VO, use darttip
                        # Check if bearing should be mirrored
                        if i_other[j] < i:
                            qdr_los = qdr[ind[j]] + np.pi
                        else:
                            qdr_los = qdr[ind[j]]
                        # Length of inner-leg of darttip
                        leg = 1.1 * vmax / np.cos(beta) * np.array([1,1,1,0])
                        # Angles of darttip
                        angles_los = np.array([qdr_los + 2 * beta, qdr_los, qdr_los - 2 * beta, 0.])
                        # Calculate coordinates (CCW)
                        x_los = leg * np.sin(angles_los)
                        y_los = leg * np.cos(angles_los)
                        # Put in array of correct format
                        xy_los = np.vstack((x_los,y_los)).T
                        # Scale darttip
                        VO = pyclipper.scale_to_clipper(tuple(map(tuple,xy_los)))
                    # Add scaled VO to clipper
                    pc.AddPath(VO, pyclipper.PT_CLIP, True)
                    # For RotA it is possible to ignore
                    if priocode == "RS6":
                        if brg_own[j] >= -20. and brg_own[j] <= 110.:
                            # Head-on or converging from right
                            pc_rota.AddPath(VO, pyclipper.PT_CLIP, True)
                        elif brg_other[j] <= -110. or brg_other[j] >= 110.:
                            # In overtaking position
                            pc_rota.AddPath(VO, pyclipper.PT_CLIP, True)
                    # Detect conflicts for smaller layer in RS7 and RS8
                    if priocode == "RS7" or priocode == "RS8":
                        if pyclipper.PointInPolygon(pyclipper.scale_to_clipper((gseast[i],gsnorth[i])),VO):
                            asas.inconf2[i] = True
                    if priocode == "RS5":
                        if pyclipper.PointInPolygon(pyclipper.scale_to_clipper((apeast[i],apnorth[i])),VO):
                            asas.ap_free[i] = False

                # Execute clipper command
                FRV = pyclipper.scale_from_clipper(pc.Execute(pyclipper.CT_INTERSECTION, pyclipper.PFT_NONZERO, pyclipper.PFT_NONZERO))

                ARV = pc.Execute(pyclipper.CT_DIFFERENCE, pyclipper.PFT_NONZERO, pyclipper.PFT_NONZERO)

                if not priocode == "RS1" and not priocode == "RS5" and not priocode == "RS7" and not priocode == "RS8":
                    # Make another clipper object for extra intersections
                    pc2 = pyclipper.Pyclipper()
                    # When using RotA clip with pc_rota
                    if priocode == "RS6":
                        # Calculate ARV for RotA
                        ARV_rota = pc_rota.Execute(pyclipper.CT_DIFFERENCE, pyclipper.PFT_NONZERO, pyclipper.PFT_NONZERO)
                        if len(ARV_rota) > 0:
                            pc2.AddPaths(ARV_rota, pyclipper.PT_CLIP, True)
                    else:
                        # Put the ARV in there, make sure it's not empty
                        if len(ARV) > 0:
                            pc2.AddPaths(ARV, pyclipper.PT_CLIP, True)

                # Scale back
                ARV = pyclipper.scale_from_clipper(ARV)

                # Check if ARV or FRV is empty
                if len(ARV) == 0:
                    # No aircraft in the vicinity
                    # Map them into the format ARV wants. Outercircle CCW, innercircle CW
                    ARV_loc[i] = []
                    FRV_loc[i] = circle_lst
                    ARV_calc_loc[i] = []
                    # Calculate areas and store in asas
                    FRV_area_loc[i] = np.pi * (vmax **2 - vmin ** 2)
                    ARV_area_loc[i] = 0
                elif len(FRV) == 0:
                    # Should not happen with one a/c or no other a/c in the vicinity.
                    # These are handled earlier. Happens when RotA has removed all
                    # Map them into the format ARV wants. Outercircle CCW, innercircle CW
                    ARV_loc[i] = circle_lst
                    FRV_loc[i] = []
                    ARV_calc_loc[i] = circle_lst
                    # Calculate areas and store in asas
                    FRV_area_loc[i] = 0
                    ARV_area_loc[i] = np.pi * (vmax **2 - vmin ** 2)
                else:
                    # Check multi exteriors, if this layer is not a list, it means it has no exteriors
                    # In that case, make it a list, such that its format is consistent with further code
                    if not type(FRV[0][0]) == list:
                        FRV = [FRV]
                    if not type(ARV[0][0]) == list:
                        ARV = [ARV]
                    # Store in asas
                    FRV_loc[i] = FRV
                    ARV_loc[i] = ARV
                    # Calculate areas and store in asas
                    FRV_area_loc[i] = area(FRV)
                    ARV_area_loc[i] = area(ARV)

                    # For resolution purposes sometimes extra intersections are wanted
                    if priocode == "RS2" or priocode == "RS9" or priocode == "RS6" or priocode == "RS3" or priocode == "RS4":
                        # Make a box that covers right or left of SSD
                        own_hdg = hdg[i] * np.pi / 180
                        # Efficient calculation of box, see notes
                        if priocode == "RS2" or priocode == "RS6":
                            # CW or right-turning
                            sin_table = np.array([[1,0],[-1,0],[-1,-1],[1,-1]], dtype=np.float64)
                            cos_table = np.array([[0,1],[0,-1],[1,-1],[1,1]], dtype=np.float64)
                        elif priocode == "RS9":
                            # CCW or left-turning
                            sin_table = np.array([[1,0],[1,1],[-1,1],[-1,0]], dtype=np.float64)
                            cos_table = np.array([[0,1],[-1,1],[-1,-1],[0,-1]], dtype=np.float64)
                        # Overlay a part of the full SSD
                        if priocode == "RS2" or priocode == "RS9" or priocode == "RS6":
                            # Normalized coordinates of box
                            xyp = np.sin(own_hdg) * sin_table + np.cos(own_hdg) * cos_table
                            # Scale with vmax (and some factor) and put in tuple
                            part = pyclipper.scale_to_clipper(tuple(map(tuple, 1.1 * vmax * xyp)))
                            pc2.AddPath(part, pyclipper.PT_SUBJECT, True)
                        elif priocode == "RS3":
                            # Small ring
                            xyp = (tuple(map(tuple, np.flipud(xyc * min(vmax,gs_ap[i] + 0.1)))), tuple(map(tuple , xyc * max(vmin,gs_ap[i] - 0.1))))
                            part = pyclipper.scale_to_clipper(xyp)
                            pc2.AddPaths(part, pyclipper.PT_SUBJECT, True)
                        elif priocode == "RS4":
                            hdg_sel = hdg[i] * np.pi / 180
                            xyp = np.array([[np.sin(hdg_sel-0.0087),np.cos(hdg_sel-0.0087)],
                                            [0,0],
                                            [np.sin(hdg_sel+0.0087),np.cos(hdg_sel+0.0087)]],
                                            dtype=np.float64)
                            part = pyclipper.scale_to_clipper(tuple(map(tuple, 1.1 * vmax * xyp)))
                            pc2.AddPath(part, pyclipper.PT_SUBJECT, True)
                        # Execute clipper command
                        ARV_calc = pyclipper.scale_from_clipper(pc2.Execute(pyclipper.CT_INTERSECTION, pyclipper.PFT_NONZERO, pyclipper.PFT_NONZERO))
                        N += 1
                        # If no smaller ARV is found, take the full ARV
                        if len(ARV_calc) == 0:
                            ARV_calc = ARV
                        # Check multi exteriors, if this layer is not a list, it means it has no exteriors
                        # In that case, make it a list, such that its format is consistent with further code
                        if not type(ARV_calc[0][0]) == list:
                            ARV_calc = [ARV_calc]
                    # Shortest way out prio, so use full SSD (ARV_calc = ARV)
                    else:
                        ARV_calc = ARV
                    # Update calculatable ARV for resolutions
                    ARV_calc_loc[i] = ARV_calc

    # If sequential approach, the local should go elsewhere
    if not priocode == "RS7" and not priocode == "RS8":
        asas.FRV          = FRV_loc
        asas.ARV          = ARV_loc
        asas.ARV_calc     = ARV_calc_loc
        asas.FRV_area     = FRV_area_loc
        asas.ARV_area     = ARV_area_loc
    else:
        asas.ARV_calc2    = ARV_calc_loc
    return
def calculateStatistics(path_to_imprint_file_left,
                        path_to_imprint_file_right,
                        path_to_zones_left,
                        path_to_zones_right,
                        path_to_transform_imprint,
                        path_to_transform_left_zones,
                        path_to_transform_right_zones,
                        path_to_pressure_data,
                        path_to_pressure_metadata,
                        path_to_write_statistics):

    transform_imprint = np.matrix(np.loadtxt(path_to_transform_imprint, delimiter=","))
    transform_left_zones = np.loadtxt(path_to_transform_left_zones, delimiter=",")
    transform_right_zones = np.loadtxt(path_to_transform_right_zones, delimiter=",")

    segs_left_orig = segs_from_file(path_to_imprint_file_left)
    segs_right_orig = segs_from_file(path_to_imprint_file_right)
    segs_zones_left_orig = segs_from_file(path_to_zones_left)
    segs_zones_right_orig = segs_from_file(path_to_zones_right)

    segs_left = transformSegments(segs_left_orig, transform_imprint)
    segs_right = transformSegments(segs_right_orig, transform_imprint)
    segs_zones_left = transformSegments(segs_zones_left_orig, transform_left_zones)
    segs_zones_right = transformSegments(segs_zones_right_orig, transform_right_zones)

    col_spacing = 0.5
    row_spacing = 0.5

    with open(path_to_pressure_metadata, "rb") as metadata_file:
        reader = csv.DictReader(metadata_file)
        for row in reader:
            variable = row["variable"]
            value = row["value"]
            if str(variable).lower()=="COL_SPACING".lower():
                col_spacing = float(value)
            elif str(variable).lower()=="ROW_SPACING".lower():
                row_spacing = float(value)
            elif str(variable).lower() == "UNITS".lower():
                units = value

    with open(path_to_pressure_data, "rb") as pressure_file:
        reader = csv.reader(pressure_file)
        header = reader.next()
        pressure_data = []
        for row in reader:
            pressure_data.append([float(val) for val in row])

    pressure_data = np.array(pressure_data)
    pressure_data_x_col = next(i for i, var in enumerate(header) if var=="x")
    pressure_data_y_col = next(i for i, var in enumerate(header) if var == "y")
    pressure_data_pressure_col = next(i for i, var in enumerate(header) if var == "pressure")

    pressure_data_not_null = pressure_data[pressure_data[:,pressure_data_pressure_col]!=0]

    pressure_meas = []
    area = []
    area_intersect = []
    sensor_segs = []
    sensor_clipped_against_imprint_scaled_for_clipper = []

    pc = pyclipper.Pyclipper()

    for row in pressure_data_not_null:
        x = row[pressure_data_x_col]
        y = row[pressure_data_y_col]
        subj = ((x-row_spacing/2., y-col_spacing/2.),
                (x+row_spacing/2., y-col_spacing/2.),
                (x+row_spacing/2., y+col_spacing/2.),
                (x-row_spacing/2., y+col_spacing/2.))

        sensor_segs.append(subj)

        ar = col_spacing*row_spacing
        area.append(ar)
        pressure_meas.append(row[pressure_data_pressure_col]*ar)

        # clip against segments
        # left
        pc.Clear()
        pc.AddPaths(pyclipper.scale_to_clipper(segs_left), pyclipper.PT_CLIP, True)
        pc.AddPaths(pyclipper.scale_to_clipper(segs_right), pyclipper.PT_CLIP, True)
        pc.AddPath(pyclipper.scale_to_clipper(subj), pyclipper.PT_SUBJECT, True)
        sol = pc.Execute(pyclipper.CT_INTERSECTION, pyclipper.PFT_NONZERO, pyclipper.PFT_NONZERO)

        sensor_clipped_against_imprint_scaled_for_clipper.append(sol)
        sol_for_ar = np.array([np.array(seg) for seg in pyclipper.scale_from_clipper(sol)])
        ar_intersect = sum(abs(np.array([sum((seg[np.r_[1:len(seg), 0],0]-seg[:,0])*(seg[np.r_[1:len(seg), 0],1]+seg[:,1]))/2. for seg in sol_for_ar])))

        area_intersect.append(ar_intersect)

    pc.Clear()

    area_zones = [[abs(sum((seg[np.r_[1:len(seg), 0],0]-seg[:,0])*(seg[np.r_[1:len(seg), 0],1]+seg[:,1]))/2.) for seg in np.array(segs)] for segs in (segs_zones_left, segs_zones_right)]

    area_intersect_zones=[[],[]]
    for side in (0, 1):
        segs_zone = segs_zones_left if side == 0 else segs_zones_right
        for seg_zone in segs_zone:
            ar_segment_with_pressure_points = []
            for sensor_clipped_segs in sensor_clipped_against_imprint_scaled_for_clipper:
                if sensor_clipped_segs!=[]:
                    pc.Clear()
                    pc.AddPath(pyclipper.scale_to_clipper(seg_zone), pyclipper.PT_CLIP, True)
                    pc.AddPaths(sensor_clipped_segs, pyclipper.PT_SUBJECT, True)
                    sol = pc.Execute(pyclipper.CT_INTERSECTION, pyclipper.PFT_NONZERO, pyclipper.PFT_NONZERO)
                    sol_for_ar = np.array([np.array(seg) for seg in pyclipper.scale_from_clipper(sol)])
                    ar = sum(abs(np.array([sum((seg[np.r_[1:len(seg), 0],0]-seg[:,0])*(seg[np.r_[1:len(seg), 0],1]+seg[:,1]))/2. for seg in sol_for_ar])))
                else:
                    ar = 0
                ar_segment_with_pressure_points.append(ar)
            area_intersect_zones[side].append(ar_segment_with_pressure_points)

    area_zones_clipped_against_imprint = [[],[]]
    for side in (0, 1):
        segs_zone = segs_zones_left if side == 0 else segs_zones_right
        segs_imprint = segs_left if side == 0 else segs_right
        for seg_zone in segs_zone:
            pc.Clear()
            pc.AddPath(pyclipper.scale_to_clipper(seg_zone), pyclipper.PT_CLIP, True)
            pc.AddPaths(pyclipper.scale_to_clipper(segs_imprint), pyclipper.PT_SUBJECT, True)
            sol = pc.Execute(pyclipper.CT_INTERSECTION, pyclipper.PFT_NONZERO, pyclipper.PFT_NONZERO)
            sol_for_ar = np.array([np.array(seg) for seg in pyclipper.scale_from_clipper(sol)])
            ar = sum(abs(np.array([sum((seg[np.r_[1:len(seg), 0],0]-seg[:,0])*(seg[np.r_[1:len(seg), 0],1]+seg[:,1]))/2. for seg in sol_for_ar])))
            area_zones_clipped_against_imprint[side].append(ar)



    pressure_calculated_for_zones = [[sum([(ar_zone[k]/area_intersect[k])*pressure_meas[k] if area_intersect[k]!=0 else 0 for k in range(0, len(area_intersect))]) for j, ar_zone in enumerate(ar_zones_s)] for i, ar_zones_s in enumerate(area_intersect_zones)]

    pressure_all = sum(pressure_meas)


    if path_to_write_statistics!="":
        with open(path_to_write_statistics, 'w') as statistics_file:
            statistics_file.write('side,'
                                  'SID,'
                                  'force,'
                                  'force_rel_to_all,'
                                  'force_rel_to_side,'
                                  'force_rel_to_area,'
                                  'area,'
                                  'area_unclipped,'
                                  'area_with_pressure,'
                                  'area_with_pressure_unclipped'
                                  '\n')
            for side_idx in (0,1):
                side = "left" if side_idx==0 else "right"
                segs_zone = segs_zones_left if side_idx==0 else segs_zones_right
                pressure_side =sum(pressure_calculated_for_zones[side_idx])

                for sid in range(0, len(segs_zone)):
                    area_clipped = area_zones_clipped_against_imprint[side_idx][sid]
                    area_unclipped = area_zones[side_idx][sid]
                    area_with_pressure_clipped = sum(area_intersect_zones[side_idx][sid])
                    area_with_pressure_unclipped =sum([1 if a >0 else 0 for a in area_intersect_zones[side_idx][sid]])*row_spacing*col_spacing
                    pressure = pressure_calculated_for_zones[side_idx][sid]
                    statistics_file.write('"{}",{},{},{},{},{},{},{},{},{}\n'.format(
                        side,
                        sid,
                        pressure,
                        (pressure/pressure_all),
                        (pressure/pressure_side),
                        (pressure/area_clipped),
                        area_clipped,
                        area_unclipped,
                        area_with_pressure_clipped,
                        area_with_pressure_unclipped
                    ))




    return(pressure_calculated_for_zones)
Example #39
0
        area += corners[i][0] * corners[j][1]
        area -= corners[j][0] * corners[i][1]
    area = abs(area) / 2.0
    return area

#Remove too big regions
regions = filter(lambda region: area([vor.vertices[r] for r in region]) < 3, regions)

#Assemble extruded sections
print "Building openscad file"

holes = []
for region in regions:
    verts = [vor.vertices[r] for r in region]
    pco = pyclipper.PyclipperOffset()
    pco.AddPath( pyclipper.scale_to_clipper( [[v[0], v[1]] for v in verts] ), pyclipper.JT_MITER, pyclipper.ET_CLOSEDPOLYGON )

    p2 = pyclipper.scale_from_clipper( pco.Execute( pyclipper.scale_to_clipper( -.1 ) ) )
    cutout = union() ( [down( 1 ) ( linear_extrude( height=h+2 ) (
        polygon( points=path )
    )) for path in p2] )

    holes.append( cutout )

# Add Frame
parts = cube( [width, height, 1] ) - holes
parts += cube( [width, height, 1] ) - translate( [1, 1, -1] ) ( cube( [width-2, height-2, 3] ) )

print "Saving File"
with open( __file__ + ".scad", "w" ) as f:
    f.write( scad_render( union() ( parts ) ) )