def main(args): ''' Main function, invoked from either command line or qc_wrap ''' pargs = parser.parse_args(args[1:]) lasname = pargs.las_file kmname = constants.get_tilename(lasname) msg = "Running %s on block: %s, %s" print(msg % (os.path.basename(args[0]), kmname, time.asctime())) if pargs.schema is not None: report.set_schema(pargs.schema) reporter = report.ReportSpikes(pargs.use_local) if pargs.zlim < 0: print("zlim must be positive!") usage() if pargs.slope < 0 or pargs.slope >= 90: print("Specify a slope angle in the range 0->90 degrees.") usage() cut_class = pargs.cut_class print("Cutting to class (terrain) {0:d}".format(cut_class)) pc = pointcloud.fromAny(lasname).cut_to_class(cut_class) if pc.get_size() < 10: print("Too few points in pointcloud.") return print("Sorting spatially...") pc.sort_spatially(FILTER_RAD) slope_arg = np.tan(np.radians(pargs.slope))**2 msg = "Using steepnes parameters: angle: {0:.2f} degrees, delta-z: {1:.2f}" print(msg.format(pargs.slope, pargs.zlim)) print("Filtering, radius: {0:.2f}".format(FILTER_RAD)) dz = pc.spike_filter(FILTER_RAD, slope_arg, pargs.zlim) mask = (dz != 0) dz = dz[mask] pc = pc.cut(mask) print("Spikes: {0:d}".format(mask.sum())) for i in xrange(pc.size): x, y = pc.xy[i] z = pc.z[i] mdz = dz[i] c = pc.c[i] pid = pc.pid[i] print("spike: x: {0:.2f} y: {1:.2f} mean-dz: {2:.2f}".format(x, y, mdz)) wkt_geom = "POINT({0:.2f} {1:.2f})".format(x, y) reporter.report(kmname, FILTER_RAD, mdz, x, y, z, c, pid, wkt_geom=wkt_geom)
def main(args): pargs = parser.parse_args(args[1:]) lasname = pargs.las_file buildname = pargs.build_data if pargs.schema is not None: report.set_schema(pargs.schema) reporter = report.ReportZcheckBuilding(pargs.use_local) done = zcheck_base.zcheck_base(lasname, buildname, angle_tolerance, xy_tolerance, z_tolerance, pargs.cut_to, reporter, layername=pargs.layername, layersql=pargs.layersql)
def main(args): pargs = parser.parse_args(args[1:]) lasname = pargs.las_file roadname = pargs.road_data cut = pargs.cut_to if pargs.schema is not None: report.set_schema(pargs.schema) reporter = report.ReportZcheckRoad(pargs.use_local) done = zcheck_base.zcheck_base(lasname, roadname, angle_tolerance, xy_tolerance, z_tolerance, cut, reporter, buffer_dist=buffer_dist, layername=pargs.layername, layersql=pargs.layersql)
def main(args): pargs = parser.parse_args(args[1:]) lasname = pargs.las_file use_local = pargs.use_local if pargs.schema is not None: report.set_schema(pargs.schema) if pargs.height is not None: reporter = report.ReportClouds(use_local) CS = 4 CELL_COUNT_LIM = 4 else: reporter = report.ReportAutoBuilding(use_local) CS = 1 CELL_COUNT_LIM = 2 kmname = constants.get_tilename(lasname) print("Running %s on block: %s, %s" % (os.path.basename(args[0]), kmname, time.asctime())) try: xul, yll, xlr, yul = constants.tilename_to_extent(kmname) except Exception, e: print("Exception: %s" % str(e)) print("Bad 1km formatting of las file name: %s" % lasname) return 1
def main(args): try: pargs=parser.parse_args(args[1:]) except Exception,e: print(str(e)) return 1 kmname=constants.get_tilename(pargs.las_file) print("Running %s on block: %s, %s" %(progname,kmname,time.asctime())) lasname=pargs.las_file linename=pargs.ref_data use_local=pargs.use_local if pargs.schema is not None: report.set_schema(pargs.schema) reporter=report.ReportLineOutliers(use_local) try: extent=np.asarray(constants.tilename_to_extent(kmname)) except Exception,e: print("Could not get extent from tilename.") raise e lines=vector_io.get_features(linename,pargs.layername,pargs.layersql,extent) print("Found %d features in %s" %(len(lines),linename)) if len(lines)==0: return 2 cut_input_to=pargs.cut_to print("Reading "+lasname+"....") pc=pointcloud.fromAny(lasname).cut_to_class(cut_input_to) #what to cut to here...?? if pargs.debug: print("Cutting input pointcloud to class %d" %cut_input_to)
def main(args): pargs = parser.parse_args(args[1:]) lasname = pargs.las_file polyname = pargs.build_polys kmname = constants.get_tilename(lasname) print("Running %s on block: %s, %s" % (os.path.basename(args[0]), kmname, time.asctime())) use_local = pargs.use_local if pargs.schema is not None: report.set_schema(pargs.schema) reporter = report.ReportRoofridgeCheck(use_local) cut_class = pargs.cut_class print("Using class(es): %s" % (cut_class)) # default step values for search... steps1 = 32 steps2 = 14 search_factor = pargs.search_factor if search_factor != 1: # can turn search steps up or down steps1 = int(search_factor * steps1) steps2 = int(search_factor * steps2) print("Incresing search factor by: %.2f" % search_factor) print( "Running time will increase exponentionally with search factor...") pc = pointcloud.fromAny(lasname).cut_to_class(cut_class).cut_to_z_interval( Z_MIN, Z_MAX) try: extent = np.asarray(constants.tilename_to_extent(kmname)) except Exception: print("Could not get extent from tilename.") extent = None polys = vector_io.get_geometries(polyname, pargs.layername, pargs.layersql, extent) fn = 0 sl = "+" * 60 is_sloppy = pargs.sloppy use_all = pargs.use_all for poly in polys: print(sl) fn += 1 print("Checking feature number %d" % fn) a_poly = array_geometry.ogrgeom2array(poly) # secret argument to use all buildings... if (len(a_poly) > 1 or a_poly[0].shape[0] != 5) and (not use_all) and (not is_sloppy): print("Only houses with 4 corners accepted... continuing...") continue pcp = pc.cut_to_polygon(a_poly) # hmmm, these consts should perhaps be made more visible... if (pcp.get_size() < 500 and (not is_sloppy)) or (pcp.get_size() < 10): print("Few points in polygon...") continue # Go to a more numerically stable coord system - from now on only consider outer ring... a_poly = a_poly[0] xy_t = a_poly.mean(axis=0) a_poly -= xy_t pcp.xy -= xy_t pcp.triangulate() geom = pcp.get_triangle_geometry() m = geom[:, 1].mean() sd = geom[:, 1].std() if (m > 1.5 or 0.5 * sd > m) and (not is_sloppy): print("Feature %d, bad geometry...." % fn) print(m, sd) continue planes = cluster(pcp, steps1, steps2) if len(planes) < 2: print("Feature %d, didn't find enough planes..." % fn) pair, equation = find_planar_pairs(planes) if pair is not None: p1 = planes[pair[0]] p2 = planes[pair[1]] z1 = p1[0] * pcp.xy[:, 0] + p1[1] * pcp.xy[:, 1] + p1[2] z2 = p2[0] * pcp.xy[:, 0] + p2[1] * pcp.xy[:, 1] + p2[2] print("%s" % ("*" * 60)) print("Statistics for feature %d" % fn) if DEBUG: plot3d(pcp.xy, pcp.z, z1, z2) intersections, distances, rotations = get_intersections( a_poly, equation) if intersections.shape[0] == 2: line_x = intersections[:, 0] line_y = intersections[:, 1] z_vals = p1[0] * intersections[:, 0] + p1[ 1] * intersections[:, 1] + p1[2] if abs(z_vals[0] - z_vals[1]) > 0.01: print("Numeric instabilty for z-calculation...") z_val = float(np.mean(z_vals)) print("Z for intersection is %.2f m" % z_val) if abs(equation[1]) > 1e-3: a = -equation[0] / equation[1] b = equation[2] / equation[1] line_y = a * line_x + b elif abs(equation[0]) > 1e-3: a = -equation[1] / equation[0] b = equation[2] / equation[0] line_x = a * line_y + b if DEBUG: plot_intersections(a_poly, intersections, line_x, line_y) # transform back to real coords line_x += xy_t[0] line_y += xy_t[1] wkt = "LINESTRING(%.3f %.3f %.3f, %.3f %.3f %.3f)" % ( line_x[0], line_y[0], z_val, line_x[1], line_y[1], z_val) print("WKT: %s" % wkt) reporter.report(kmname, rotations[0], distances[0], distances[1], wkt_geom=wkt) else: print( "Hmmm - something wrong, didn't get exactly two intersections..." )
def main(args): pargs = parser.parse_args(args[1:]) lasname = pargs.las_file polyname = pargs.build_polys kmname = constants.get_tilename(lasname) print("Running %s on block: %s, %s" % (os.path.basename(args[0]), kmname, time.asctime())) if pargs.schema is not None: report.set_schema(pargs.schema) reporter = report.ReportRoofridgeStripCheck(pargs.use_local) cut_class = pargs.cut_class # default step values for search... steps1 = 30 steps2 = 13 search_factor = pargs.search_factor if search_factor != 1: # can turn search steps up or down steps1 = int(search_factor * steps1) steps2 = int(search_factor * steps2) print("Incresing search factor by: %.2f" % search_factor) print("Running time will increase exponentionally with search factor...") pc = pointcloud.fromAny(lasname).cut_to_class(cut_class).cut_to_z_interval(Z_MIN, Z_MAX) try: extent = np.asarray(constants.tilename_to_extent(kmname)) except Exception: print("Could not get extent from tilename.") extent = None polys = vector_io.get_geometries(polyname, pargs.layername, pargs.layersql, extent) fn = 0 sl = "+" * 60 is_sloppy = pargs.sloppy use_all = pargs.use_all for poly in polys: print(sl) fn += 1 print("Checking feature number %d" % fn) a_poly = array_geometry.ogrgeom2array(poly) # secret argument to use all buildings... if (len(a_poly) > 1 or a_poly[0].shape[0] != 5) and (not use_all) and (not is_sloppy): print("Only houses with 4 corners accepted... continuing...") continue pcp = pc.cut_to_polygon(a_poly) strips = pcp.get_pids() if len(strips) != 2: print("Not exactly two overlapping strips... continuing...") continue # Go to a more numerically stable coord system - from now on only consider outer ring... a_poly = a_poly[0] xy_t = a_poly.mean(axis=0) # center of mass system a_poly -= xy_t lines = [] # for storing the two found lines... for sid in strips: print("-*-" * 15) print("Looking at strip %d" % sid) pcp_ = pcp.cut_to_strip(sid) # hmmm, these consts should perhaps be made more visible... if (pcp_.get_size() < 500 and (not is_sloppy)) or (pcp_.get_size() < 10): print("Few points in polygon... %d" % pcp_.get_size()) continue pcp_.xy -= xy_t pcp_.triangulate() geom = pcp_.get_triangle_geometry() m = geom[:, 1].mean() sd = geom[:, 1].std() if (m > 1.5 or 0.5 * sd > m) and (not is_sloppy): print("Feature %d, strip %d, bad geometry...." % (fn, sid)) break planes = cluster(pcp_, steps1, steps2) if len(planes) < 2: print("Feature %d, strip %d, didn't find enough planes..." % (fn, sid)) pair, equation = find_planar_pairs(planes) if pair is not None: p1 = planes[pair[0]] print("%s" % ("*" * 60)) print("Statistics for feature %d" % fn) # Now we need to find some points on the line near the house... (0,0) is # the center of mass norm_normal = equation[0]**2 + equation[1]**2 if norm_normal < 1e-10: print("Numeric instablity, small normal") break # this should be on the line cm_line = np.asarray(equation[:2]) * (equation[2] / norm_normal) line_dir = np.asarray((-equation[1], equation[0])) / (sqrt(norm_normal)) end1 = cm_line + line_dir * LINE_RAD end2 = cm_line - line_dir * LINE_RAD intersections = np.vstack((end1, end2)) line_x = intersections[:, 0] line_y = intersections[:, 1] z_vals = p1[0] * intersections[:, 0] + p1[1] * intersections[:, 1] + p1[2] if abs(z_vals[0] - z_vals[1]) > 0.01: print("Numeric instabilty for z-calculation...") z_val = float(np.mean(z_vals)) print("Z for intersection is %.2f m" % z_val) # transform back to real coords line_x += xy_t[0] line_y += xy_t[1] wkt = "LINESTRING(%.3f %.3f %.3f, %.3f %.3f %.3f)" % ( line_x[0], line_y[0], z_val, line_x[1], line_y[1], z_val) print("WKT: %s" % wkt) lines.append([sid, wkt, z_val, cm_line, line_dir]) if len(lines) == 2: # check for parallelity id1 = lines[0][0] id2 = lines[1][0] z1 = lines[0][2] z2 = lines[1][2] if abs(z1 - z2) > 0.5: print("Large difference in z-values for the two lines!") else: ids = "{0:d}_{1:d}".format(id1, id2) inner_prod = (lines[0][4] * lines[1][4]).sum() inner_prod = max(-1, inner_prod) inner_prod = min(1, inner_prod) if DEBUG: print("Inner product: %.4f" % inner_prod) ang = abs(degrees(acos(inner_prod))) if ang > 175: ang = abs(180 - ang) if ang < 15: v = (lines[0][3] - lines[1][3]) d = np.sqrt((v**2).sum()) if d < 5: for line in lines: reporter.report(kmname, id1, id2, ids, d, ang, line[2], wkt_geom=line[1]) else: print("Large distance between centers %s, %s, %.2f" % (lines[0][3], lines[1][3], d)) else: print("Pair found - but not very well aligned - angle: %.2f" % ang) else: print("Pair not found...")
def main(args): ''' Run road delta check. Invoked from either command line or qc_wrap.py ''' pargs = parser.parse_args(args[1:]) lasname = pargs.las_file linename = pargs.lines kmname = constants.get_tilename(lasname) print("Running %s on block: %s, %s" % (os.path.basename(args[0]), kmname, time.asctime())) if pargs.schema is not None: report.set_schema(pargs.schema) reporter = report.ReportDeltaRoads(pargs.use_local) cut_class = pargs.cut_class pc = pointcloud.fromAny(lasname).cut_to_class(cut_class) if pc.get_size() < 5: print("Too few points to bother..") return 1 pc.triangulate() geom = pc.get_triangle_geometry() print("Using z-steepnes limit {0:.2f} m".format(pargs.zlim)) mask = np.logical_and(geom[:, 1] < XY_MAX, geom[:, 2] > pargs.zlim) geom = geom[mask] # save for reporting if not mask.any(): print("No steep triangles found...") return 0 # only the centers of the interesting triangles centers = pc.triangulation.get_triangle_centers()[mask] print("{0:d} steep triangles in tile.".format(centers.shape[0])) try: extent = np.asarray(constants.tilename_to_extent(kmname)) except Exception: print("Could not get extent from tilename.") extent = None lines = vector_io.get_geometries(linename, pargs.layername, pargs.layersql, extent) feature_count = 0 for line in lines: xy = array_geometry.ogrline2array(line, flatten=True) if xy.shape[0] == 0: print("Seemingly an unsupported geometry...") continue # select the triangle centers which lie within line_buffer of the road segment mask = array_geometry.points_in_buffer(centers, xy, LINE_BUFFER) critical = centers[mask] print("*" * 50) print("{0:d} steep centers along line {1:d}".format(critical.shape[0], feature_count)) feature_count += 1 if critical.shape[0] > 0: z_box = geom[mask][:, 2] z1 = z_box.max() z2 = z_box.min() wkt = "MULTIPOINT(" for point in critical: wkt += "{0:.2f} {1:.2f},".format(point[0], point[1]) wkt = wkt[:-1] + ")" reporter.report(kmname, z1, z2, wkt_geom=wkt)