def fix_onepoint(block): points = gml.flat_to_xys(block.geometry_wkt) if len(points) == 3: # remove extra point, we don't need it anymore del points[1] block.geometry_wkt = ( 'LINESTRING(%s)' % (gml.wkt_coords_format(points),))
def __init__(self, obs, cutoff_distance): if len(obs) > 1: self.geometry_wkt = ( 'LINESTRING(%s)' % (gml.wkt_coords_format(obs),)) else: self.geometry_wkt = 'POINT(%s %s)' % (obs[0][0], obs[0][1],) self.cutoff = cutoff_distance
def split_block(self, b, intersection, new_node_id=None): points = gml.flat_to_xys(b.geometry_wkt) index = get_point_index(b, intersection) # Insert the new vertex into the byway points.insert(index, intersection) # Split the byway at the new vertex new_split_block = copy.deepcopy(b) new_split_block.stack_id = self.get_fresh_id() new_split_block.split_from_stack_id = b.stack_id geom1 = list() geom2 = list() # TODO: this can be done without a for loop for i in range(0,len(points)): if (i <= index): geom1.append(points[i]) if (i >= index): geom2.append(points[i]) if (new_node_id is None): new_split_block.nid2 = self.get_fresh_id() else: new_split_block.nid2 = new_node_id b.nid1 = new_split_block.nid2 # Remove the old split block since its geometry has changed for block in self.new_byways: if block.stack_id == b.stack_id: self.new_byways.remove(block) break # Save the new split blocks to the byways list new_split_block.geometry_wkt = ( 'LINESTRING(%s)' % (gml.wkt_coords_format(geom1),)) self.new_byways.append(new_split_block) b.geometry_wkt = ( 'LINESTRING(%s)' % (gml.wkt_coords_format(geom2),)) self.new_byways.append(b) return b.nid1, new_split_block.stack_id, b.stack_id
def create_new_block(self, obs, bounds, last_block_ids=None): first_point_index = bounds[0] last_point_index = bounds[1] new_block = BywayMeta(self.get_fresh_id(), 'New Block', self.get_fresh_id(), self.get_fresh_id(), 0, 0, 0, None, None, 1) new_block_points = [] one_point = False for i in range(first_point_index, last_point_index+1): new_block_points.append((obs[i][0], obs[i][1])) if (len(new_block_points) == 1): # Single points need to be handled differently, because when connecting # to nearby blocks the point may be moved one_point = True new_block_points.append(new_block_points[0]) new_block.geometry_wkt = ( 'LINESTRING(%s)' % (gml.wkt_coords_format(new_block_points),)) # Extend byway both ways and split (or connect if end node near enough) ignore_ids = self.continue_block(new_block, -1, last_block_ids) if (one_point): fix_onepoint(new_block) ignore = [new_block.stack_id] if (one_point and ignore_ids is not None): ignore.extend(ignore_ids) self.continue_block(new_block, 1, ignore=ignore) if (one_point): fix_onepoint(new_block) # Smooth new byway geometry new_block.geometry_wkt, new_block.geometry_svg = ( self.smooth_path(new_block.geometry_wkt)) # Save byway to block cache #new_block.geometry_wkt = 'LINESTRING(%s)' % ( # gml.wkt_coords_format(new_block.geometry_wkt),) self.new_byways.append(new_block) return new_block
def from_gml(self, qb, elem): geofeature.One.from_gml(self, qb, elem) # BUG nnnn: Make tracks revisionless. Uncomment this: # self.setup_item_revisionless_defaults(qb, force=True) xys_string = list() for tpoint in elem: tp = track_point.One() tp.from_gml(qb, tpoint) self.track_points.append(tp) xys_string.append((float(tp.x), float(tp.y))) self.set_geometry_wkt( gml.wkt_linestring_get(gml.wkt_coords_format(xys_string))) if not self.track_points: log.warning('from_gml: no track_points: %d' % (len(self.track_points), ))
def from_gml(self, qb, elem): geofeature.One.from_gml(self, qb, elem) # BUG nnnn: Make tracks revisionless. Uncomment this: # self.setup_item_revisionless_defaults(qb, force=True) xys_string = list() for tpoint in elem: tp = track_point.One() tp.from_gml(qb, tpoint) self.track_points.append(tp) xys_string.append((float(tp.x), float(tp.y))) self.set_geometry_wkt(gml.wkt_linestring_get( gml.wkt_coords_format(xys_string))) if not self.track_points: log.warning('from_gml: no track_points: %d' % (len(self.track_points),))
def continue_block(self, new_block, direction, last_block_ids=None, ignore=None): if direction == -1: endpoint_index = 0 else: endpoint_index = -1 extending_points = gml.flat_to_xys(new_block.geometry_wkt) if ignore is None: ignore = [new_block.stack_id] # If there are no blocks nearby, no need to extend this block nearest_block = self.get_nearest_block( extending_points[endpoint_index], last_block_ids, ignore=ignore) if (nearest_block is None or nearest_block.dist > self.wtem.distance_error): return None ignore_ids = [nearest_block.stack_id] near_points = gml.flat_to_xys(nearest_block.geometry_wkt) # If we are close to an endpoint of another block, connect to it. if (dist(extending_points[endpoint_index], near_points[0]) <= self.wtem.distance_error): # add blocks that connect to that endpoint to ignore list for next # block continuation ignore_ids.extend( [b.stack_id for b in self.get_connected_blocks( nearest_block, nearest_block.nid1)]) if direction == -1: extending_points[0] = near_points[0] new_block.nid1 = nearest_block.nid1 else: extending_points[-1] = near_points[0] new_block.nid2 = nearest_block.nid1 elif (dist(extending_points[endpoint_index], near_points[-1]) <= self.wtem.distance_error): # add blocks that connect to that endpoint to ignore list for next # block continuation ignore_ids.extend( [b.stack_id for b in self.get_connected_blocks( nearest_block, nearest_block.nid2)]) if direction == -1: extending_points[0] = near_points[-1] new_block.nid1 = nearest_block.nid2 else: extending_points[-1] = near_points[-1] new_block.nid2 = nearest_block.nid2 else: # Get location of closest point on the nearest block and the expected # index in that block's sequence of points. point = self.proj_block( extending_points[endpoint_index], nearest_block) new_node, b1_id, b2_id = self.split_block(nearest_block, point) ignore_ids = [b1_id, b2_id] # Connect the current block to the intersection if direction == -1: extending_points.insert(0, point) new_block.nid1 = new_node else: extending_points.append(point) new_block.nid2 = new_node new_block.geometry_wkt = ( 'LINESTRING(%s)' % (gml.wkt_coords_format(extending_points),)) return ignore_ids
def save_rstep(self, qb, route, step_number): self.route_id = route.system_id # FIXME: Do we need these? They're in the table... self.route_stack_id = route.stack_id self.route_version = route.version self.step_number = step_number g.assurt(self.byway_stack_id > 0) g.assurt(self.byway_version > 0) # 2014.08.19: flashclient sending byway_id="0" ??? if (not self.byway_id) or (self.byway_id <= 0): if route.stack_id not in One.warned_re_sysid_stk_ids: One.warned_re_sysid_stk_ids.add(route.stack_id) log.warning( 'save_rstep: byway_id not sent from client: route sid: %s' % (route.stack_id, )) branch_ids = [str(branch_tup[0]) for branch_tup in qb.branch_hier] # FIXME: The ORDER BY is pretty lame... but if we just have a stack ID # and a version, and if we don't check against the time when # the route was requested, we can't know for sure which branch # the byway is from (e.g., a route was requested in a leafy # branch and the parent branch's byways were selected, but # then one byway is edited in both the parent and the leaf, # then there are two byways with the same stack ID and version # but different branch_ids: since our qb is Current but the # route is historic, we would really need to find the revision # when the route was requested and use that to find the true # byway system_id). This code just finds the leafiest matching # byway... which is probably okay, since this code is for # saving byways, and most users will be saving to the basemap # branch (who uses the MetC Bikeways 2012 branch, anyway? No # one...), and also this code is just a stopgap until we fix # the real problem that is the client is not sending byway # system IDs, which might be a pyserver problem not sending # them to the client in the first place.... sys_id_sql = (""" SELECT iv.system_id FROM item_versioned AS iv WHERE iv.stack_id = %d AND iv.version = %d AND branch_id IN (%s) ORDER BY branch_id DESC LIMIT 1 """ % ( self.byway_stack_id, self.byway_version, ','.join(branch_ids), )) rows = qb.db.sql(sys_id_sql) g.assurt( len(rows) == 1) # Or not, if no match, which would be weird. self.byway_id = rows[0]['system_id'] g.assurt(self.byway_id > 0) if (self.geometry and (self.travel_mode == Travel_Mode.transit)): # Old CcpV1: db_glue automatically prepends the SRID for columns named # 'geometry' but we have to do it manually here so constraints pass. # 2012.09.27: What does 'constraints pass' mean? Doesn't db_glue fix # this list the comment says? # MAYBE: This feels like a gml fcn. See maybe: wkt_linestring_get. wkt_geom = ( 'SRID=%s;LINESTRING(%s)' % ( conf.default_srid, gml.wkt_coords_format( # FIXED?: Was: gml.flat_to_xys(self.geometry[2:]) gml.flat_to_xys(self.geometry)), )) else: # Either this is a byway-associated route_step, so we don't save the # byway's geometry (it's easy to lookup in the database), or something # else... wkt_geom = None if self.travel_mode == Travel_Mode.transit: # FIXME: Does this mean we're clearing existing geometry? Seems # weird... log.warning( 'save_rstep: transit step has geometry? are we clearing it?' ) # FIXME: What about wkt_geom? Is this right? self.transit_geometry = wkt_geom self.save_insert(qb, One.item_type_table, One.psql_defns)