def make_prototype(triangles, spot_based=True): trans_triangles = [] for t in triangles: # Centralize the triangle in the plane t += np.array([250.0, 250.0]) - geometry.centroid(t) # If non-spot-based pototype is requested, swap the vertices around so that vertex 1 is # the pointiest one. if spot_based == False: angles = [geometry.angle(t,1), geometry.angle(t,2), geometry.angle(t,3)] min_angle = angles.index(min(angles)) if min_angle == 0: t = np.array([t[0], t[1], t[2]]) elif min_angle == 1: t = np.array([t[1], t[2], t[0]]) elif min_angle == 2: t = np.array([t[2], t[0], t[1]]) # Rotate the triangle around its centroid so that vertex 1 points North t = geometry.rotate(t) # Ensure that vertex 2 is to the left of vertex 3 to prevent cancelling out if t[1,0] > t[2,0]: t = np.array([t[0], t[2], t[1]]) trans_triangles.append(t) # Reformat as Numpy array and take the mean of the coordinates to form the prototype trans_triangles = np.asarray(trans_triangles, dtype=float) prototype = trans_triangles.mean(axis=0) # Shift the prototype such that its bounding box is vertically centralized in the plane prototype[:, 1] += ((500.0 - (max([prototype[1,1], prototype[2,1]]) - prototype[0,1])) / 2.0) - prototype[0,1] return prototype
def get_angle(point1, point2, point3, rad=False): """ Get the angle between three points """ vec1 = geometry.create_vector([point1[i] - point2[i] for i in range(3)]) vec2 = geometry.create_vector([point3[i] - point2[i] for i in range(3)]) if rad: return geometry.angle(vec1, vec2) else: return 360*geometry.angle(vec1, vec2)/(2*pi)
def get_angle(point1, point2, point3, rad=False): """ Get the angle between three points """ vec1 = geometry.create_vector([point1[i] - point2[i] for i in range(3)]) vec2 = geometry.create_vector([point3[i] - point2[i] for i in range(3)]) if rad: return geometry.angle(vec1, vec2) else: return 360 * geometry.angle(vec1, vec2) / (2 * pi)
def __init__(self, center, headEdges, arms, vertexMapping, weight): self.weight = weight # TODO:decide self.headEdges = set(headEdges) self.arms = arms self.armEdges = set(chain(*map(lambda arm: map(lambda v1, v2: tuple(sorted([v1, v2])),arm[:-1],arm[1:]), arms))) self.deepestPoint = center #Wedge.__deepestPoint(self, arms, vertexMapping, center) # order vertices clockwise verts = map(lambda arm: vertexMapping[arm[-1],:], arms) if angle(verts[0]-self.deepestPoint,verts[1]-self.deepestPoint,0,True) < angle(verts[0]-self.deepestPoint,verts[2]-self.deepestPoint, 0, True): self.vertices = np.array(verts) else: self.vertices = np.array(list(reversed(verts)))
def f_vector(database,choice): # CONSTRUCTING FEATURE VECTORS if choice == 0: vector = [] for i in range(len(database)): temp = [] dist_d = geometry.distance(database[i][10],database[i][11],database[i][12],database[i][16],database[i][17],database[i][18]) temp.append(dist_d) dist_D = geometry.distance(database[i][4],database[i][5],database[i][6],database[i][16],database[i][17],database[i][18]) temp.append(dist_D) ang_th = geometry.angle(database[i][4]-database[i][10],database[i][5]-database[i][11],database[i][6]-database[i][12],database[i][16]-database[i][10],database[i][17]-database[i][11],database[i][18]-database[i][12]) temp.append(ang_th) if database[i][19] == 'YES': temp.append('YES') vector.append(temp) elif database[i][19] == 'NO': temp.append('NO') vector.append(temp) return vector elif choice == 1: vector = [] for i in range(len(database)): temp = [] dist_d = geometry.distance(database[i][10],database[i][11],database[i][12],database[i][16],database[i][17],database[i][18]) temp.append(dist_d) dist_D = geometry.distance(database[i][4],database[i][5],database[i][6],database[i][16],database[i][17],database[i][18]) temp.append(dist_D) ang_th = geometry.angle(database[i][4]-database[i][10],database[i][5]-database[i][11],database[i][6]-database[i][12],database[i][16]-database[i][10],database[i][17]-database[i][11],database[i][18]-database[i][12]) temp.append(ang_th) vector.append(temp) return vector
def fits_cross_motif(self, pJ, p0, p1, p2 ): ''' compares the angle p1-p0-pJ. p0 is the point being extended and pJ is the point being considered. Returns true if the following conditions are true: the distance d (p0-pJ) is c*(1-delta) < d < c*(1+delta) where c is critdist() the angle p1-p0-pJ is within rho degrees of 90 the angle p1-p0-pJ is within rho_strict degrees of the angle p1-p0-p2 ''' if GridPoint(pJ) in self.connectivity: return False c = self.critdist() distance_cond = within_distance(c, p0, pJ, self.delta) angle_cond = is_perpend(pJ-p0, p1-p0, self.rho_loose) #angle_cond = True rel_angle_cond = (np.abs( angle(pJ-p0, p1-p0) - angle(p1-p0, p2-p0) ) < self.rho) #rel_angle_cond = True return (distance_cond and angle_cond and rel_angle_cond)
def contains_wn(self, point): size = len(self.vertices) if size == 0: return False s = 0.0 for i in range(0, size - 1): v1 = self.vertices[i].p if point == v1: return True v2 = self.vertices[i + 1].p if point == v2: return True if ccw(point, v1, v2): s += angle(v1, point, v2) else: s -= angle(v1, point, v2) s = s.real print(s) print(fabs(fabs(s) - 2 * PI)) return fabs(fabs(s) - 2 * PI) < EPS
def fits_cross_motif(self, pJ, p0, p1, p2): ''' compares the angle p1-p0-pJ. p0 is the point being extended and pJ is the point being considered. Returns true if the following conditions are true: the distance d (p0-pJ) is c*(1-delta) < d < c*(1+delta) where c is critdist() the angle p1-p0-pJ is within rho degrees of 90 the angle p1-p0-pJ is within rho_strict degrees of the angle p1-p0-p2 ''' if GridPoint(pJ) in self.connectivity: return False c = self.critdist() distance_cond = within_distance(c, p0, pJ, self.delta) angle_cond = is_perpend(pJ - p0, p1 - p0, self.rho_loose) #angle_cond = True rel_angle_cond = ( np.abs(angle(pJ - p0, p1 - p0) - angle(p1 - p0, p2 - p0)) < self.rho) #rel_angle_cond = True return (distance_cond and angle_cond and rel_angle_cond)
def calc_angular_error(self): ''' Compute the angular error between the cursor movement from one task loop iteration to the next (typically at 60 Hz). Angular error is with reference to the straight line between the cursor and the target ''' # compute angles for each trial cursor = self.hdf.root.task[:]['cursor'] target = self.hdf.root.task[:]['target'] cursor_vel = np.diff(cursor, axis=0) int_dir = target - cursor dist_to_targ = np.array(map(np.linalg.norm, int_dir)) window_angle = np.arctan2(self.target_radius, dist_to_targ) import geometry angles = geometry.angle(int_dir[:-1], cursor_vel, axis=0) angles = angles - window_angle[:-1] angles[angles < 0] = 0 angles = np.hstack([angles, np.nan]) return angles
def find_init_pts(init_coords, dist=25, min_angle=10): n_p = init_coords.shape[0] As = np.zeros(n_p) for k in range(n_p): p0 = init_coords[k, :] p1, p2 = find_neighbors(p0, init_coords, 2) if (norm(p1 - p0) < dist) and (norm(p2 - p0) < dist): As[k] = angle(p1 - p0, p2 - p0) elif (sum(p1 == p0) == 3) or (sum(p2 == p0) == 3): As[k] = 400 else: As[k] = 500 As[np.where(np.isnan(As))]=np.inf if np.abs(As - 90).min() < min_angle: p0 = init_coords[np.abs(As - 90).argmin(), :] p1, p2 = find_neighbors(p0, init_coords, 2) return [p0, p1, p2] else: return -1
def find_init_pts(init_coords, dist=25, min_angle=10): n_p = init_coords.shape[0] As = np.zeros(n_p) for k in range(n_p): p0 = init_coords[k, :] p1, p2 = find_neighbors(p0, init_coords, 2) if (norm(p1 - p0) < dist) and (norm(p2 - p0) < dist): As[k] = angle(p1 - p0, p2 - p0) elif (sum(p1 == p0) == 3) or (sum(p2 == p0) == 3): As[k] = 400 else: As[k] = 500 As[np.where(np.isnan(As))] = np.inf if np.abs(As - 90).min() < min_angle: p0 = init_coords[np.abs(As - 90).argmin(), :] p1, p2 = find_neighbors(p0, init_coords, 2) return [p0, p1, p2] else: return -1
def find_init_angles(all_elecs, mindist=10, maxdist=25): ''' Takes the set of all electrodes and some constraint parameters. Returns angle for each electrode's best match as Nx1 vector''' n = all_elecs.shape[0] angles = np.zeros(n) dists = np.zeros((n, 2)) actual_points = np.zeros((n, 3, 3)) for k in xrange(n): p0 = all_elecs[k, :] p1, p2 = find_neighbors(p0, all_elecs, 2) if ((mindist < norm(p1 - p0) < maxdist) and (mindist < norm(p2 - p0) < maxdist)): angles[k] = angle(p1 - p0, p2 - p0) dists[k] = norm(p1 - p0), norm(p2 - p0) actual_points[k] = (p0, p1, p2) else: angles[k] = np.inf dists[k] = (np.inf, np.inf) actual_points[k] = (p0, p1, p2) return angles, dists, actual_points
def find_init_angles(all_elecs, mindist=10, maxdist=25): ''' Takes the set of all electrodes and some constraint parameters. Returns angle for each electrode's best match as Nx1 vector''' n = all_elecs.shape[0] angles = np.zeros(n) dists = np.zeros((n,2)) actual_points = np.zeros((n,3,3)) for k in xrange(n): p0 = all_elecs[k,:] p1, p2 = find_neighbors(p0, all_elecs, 2) if ((mindist < norm(p1-p0) < maxdist) and (mindist < norm(p2-p0) < maxdist)): angles[k] = angle(p1-p0, p2-p0) dists[k] = norm(p1-p0), norm(p2-p0) actual_points[k] = (p0,p1,p2) else: angles[k] = np.inf dists[k] = (np.inf, np.inf) actual_points[k] = (p0,p1,p2) return angles, dists, actual_points
def shp(sf_path, rlat_d, rlon_d, udir_d, uheight1_d, rlat_v, rlon_v, \ FR_URBAN, FR_ROOF, norm_vert): # Inizializations AREA_BLD = np.zeros((1, rlat_d, rlon_d)) BUILD_W = np.zeros((1, udir_d, rlat_d, rlon_d)) FR_STREETD = np.zeros((1, udir_d, rlat_d, rlon_d)) LAMBDA_F = np.zeros((1, udir_d, rlat_d, rlon_d)) LAMBDA_P = np.zeros((1, rlat_d, rlon_d)) MEAN_HEIGHT = np.zeros((1, rlat_d, rlon_d)) STREET_W = np.zeros((1, udir_d, rlat_d, rlon_d)) VERT_AREA = np.zeros((1, udir_d, rlat_d, rlon_d)) # Read the dataset sf = shapefile.Reader(sf_path) shapes = sf.shapes() # Calculations N = len(shapes) for x in range(0, N): # Reading Geometry shape = shapes[x] p = shape.points p = np.array(p) # Reading the Area (horizontal) area = sf.record(x)[4] # Calculating the coordinates of the centroid of the polygon lonC = np.mean(p[:, 0]) latC = np.mean(p[:, 1]) # Converting centroid to rotated coordinates [lonC_r, latC_r] = geo2rot.g2r(lonC, latC) # Calculating the index of the correspoding grid point lon_idx = np.abs(rlon_v - lonC_r).argmin() lat_idx = np.abs(rlat_v - latC_r).argmin() # Allocating the total building area AREA_BLD[0, lat_idx, lon_idx] += area # Clustering the geomerty heights hgt = sf.record(x)[0] MEAN_HEIGHT[0, lat_idx, lon_idx] += hgt * area hgt_class = cluster.height_old(hgt) # Looping over building segments (facades) for k in range(1, len(p)): vert_area = geometry.distWGS(p, k) * hgt ang = geometry.angle(p, k) ang_class = cluster.angle(ang) # VERT_AREA[0, ang_class, lat_idx, lon_idx] += vert_area # Allocating the building area by direction and height FR_ROOF[0, ang_class, hgt_class, lat_idx, lon_idx] += vert_area # Calculating the area densities (Grimmond and Oke, 1998) np.seterr(divide='ignore') # disabled division by 0 warning area_grid = 77970 # m2, calculated in GIS. TO DO: calculate from grid lambda_p = AREA_BLD[0, :, :] / (area_grid * FR_URBAN[0, :, :]) lambda_p[lambda_p > 0.9] = 0.9 # upper limit lambda_p[lambda_p < 0.1] = 0.1 # lower limit lambda_f = VERT_AREA[0, :, :, :] / (area_grid * FR_URBAN[0, :, :]) lambda_f[lambda_f > 0.9] = 0.9 # upper limit lambda_f[lambda_f < 0.1] = 0.1 # lower limit LAMBDA_P[0, :, :] = lambda_p LAMBDA_F[0, :, :, :] = lambda_f # Calculating the street and building widths (Martilli, 2009) h_m = MEAN_HEIGHT[0, :, :] / AREA_BLD[0, :, :] h_m[h_m == 15] = 10. BUILD_W[0, :, :, :] = lambda_p[np.newaxis, :, :] / lambda_f[:, :, :] * h_m STREET_W[0,:,:,:] = (1 / lambda_p[np.newaxis,:,:] - 1) * lambda_p[np.newaxis,:,:] \ / lambda_f * h_m #STREET_W[STREET_W<5] = 5 # min aspect ration LCZ 2 #STREET_W[STREET_W>100] = 100 # max aspect ration LCZ 9 # Calculating and normalizing the canyon direction distribution FR_STREETD = np.sum(FR_ROOF, 2) norm_streetd = np.sum(FR_STREETD, 1) FR_STREETD = FR_STREETD / norm_streetd # Normalizing FR_ROOF if norm_vert == True: norm_fr_roof = np.sum(FR_ROOF, 2) else: norm_fr_roof = np.sum(FR_ROOF, 1) for j in range(0, udir_d): for k in range(0, uheight1_d): for o in range(0, rlat_d): for z in range(0, rlon_d): if norm_vert == True: if norm_fr_roof[0, j, o, z] != 0: FR_ROOF[0, j, k, o, z] = FR_ROOF[0, j, k, o, z] / norm_fr_roof[0, j, o, z] else: if norm_fr_roof[0, k, o, z] != 0: FR_ROOF[0, j, k, o, z] = FR_ROOF[0, j, k, o, z] / norm_fr_roof[0, k, o, z] FR_ROOF[FR_ROOF < 0.001] = 0 # to avoid negative values return BUILD_W, STREET_W, FR_ROOF, FR_STREETD, shapes
def calculate_forces(self): """ The force calculations have been joined into a single function for performance reasons. """ forces = {"separation": (0, 0), "alignment": (0, 0), "cohesion": (0, 0), "avoidance": (0, 0), "flight": (0, 0)} self.fleeing = False flight_x, flight_y = 0.0, 0.0 for predator in self.predators: self.fleeing = True distance = self.distance(predator) if distance < PREDATOR_RADIUS: dead = self.die() if dead: return forces factor = 1 - distance / self.world.neighbourhood_radius rel_x, rel_y = self.relative_coordinates(predator.x, predator.y) flight_x -= factor * rel_x flight_y -= factor * rel_y forces["flight"] = (flight_x, flight_y) self.avoiding = False avoidance_x, avoidance_y = 0.0, 0.0 for obstacle in self.world.obstacles: distance = self.shortest_distance(obstacle.x, obstacle.y) if distance < (BOID_RADIUS + self.world.neighbourhood_radius + OBSTACLE_RADIUS): if distance < OBSTACLE_RADIUS: dead = self.die() if dead: return forces normalized_vx, normalized_vy = self.normalized_velocity intersection = False for n in xrange(1, int(distance)): future_x = self.x + n * normalized_vx future_y = self.y + n * normalized_vy d = euclidean_distance((future_x, future_y), obstacle.position) if d < (obstacle.r + BOID_RADIUS): intersection = True break if intersection: self.avoiding = True factor = 1 - (distance - obstacle.r) / self.world.neighbourhood_radius future_x = self.x + distance * normalized_vx future_y = self.y + distance * normalized_vy v1 = self.relative_coordinates(*obstacle.position) v2 = self.relative_coordinates(future_x, future_y) a = angle(v1, v2) if a < 0: factor *= -1 avoidance_x += factor * -normalized_vy avoidance_y += factor * normalized_vx forces["avoidance"] = (avoidance_x, avoidance_y) if len(self.neighbours) == 0: return forces sum_x, sum_y = 0.0, 0.0 sum_vx, sum_vy = 0.0, 0.0 sep_x, sep_y = 0.0, 0.0 for boid in self.neighbours: distance = self.world.distances[self, boid] factor = 1 - distance / self.world.neighbourhood_radius nvx, nvy = boid.normalized_velocity sum_vx += nvx sum_vy += nvy sum_x += boid.x sum_y += boid.y rel_x, rel_y = normalize_vector(*self.relative_coordinates(boid.x, boid.y)) sep_x -= factor * rel_x sep_y -= factor * rel_y forces["separation"] = (sep_x, sep_y) forces["alignment"] = normalize_vector(sum_vx, sum_vy) avg_x = sum_x / len(self.neighbours) avg_y = sum_y / len(self.neighbours) forces["cohesion"] = normalize_vector(*self.relative_coordinates(avg_x, avg_y)) return forces
def calculate_forces(self): """ The force calculations have been joined into a single function for performance reasons. """ forces = { 'separation': (0, 0), 'alignment': (0, 0), 'cohesion': (0, 0), 'avoidance': (0, 0), 'flight': (0, 0) } self.fleeing = False flight_x, flight_y = 0.0, 0.0 for predator in self.predators: self.fleeing = True distance = self.distance(predator) if distance < PREDATOR_RADIUS: dead = self.die() if dead: return forces factor = 1 - distance / self.world.neighbourhood_radius rel_x, rel_y = self.relative_coordinates(predator.x, predator.y) flight_x -= factor * rel_x flight_y -= factor * rel_y forces['flight'] = (flight_x, flight_y) self.avoiding = False avoidance_x, avoidance_y = 0.0, 0.0 for obstacle in self.world.obstacles: distance = self.shortest_distance(obstacle.x, obstacle.y) if distance < (BOID_RADIUS + self.world.neighbourhood_radius + OBSTACLE_RADIUS): if distance < OBSTACLE_RADIUS: dead = self.die() if dead: return forces normalized_vx, normalized_vy = self.normalized_velocity intersection = False for n in xrange(1, int(distance)): future_x = self.x + n * normalized_vx future_y = self.y + n * normalized_vy d = euclidean_distance((future_x, future_y), obstacle.position) if d < (obstacle.r + BOID_RADIUS): intersection = True break if intersection: self.avoiding = True factor = 1 - (distance - obstacle.r) / self.world.neighbourhood_radius future_x = self.x + distance * normalized_vx future_y = self.y + distance * normalized_vy v1 = self.relative_coordinates(*obstacle.position) v2 = self.relative_coordinates(future_x, future_y) a = angle(v1, v2) if a < 0: factor *= -1 avoidance_x += factor * -normalized_vy avoidance_y += factor * normalized_vx forces['avoidance'] = (avoidance_x, avoidance_y) if len(self.neighbours) == 0: return forces sum_x, sum_y = 0.0, 0.0 sum_vx, sum_vy = 0.0, 0.0 sep_x, sep_y = 0.0, 0.0 for boid in self.neighbours: distance = self.world.distances[self, boid] factor = 1 - distance / self.world.neighbourhood_radius nvx, nvy = boid.normalized_velocity sum_vx += nvx sum_vy += nvy sum_x += boid.x sum_y += boid.y rel_x, rel_y = normalize_vector( *self.relative_coordinates(boid.x, boid.y)) sep_x -= factor * rel_x sep_y -= factor * rel_y forces['separation'] = (sep_x, sep_y) forces['alignment'] = normalize_vector(sum_vx, sum_vy) avg_x = sum_x / len(self.neighbours) avg_y = sum_y / len(self.neighbours) forces['cohesion'] = normalize_vector( *self.relative_coordinates(avg_x, avg_y)) return forces
def angles(self): return np.degrees(map(lambda v1,v2: angle(v1-self.deepestPoint, v2-self.deepestPoint,0,True), self.vertices, np.roll(self.vertices,-1,0)))