def text2coordList(datatext): x = [] y = [] z = [] if len(datatext) != 0: lines = datatext.split('\n') for zn, l in enumerate(lines): words = l.split() try: [xv, yv, zv] = [float(words[0]), float(words[1]), float(words[2])] x.append(xv) y.append(yv) z.append(10 * zv) except: sayErr(("Fehler in Zeile ", zn)) x = np.array(x) y = np.array(y) z = np.array(z) #x=x-x.min() #y=y-y.min() return (x, y, z)
def interpolate(x, y, z, gridsize, mode='thin_plate', rbfmode=True, shape=None): mode = str(mode) grids = gridsize dx = np.max(x) - np.min(x) dy = np.max(y) - np.min(y) if dx > dy: gridx = grids gridy = int(round(dy / dx * grids)) else: gridy = grids gridx = int(round(dx / dy * grids)) if shape != None: (gridy, gridx) = shape xi, yi = np.linspace(np.min(x), np.max(x), gridx), np.linspace(np.min(y), np.max(y), gridy) xi, yi = np.meshgrid(xi, yi) if rbfmode: rbf = scipy.interpolate.Rbf(x, y, z, function=mode) rbf2 = scipy.interpolate.Rbf(y, x, z, function=mode) else: sayErr("interp2d nicht implementiert") x = np.array(x) y = np.array(y) z = np.array(z) xi, yi = np.linspace(np.min(x), np.max(x), gridx), np.linspace(np.min(y), np.max(y), gridy) rbf = scipy.interpolate.interp2d(x, y, z, kind=mode) rbf2 = scipy.interpolate.interp2d(y, x, z, kind=mode) zi = rbf2(yi, xi) return [rbf, xi, yi, zi]
def import_osm2(b, l, bk, progressbar=False, status=False, elevation=False): bk = 0.5 * bk if elevation: say("get height for {}, {}".format(b, l)) baseheight = get_height_single(b, l) say("baseheight: {}".format(baseheight)) else: baseheight = 0.0 say("The importer of trails is used to import osm data.") say("This one does support elevations.") say(b, l, bk, progressbar, status, elevation) # ************************************************************************* # get and parse osm data if progressbar and FreeCAD.GuiUp: progressbar.setValue(0) if status and FreeCAD.GuiUp: status.setText( "get data from openstreetmap.org and parse it for later usage ..." ) FreeCADGui.updateGui() tree = get_osmdata(b, l, bk) if tree is None: sayErr("Something went wrong on retrieving OSM data.") return False # say("nodes") # for element in tree.getiterator("node"): # say(element.params) # say("ways") # for element in tree.getiterator("way"): # say(element.params) # say("relations") # for element in tree.getiterator("relation"): # say(element.params) # ************************************************************************* if status and FreeCAD.GuiUp: status.setText("transform data ...") FreeCADGui.updateGui() # relations = tree.getiterator("relation") nodes = tree.getiterator("node") ways = tree.getiterator("way") bounds = tree.getiterator("bounds")[0] # get base area size and map nodes data to the area on coordinate origin tm, size, corner_min, points, nodesbyid = map_data(nodes, bounds) # say(tm) # say(size) # say(corner_min) # say(len(points)) # say(len(nodesbyid)) # ************************************************************************* if status and FreeCAD.GuiUp: status.setText("create visualizations ...") FreeCADGui.updateGui() # new document # TODO, if a document exists or was passed use this one # it makes sense to use the doc as return value doc = FreeCAD.newDocument("OSM Map") say("New FreeCAD document created.") # base area area = doc.addObject("Part::Plane", "area") area.Length = size[0] * 2 area.Width = size[1] * 2 placement_for_area = FreeCAD.Placement( FreeCAD.Vector(-size[0], -size[1], 0.00), FreeCAD.Rotation(0.00, 0.00, 0.00, 1.00) ) area.Placement = placement_for_area if FreeCAD.GuiUp: # set camera set_cam(area, bk) area.ViewObject.Document.activeView().viewAxonometric() FreeCADGui.updateGui() say("Base area created.") if elevation: elearea = doc.addObject("Part::Feature","Elevation_Area") elearea.Shape = get_elebase_sh(corner_min, size, baseheight, tm) doc.recompute() if FreeCAD.GuiUp: area.ViewObject.hide() elearea.ViewObject.Transparency = 75 elearea.ViewObject.Document.activeView().viewAxonometric() # elearea.ViewObject.Document.activeView().fitAll() # the cam was set FreeCADGui.updateGui() say("Area with Height done") # ************************************************************************* # ways say("Ways") wn = -1 count_ways = len(ways) starttime = time.time() refresh = 1000 for way in ways: wid = way.params["id"] wn += 1 # say(way.params) # say("way content") # for c in way.content: # say(c) # for debugging, break after some of the ways have been processed # if wn == 6: # say("Waycount restricted to {} by dev".format(wn - 1)) # break nowtime = time.time() # if wn != 0 and (nowtime - starttime) / wn > 0.5: # had problems if wn != 0: say( "way ---- # {}/{} time per house: {}" .format(wn, count_ways, round((nowtime-starttime)/wn, 2)) ) if progressbar: progressbar.setValue(int(0 + 100.0 * wn / count_ways)) # get a name for the way name, way_type, nr, building_height = get_way_information(way) # generate way polygon points say("get nodes", way) if not elevation: polygon_points = [] for n in way.getiterator("nd"): wpt = points[str(n.params["ref"])] # say(wpt) polygon_points.append(wpt) else: # get heights for lat lon way polygon points polygon_points = get_ppts_with_heights(way, way_type, points, nodesbyid, baseheight) # create document object out of the way polygon points # for p in polygon_points: # say(p) # a wire for each way polygon polygon_shape = Part.makePolygon(polygon_points) polygon_obj = doc.addObject("Part::Feature", "w_" + wid) polygon_obj.Shape = polygon_shape # polygon_obj.Label = "w_" + wid if name == " ": g = doc.addObject("Part::Extrusion", name) g.Base = polygon_obj g.ViewObject.ShapeColor = (1.0, 1.0, 0.0) g.Dir = (0, 0, 10) g.Solid = True g.Label = "way ex " if way_type == "building": g = doc.addObject("Part::Extrusion", name) g.Base = polygon_obj g.ViewObject.ShapeColor = (1.0, 1.0, 1.0) if building_height == 0: building_height = 10000 g.Dir = (0, 0, building_height) g.Solid = True g.Label = name inventortools.setcolors2(g) # what does this do? if way_type == "highway": g = doc.addObject("Part::Extrusion", "highway") g.Base = polygon_obj g.ViewObject.LineColor = (0.0, 0.0, 1.0) g.ViewObject.LineWidth = 10 g.Dir = (0, 0, 0.2) g.Label = name if way_type == "landuse": g = doc.addObject("Part::Extrusion", name) g.Base = polygon_obj if nr == "residential": g.ViewObject.ShapeColor = (1.0, 0.6, 0.6) elif nr == "meadow": g.ViewObject.ShapeColor = (0.0, 1.0, 0.0) elif nr == "farmland": g.ViewObject.ShapeColor = (0.8, 0.8, 0.0) elif nr == "forest": g.ViewObject.ShapeColor = (1.0, 0.4, 0.4) g.Dir = (0, 0, 0.1) g.Label = name g.Solid = True refresh += 1 if refresh > 3 and FreeCAD.GuiUp: FreeCADGui.updateGui() # FreeCADGui.SendMsgToActiveView("ViewFit") refresh = 0 # ************************************************************************* doc.recompute() if progressbar and FreeCAD.GuiUp: progressbar.setValue(100) if status and FreeCAD.GuiUp: status.setText("import finished.") FreeCADGui.updateGui() organize_doc(doc) doc.recompute() endtime = time.time() say(("running time ", int(endtime-starttime), " count ways ", count_ways)) return True
def get_ppts_with_heights(way, way_type, points, nodesbyid, baseheight): plg_pts_latlon = [] for n in way.getiterator("nd"): # say(n.params) m = nodesbyid[n.params["ref"]] plg_pts_latlon.append([ n.params["ref"], m.params["lat"], m.params["lon"] ]) say(" baseheight: {}".format(baseheight)) say(" get heights for " + str(len(plg_pts_latlon))) heights = get_height_list(plg_pts_latlon) # say(heights) # set the scaled height for each way polygon point height = None polygon_points = [] for n in way.getiterator("nd"): wpt = points[str(n.params["ref"])] # say(wpt) m = nodesbyid[n.params["ref"]] # say(m.params) hkey = "{:.7f} {:.7f}".format( float(m.params["lat"]), float(m.params["lon"]) ) # say(hkey) if way_type == "building": # for buildings use the height of the first point for all # thus code a bit different from the others # TODO use 10 cm below the lowest not the first # Why do we get all heights if only use one # but we need them all to get the lowest if height is None: say(" Building") if hkey in heights: say(" height abs: {}".format(heights[hkey])) height = heights[hkey] say(heights[hkey]) say(" height rel: {}".format(height)) else: sayErr(" ---no height in heights for " + hkey) height = baseheight elif way_type == "highway": # use the height for all points if height is None: say(" Highway") if hkey in heights: height = heights[hkey] else: sayErr(" ---no height in heights for " + hkey) height = baseheight elif way_type == "landuse": # use 1 mm above base height if height is None: sayErr(" ---no height used for landuse ATM") height = baseheight + 1 else: # use the height for all points if height is None: say(" Other") if hkey in heights: height = heights[hkey] else: sayErr(" ---no height in heights for " + hkey) height = baseheight if height is None: height = baseheight wpt.z = height - baseheight # say(" with base: {}".format(wpt.z)) polygon_points.append(wpt) return polygon_points
def get_way_information(w): st = "" st2 = "" nr = "" building_height = 0 # ci is never used # ci = "" way_type = "" for t in w.getiterator("tag"): try: if debug: say(t) # say(t.params["k"]) # say(t.params["v"]) if str(t.params["k"]) == "building": way_type = "building" if st == "": st = "building" if str(t.params["k"]) == "landuse": way_type = "landuse" st = t.params["k"] nr = t.params["v"] if str(t.params["k"]) == "highway": way_type = "highway" st = t.params["k"] if str(t.params["k"]) == "addr:city": pass # ci is never used # ci = t.params["v"] if str(t.params["k"]) == "name": nr = t.params["v"] if str(t.params["k"]) == "ref": nr = t.params["v"]+" /" if str(t.params["k"]) == "addr:street": st2 = " "+t.params["v"] if str(t.params["k"]) == "addr:housenumber": nr = str(t.params["v"]) if str(t.params["k"]) == "building:levels": if building_height == 0: building_height = int(str(t.params["v"]))*1000*3 if str(t.params["k"]) == "building:height": building_height = int(str(t.params["v"]))*1000 except Exception: sayErr("unexpected error {}".format(50*"#")) name = "{}{} {}".format(st, st2, nr) if name == " ": name = "landuse xyz" if debug: say("name {}".format(name)) return (name, way_type, nr, building_height)