def write(self, writer): mapTo3d = writer.settings.mapTo3d() writer.write("bl = lyr.addBlock({0}, {1});\n".format( pyobj2js(self.properties), pyobj2js(bool(self.clip_geometry)))) writer.write("bl.data = [{0}];\n".format(",".join( map(gdal2threejs.formatValue, self.dem_values)))) # clipped with polygon layer if self.clip_geometry: z_func = lambda x, y: 0 transform_func = lambda x, y, z: mapTo3d.transform(x, y, z) geom = PolygonGeometry.fromQgsGeometry(self.clip_geometry, z_func, transform_func) geom.splitPolygon( writer.triangleMesh(self.dem_width, self.dem_height)) polygons = [] for polygon in geom.polygons: bnds = [] for boundary in polygon: bnds.append(map(lambda pt: [pt.x, pt.y], boundary)) polygons.append(bnds) writer.write("bl.clip = {};\n") writer.write("bl.clip.polygons = {0};\n".format( pyobj2js(polygons))) triangles = Triangles() polygons = [] for polygon in geom.split_polygons: boundary = polygon[0] if len(polygon) == 1 and len(boundary) == 4: # vertex order should be counter-clockwise triangles.addTriangle(boundary[0], boundary[2], boundary[1]) else: bnds = [ map(lambda pt: [pt.x, pt.y], bnd) for bnd in polygon ] polygons.append(bnds) vf = { "v": map(lambda pt: [pt.x, pt.y], triangles.vertices), "f": triangles.faces } writer.write("bl.clip.triangles = {0};\n".format(pyobj2js(vf))) writer.write("bl.clip.split_polygons = {0};\n".format( pyobj2js(polygons)))
def writeBlock(quad_rect, extent, dem_width, dem_height, dem_values, image_width, image_height): # extent = baseExtent.subrectangle(rect) npt = baseExtent.normalizePoint(extent.center().x(), extent.center().y()) block = {"width": dem_width, "height": dem_height} block["plane"] = {"width": quad_rect.width() * mapTo3d.planeWidth, "height": quad_rect.height() * mapTo3d.planeHeight, "offsetX": (npt.x() - 0.5) * mapTo3d.planeWidth, "offsetY": (npt.y() - 0.5) * mapTo3d.planeHeight} # display type if properties.get("radioButton_MapCanvas", False): block["m"] = layer.materialManager.getMapImageIndex(image_width, image_height, extent, transparency, transp_background) elif properties.get("radioButton_LayerImage", False): block["m"] = layer.materialManager.getLayerImageIndex(layerImageIds, image_width, image_height, extent, transparency, transp_background) elif properties.get("radioButton_SolidColor", False): block["m"] = layer.materialManager.getMeshLambertIndex(properties["lineEdit_Color"], transparency, True) # shading (whether compute normals) if properties.get("checkBox_Shading", True): block["shading"] = True # write block writer.nextFile(True) writer.write("bl = lyr.addBlock({0});\n".format(pyobj2js(block))) writer.write("bl.data = [{0}];\n".format(",".join(map(gdal2threejs.formatValue, dem_values))))
def write(self, f, imageManager): if not len(self._list): return toMaterialType = { self.WIREFRAME: self.MESH_LAMBERT, self.MESH_LAMBERT_FLAT: self.MESH_LAMBERT, self.CANVAS_IMAGE: self.MESH_PHONG, self.MAP_IMAGE: self.MESH_PHONG, self.LAYER_IMAGE: self.MESH_PHONG, self.IMAGE_FILE: self.MESH_PHONG } for index, mat in enumerate(self._list): m = {"type": toMaterialType.get(mat[0], mat[0])} transp_background = False if mat[0] == self.CANVAS_IMAGE: transp_background = mat[1] m["i"] = imageManager.canvasImageIndex(transp_background) elif mat[0] == self.MAP_IMAGE: width, height, extent, transp_background = mat[1] m["i"] = imageManager.mapImageIndex(width, height, extent, transp_background) elif mat[0] == self.LAYER_IMAGE: layerids, width, height, extent, transp_background = mat[1] m["i"] = imageManager.layerImageIndex(layerids, width, height, extent, transp_background) elif mat[0] in [self.IMAGE_FILE, self.SPRITE]: filepath, transp_background = mat[1] m["i"] = imageManager.imageIndex(filepath) else: m["c"] = mat[1] if transp_background: m["t"] = 1 if mat[0] == self.WIREFRAME: m["w"] = 1 if mat[0] == self.MESH_LAMBERT_FLAT: m["flat"] = 1 transparency = mat[2] if transparency > 0: opacity = 1.0 - float(transparency) / 100 m["o"] = opacity # double sides if mat[3]: m["ds"] = 1 f.write(u"lyr.m[{0}] = {1};\n".format( index, tools.pyobj2js(m, quoteHex=False)))
def writeLayer(self, obj, fieldNames=None): self.currentLayerIndex = self.layerCount type2classprefix = { "dem": "DEM", "point": "Point", "line": "Line", "polygon": "Polygon" } self.write(u"\n// Layer {0}\n".format(self.currentLayerIndex)) self.write(u"lyr = project.addLayer(new Q3D.{0}Layer({1}));\n".format( type2classprefix[obj["type"]], pyobj2js(obj))) # del obj["type"] if fieldNames is not None: self.write(u"lyr.a = {0};\n".format(pyobj2js(fieldNames))) self.layerCount += 1 self.currentFeatureIndex = -1 self.attrs = [] return self.currentLayerIndex
def writeLayer(self, obj, fieldNames=None): self.currentLayerIndex = self.layerCount type2classprefix = {"dem": "DEM", "point": "Point", "line": "Line", "polygon": "Polygon"} self.write(u"\n// Layer {0}\n".format(self.currentLayerIndex)) self.write(u"lyr = project.addLayer(new Q3D.{0}Layer({1}));\n".format(type2classprefix[obj["type"]], pyobj2js(obj))) # del obj["type"] if fieldNames is not None: self.write(u"lyr.a = {0};\n".format(pyobj2js(fieldNames))) self.layerCount += 1 self.currentFeatureIndex = -1 self.attrs = [] return self.currentLayerIndex
def write(self, f, imageManager): if not len(self._list): return toMaterialType = {self.WIREFRAME: self.MESH_LAMBERT, self.MESH_LAMBERT_FLAT: self.MESH_LAMBERT, self.CANVAS_IMAGE: self.MESH_PHONG, self.MAP_IMAGE: self.MESH_PHONG, self.LAYER_IMAGE: self.MESH_PHONG, self.IMAGE_FILE: self.MESH_PHONG} for index, mat in enumerate(self._list): m = {"type": toMaterialType.get(mat[0], mat[0])} transp_background = False if mat[0] == self.CANVAS_IMAGE: transp_background = mat[1] m["i"] = imageManager.canvasImageIndex(transp_background) elif mat[0] == self.MAP_IMAGE: width, height, extent, transp_background = mat[1] m["i"] = imageManager.mapImageIndex(width, height, extent, transp_background) elif mat[0] == self.LAYER_IMAGE: layerids, width, height, extent, transp_background = mat[1] m["i"] = imageManager.layerImageIndex(layerids, width, height, extent, transp_background) elif mat[0] in [self.IMAGE_FILE, self.SPRITE]: filepath, transp_background = mat[1] m["i"] = imageManager.imageIndex(filepath) else: m["c"] = mat[1] if transp_background: m["t"] = 1 if mat[0] == self.WIREFRAME: m["w"] = 1 if mat[0] == self.MESH_LAMBERT_FLAT: m["flat"] = 1 transparency = mat[2] if transparency > 0: opacity = 1.0 - float(transparency) / 100 m["o"] = opacity # double sides if mat[3]: m["ds"] = 1 f.write(u"lyr.m[{0}] = {1};\n".format(index, tools.pyobj2js(m, quoteHex=False)))
def write(self, writer): mapTo3d = writer.settings.mapTo3d writer.write("bl = lyr.addBlock({0}, {1});\n".format(pyobj2js(self.properties), pyobj2js(bool(self.clip_geometry)))) writer.write("bl.data = [{0}];\n".format(",".join(map(gdal2threejs.formatValue, self.dem_values)))) # clipped with polygon layer if self.clip_geometry: z_func = lambda x, y: 0 transform_func = lambda x, y, z: mapTo3d.transform(x, y, z) geom = PolygonGeometry.fromQgsGeometry(self.clip_geometry, z_func, transform_func) geom.splitPolygon(writer.triangleMesh(self.dem_width, self.dem_height)) polygons = [] for polygon in geom.polygons: bnds = [] for boundary in polygon: bnds.append(map(lambda pt: [pt.x, pt.y], boundary)) polygons.append(bnds) writer.write("bl.clip = {};\n") writer.write("bl.clip.polygons = {0};\n".format(pyobj2js(polygons))) triangles = Triangles() polygons = [] for polygon in geom.split_polygons: boundary = polygon[0] if len(polygon) == 1 and len(boundary) == 4: triangles.addTriangle(boundary[0], boundary[2], boundary[1]) # vertex order should be counter-clockwise else: bnds = [map(lambda pt: [pt.x, pt.y], bnd) for bnd in polygon] polygons.append(bnds) vf = {"v": map(lambda pt: [pt.x, pt.y], triangles.vertices), "f": triangles.faces} writer.write("bl.clip.triangles = {0};\n".format(pyobj2js(vf))) writer.write("bl.clip.split_polygons = {0};\n".format(pyobj2js(polygons)))
def writeProject(self): # write project information self.write(u"// Qgis2threejs Project\n") settings = self.settings extent = self.settings.baseExtent rect = extent.unrotatedRect() mapTo3d = self.settings.mapTo3d() wgs84Center = self.settings.wgs84Center() args = {"title": settings.title, "crs": unicode(settings.crs.authid()), "proj": settings.crs.toProj4(), "baseExtent": [rect.xMinimum(), rect.yMinimum(), rect.xMaximum(), rect.yMaximum()], "rotation": extent.rotation(), "width": mapTo3d.planeWidth, "zExaggeration": mapTo3d.verticalExaggeration, "zShift": mapTo3d.verticalShift, "wgs84Center": {"lat": wgs84Center.y(), "lon": wgs84Center.x()}} self.write(u"project = new Q3D.Project({0});\n".format(pyobj2js(args)))
def writeProject(self): # write project information self.write(u"// Qgis2threejs Project\n") settings = self.settings extent = self.settings.baseExtent rect = extent.unrotatedRect() mapTo3d = self.settings.mapTo3d wgs84Center = self.settings.wgs84Center args = {"title": settings.title, "crs": unicode(settings.crs.authid()), "proj": settings.crs.toProj4(), "baseExtent": [rect.xMinimum(), rect.yMinimum(), rect.xMaximum(), rect.yMaximum()], "rotation": extent.rotation(), "width": mapTo3d.planeWidth, "zExaggeration": mapTo3d.verticalExaggeration, "zShift": mapTo3d.verticalShift, "wgs84Center": {"lat": wgs84Center.y(), "lon": wgs84Center.x()}} self.write(u"project = new Q3D.Project({0});\n".format(pyobj2js(args)))
def writeSimpleDEM(writer, properties, progress=None): settings = writer.settings mapTo3d = settings.mapTo3d progress = progress or dummyProgress prop = DEMPropertyReader(properties) dem_width = prop.width() dem_height = prop.height() # warp dem demLayer = QgsMapLayerRegistry.instance().mapLayer(prop.layerId) if prop.layerId else None if demLayer: layerName = demLayer.name() warp_dem = MemoryWarpRaster(demLayer.source(), str(demLayer.crs().toWkt()), str(settings.crs.toWkt())) else: layerName = "Flat plane" warp_dem = FlatRaster() dem_values = warp_dem.read(dem_width, dem_height, settings.baseExtent.geotransform(dem_width, dem_height)) # calculate statistics stats = {"max": max(dem_values), "min": min(dem_values)} # shift and scale if mapTo3d.verticalShift != 0: dem_values = map(lambda x: x + mapTo3d.verticalShift, dem_values) if mapTo3d.multiplierZ != 1: dem_values = map(lambda x: x * mapTo3d.multiplierZ, dem_values) surroundings = properties.get("checkBox_Surroundings", False) if demLayer else False if surroundings: roughenEdges(dem_width, dem_height, dem_values, properties["spinBox_Roughening"]) # layer layer = DEMLayer(writer, demLayer, prop) lyr = layer.layerObject() lyr.update({"name": layerName, "stats": stats}) lyrIdx = writer.writeLayer(lyr) # dem block block = {"width": dem_width, "height": dem_height} block["plane"] = {"width": mapTo3d.planeWidth, "height": mapTo3d.planeHeight, "offsetX": 0, "offsetY": 0} # material option transparency = properties["spinBox_demtransp"] transp_background = properties.get("checkBox_TransparentBackground", False) # display type if properties.get("radioButton_MapCanvas", False): block["m"] = layer.materialManager.getCanvasImageIndex(transparency, transp_background) elif properties.get("radioButton_LayerImage", False): layerids = properties.get("layerImageIds", []) size = settings.mapSettings.outputSize() block["m"] = layer.materialManager.getLayerImageIndex(layerids, size.width(), size.height(), settings.baseExtent, transparency, transp_background) elif properties.get("radioButton_ImageFile", False): filepath = properties.get("lineEdit_ImageFile", "") block["m"] = layer.materialManager.getImageFileIndex(filepath, transparency, transp_background, True) elif properties.get("radioButton_SolidColor", False): block["m"] = layer.materialManager.getMeshLambertIndex(properties["lineEdit_Color"], transparency, True) #elif properties.get("radioButton_Wireframe", False): # block["m"] = layer.materialManager.getWireframeIndex(properties["lineEdit_Color"], transparency) # shading (whether compute normals) if properties.get("checkBox_Shading", True): block["shading"] = True if not surroundings and properties.get("checkBox_Sides", False): block["s"] = True if not surroundings and properties.get("checkBox_Frame", False): block["frame"] = True # write central block writer.write("bl = lyr.addBlock({0});\n".format(pyobj2js(block))) writer.write("bl.data = [{0}];\n".format(",".join(map(gdal2threejs.formatValue, dem_values)))) # write surrounding dems if surroundings: writeSurroundingDEM(writer, layer, warp_dem, stats, properties, progress) # overwrite stats writer.write("lyr.stats = {0};\n".format(pyobj2js(stats))) writer.writeMaterials(layer.materialManager)
def writeMultiResDEM(writer, properties, progress=None): settings = writer.settings mapSettings = settings.mapSettings mapTo3d = settings.mapTo3d baseExtent = settings.baseExtent progress = progress or dummyProgress prop = DEMPropertyReader(properties) demLayer = QgsMapLayerRegistry.instance().mapLayer(prop.layerId) if demLayer is None: return # layer layer = DEMLayer(writer, demLayer, prop) lyrIdx = writer.writeLayer(layer.layerObject()) warp_dem = MemoryWarpRaster(demLayer.source(), str(demLayer.crs().toWkt()), str(settings.crs.toWkt())) # quad tree quadtree = settings.quadtree if quadtree is None: return quads = quadtree.quads() # (currently) dem size is 2 ^ quadtree.height * a + 1, where a is larger integer than 0 # with smooth resolution change, this is not necessary dem_width = dem_height = max(64, 2 ** quadtree.height) + 1 # material options transparency = properties["spinBox_demtransp"] transp_background = properties.get("checkBox_TransparentBackground", False) layerImageIds = properties.get("layerImageIds", []) # writeBlock function def writeBlock(quad_rect, extent, dem_width, dem_height, dem_values, image_width, image_height): # extent = baseExtent.subrectangle(rect) npt = baseExtent.normalizePoint(extent.center().x(), extent.center().y()) block = {"width": dem_width, "height": dem_height} block["plane"] = {"width": quad_rect.width() * mapTo3d.planeWidth, "height": quad_rect.height() * mapTo3d.planeHeight, "offsetX": (npt.x() - 0.5) * mapTo3d.planeWidth, "offsetY": (npt.y() - 0.5) * mapTo3d.planeHeight} # display type if properties.get("radioButton_MapCanvas", False): block["m"] = layer.materialManager.getMapImageIndex(image_width, image_height, extent, transparency, transp_background) elif properties.get("radioButton_LayerImage", False): block["m"] = layer.materialManager.getLayerImageIndex(layerImageIds, image_width, image_height, extent, transparency, transp_background) elif properties.get("radioButton_SolidColor", False): block["m"] = layer.materialManager.getMeshLambertIndex(properties["lineEdit_Color"], transparency, True) # write block writer.nextFile(True) writer.write("bl = lyr.addBlock({0});\n".format(pyobj2js(block))) writer.write("bl.data = [{0}];\n".format(",".join(map(gdal2threejs.formatValue, dem_values)))) # image size canvas_size = mapSettings.outputSize() hpw = float(canvas_size.height()) / canvas_size.width() if hpw < 1: image_width = settings.image_basesize image_height = round(image_width * hpw) else: image_height = settings.image_basesize image_width = round(image_height / hpw) unites_center = True centerQuads = DEMQuadList(dem_width, dem_height) stats = None for i, quad in enumerate(quads): progress(30 * i / len(quads) + 5) # block extent rect = quad.rect extent = baseExtent.subrectangle(rect) # warp dem dem_values = warp_dem.read(dem_width, dem_height, extent.geotransform(dem_width, dem_height)) if stats is None: stats = {"max": max(dem_values), "min": min(dem_values)} else: stats["max"] = max(max(dem_values), stats["max"]) stats["min"] = min(min(dem_values), stats["min"]) # shift and scale if mapTo3d.verticalShift != 0: dem_values = map(lambda x: x + mapTo3d.verticalShift, dem_values) if mapTo3d.multiplierZ != 1: dem_values = map(lambda x: x * mapTo3d.multiplierZ, dem_values) # calculate DEM values on edges to combine with next DEM block with different resolution neighbors = quadtree.neighbors(quad) for direction, neighbor in enumerate(neighbors): if neighbor is None: continue interval = 2 ** (quad.height - neighbor.height) if interval > 1: if direction == QuadTree.UP or direction == QuadTree.DOWN: y = 0 if direction == QuadTree.UP else dem_height - 1 for x1 in range(interval, dem_width, interval): x0 = x1 - interval z0 = dem_values[x0 + dem_width * y] z1 = dem_values[x1 + dem_width * y] for xx in range(1, interval): z = (z0 * (interval - xx) + z1 * xx) / interval dem_values[x0 + xx + dem_width * y] = z else: # LEFT or RIGHT x = 0 if direction == QuadTree.LEFT else dem_width - 1 for y1 in range(interval, dem_height, interval): y0 = y1 - interval z0 = dem_values[x + dem_width * y0] z1 = dem_values[x + dem_width * y1] for yy in range(1, interval): z = (z0 * (interval - yy) + z1 * yy) / interval dem_values[x + dem_width * (y0 + yy)] = z if unites_center and quad.height == quadtree.height: centerQuads.addQuad(quad, dem_values) else: writeBlock(rect, extent, dem_width, dem_height, dem_values, image_width, image_height) if unites_center: dem_width = (dem_width - 1) * centerQuads.width() + 1 dem_height = (dem_height - 1) * centerQuads.height() + 1 dem_values = centerQuads.unitedDEM() if hpw < 1: image_width = settings.image_basesize * centerQuads.width() image_height = round(image_width * hpw) else: image_height = settings.image_basesize * centerQuads.height() image_width = round(image_height / hpw) # block extent rect = centerQuads.rect() extent = baseExtent.subrectangle(rect) writeBlock(rect, extent, dem_width, dem_height, dem_values, image_width, image_height) writer.write("lyr.stats = {0};\n".format(pyobj2js(stats))) writer.writeMaterials(layer.materialManager)
def writeSurroundingDEM(writer, layer, warp_dem, stats, properties, progress=None): settings = writer.settings mapSettings = settings.mapSettings mapTo3d = settings.mapTo3d baseExtent = settings.baseExtent progress = progress or dummyProgress # options size = properties["spinBox_Size"] roughening = properties["spinBox_Roughening"] transparency = properties["spinBox_demtransp"] transp_background = properties.get("checkBox_TransparentBackground", False) prop = DEMPropertyReader(properties) dem_width = (prop.width() - 1) / roughening + 1 dem_height = (prop.height() - 1) / roughening + 1 # texture image size canvas_size = mapSettings.outputSize() hpw = float(canvas_size.height()) / canvas_size.width() if hpw < 1: image_width = settings.image_basesize image_height = round(image_width * hpw) #image_height = settings.image_basesize * max(1, int(round(1 / hpw))) # not rendered expectedly else: image_height = settings.image_basesize image_width = round(image_height / hpw) center = baseExtent.center() rotation = baseExtent.rotation() size2 = size * size for i in range(size2): progress(20 * i / size2 + 10) if i == (size2 - 1) / 2: # center (map canvas) continue # block extent sx = i % size - (size - 1) / 2 sy = i / size - (size - 1) / 2 block_center = QgsPoint(center.x() + sx * baseExtent.width(), center.y() + sy * baseExtent.height()) extent = RotatedRect(block_center, baseExtent.width(), baseExtent.height()).rotate(rotation, center) # warp dem dem_values = warp_dem.read(dem_width, dem_height, extent.geotransform(dem_width, dem_height)) if stats is None: stats = {"max": max(dem_values), "min": min(dem_values)} else: stats["max"] = max(max(dem_values), stats["max"]) stats["min"] = min(min(dem_values), stats["min"]) # shift and scale if mapTo3d.verticalShift != 0: dem_values = map(lambda x: x + mapTo3d.verticalShift, dem_values) if mapTo3d.multiplierZ != 1: dem_values = map(lambda x: x * mapTo3d.multiplierZ, dem_values) # generate javascript data file # dem block block = {"width": dem_width, "height": dem_height} block["plane"] = {"width": mapTo3d.planeWidth, "height": mapTo3d.planeHeight, "offsetX": mapTo3d.planeWidth * sx, "offsetY": mapTo3d.planeHeight * sy} # display type if properties.get("radioButton_MapCanvas", False): block["m"] = layer.materialManager.getMapImageIndex(image_width, image_height, extent, transparency, transp_background) elif properties.get("radioButton_LayerImage", False): layerids = properties.get("layerImageIds", []) block["m"] = layer.materialManager.getLayerImageIndex(layerids, image_width, image_height, extent, transparency, transp_background) elif properties.get("radioButton_SolidColor", False): block["m"] = layer.materialManager.getMeshLambertIndex(properties["lineEdit_Color"], transparency, True) # write block writer.write("bl = lyr.addBlock({0});\n".format(pyobj2js(block))) writer.write("bl.data = [{0}];\n".format(",".join(map(gdal2threejs.formatValue, dem_values))))
def writeSimpleDEM(writer, properties, progress=None): settings = writer.settings mapTo3d = settings.mapTo3d progress = progress or dummyProgress prop = DEMPropertyReader(properties) dem_width = prop.width() dem_height = prop.height() # warp dem demLayer = QgsMapLayerRegistry.instance().mapLayer(prop.layerId) if prop.layerId else None if demLayer: layerName = demLayer.name() warp_dem = MemoryWarpRaster(demLayer.source(), str(demLayer.crs().toWkt()), str(settings.crs.toWkt())) else: layerName = "Flat plane" warp_dem = FlatRaster() dem_values = warp_dem.read(dem_width, dem_height, settings.baseExtent.geotransform(dem_width, dem_height)) # calculate statistics stats = {"max": max(dem_values), "min": min(dem_values)} # shift and scale if mapTo3d.verticalShift != 0: dem_values = map(lambda x: x + mapTo3d.verticalShift, dem_values) if mapTo3d.multiplierZ != 1: dem_values = map(lambda x: x * mapTo3d.multiplierZ, dem_values) surroundings = properties.get("checkBox_Surroundings", False) if demLayer else False if surroundings: roughenEdges(dem_width, dem_height, dem_values, properties["spinBox_Roughening"]) # layer layer = DEMLayer(writer, demLayer, prop) lyr = layer.layerObject() lyr.update({"name": layerName, "stats": stats}) lyrIdx = writer.writeLayer(lyr) # dem block block = {"width": dem_width, "height": dem_height} block["plane"] = {"width": mapTo3d.planeWidth, "height": mapTo3d.planeHeight, "offsetX": 0, "offsetY": 0} # material option transparency = properties["spinBox_demtransp"] transp_background = properties.get("checkBox_TransparentBackground", False) # display type if properties.get("radioButton_MapCanvas", False): block["m"] = layer.materialManager.getCanvasImageIndex(transparency, transp_background) elif properties.get("radioButton_LayerImage", False): layerids = properties.get("layerImageIds", []) size = settings.mapSettings.outputSize() block["m"] = layer.materialManager.getLayerImageIndex(layerids, size.width(), size.height(), settings.baseExtent, transparency, transp_background) elif properties.get("radioButton_ImageFile", False): filepath = properties.get("lineEdit_ImageFile", "") block["m"] = layer.materialManager.getImageFileIndex(filepath, transparency, transp_background, True) elif properties.get("radioButton_SolidColor", False): block["m"] = layer.materialManager.getMeshLambertIndex(properties["lineEdit_Color"], transparency, True) #elif properties.get("radioButton_Wireframe", False): # block["m"] = layer.materialManager.getWireframeIndex(properties["lineEdit_Color"], transparency) clip_layer = None if not surroundings: # clipping option clip_option = properties.get("checkBox_Clip", False) if clip_option: clip_layerId = properties.get("comboBox_ClipLayer") clip_layer = QgsMapLayerRegistry.instance().mapLayer(clip_layerId) if clip_layerId else None if properties.get("checkBox_Sides", False): block["sides"] = True if properties.get("checkBox_Frame", False) and not clip_option: block["frame"] = True # write central block writer.write("bl = lyr.addBlock({0}, {1});\n".format(pyobj2js(block), pyobj2js(bool(clip_layer)))) writer.write("bl.data = [{0}];\n".format(",".join(map(gdal2threejs.formatValue, dem_values)))) # clipped with polygon layer if clip_layer: geometry = dissolvePolygonsOnCanvas(writer, clip_layer) z_func = lambda x, y: 0 transform_func = lambda x, y, z: mapTo3d.transform(x, y, z) geom = PolygonGeometry.fromQgsGeometry(geometry, z_func, transform_func) geom.splitPolygon(writer.triangleMesh(dem_width, dem_height)) polygons = [] for polygon in geom.polygons: bnds = [] for boundary in polygon: bnds.append(map(lambda pt: [pt.x, pt.y], boundary)) polygons.append(bnds) writer.write("bl.clip = {};\n") writer.write("bl.clip.polygons = {0};\n".format(pyobj2js(polygons))) triangles = Triangles() polygons = [] for polygon in geom.split_polygons: boundary = polygon[0] if len(polygon) == 1 and len(boundary) == 4: triangles.addTriangle(boundary[0], boundary[2], boundary[1]) # vertex order should be counter-clockwise else: bnds = [map(lambda pt: [pt.x, pt.y], bnd) for bnd in polygon] polygons.append(bnds) vf = {"v": map(lambda pt: [pt.x, pt.y], triangles.vertices), "f": triangles.faces} writer.write("bl.clip.triangles = {0};\n".format(pyobj2js(vf))) writer.write("bl.clip.split_polygons = {0};\n".format(pyobj2js(polygons))) # write surrounding dems if surroundings: writeSurroundingDEM(writer, layer, warp_dem, stats, properties, progress) # overwrite stats writer.write("lyr.stats = {0};\n".format(pyobj2js(stats))) writer.writeMaterials(layer.materialManager)
def writeAttributes(self): for index, attrs in enumerate(self.attrs): self.write(u"lyr.f[{0}].a = {1};\n".format(index, pyobj2js(attrs, True)))
def writeFeature(self, f): self.currentFeatureIndex += 1 self.write(u"lyr.f[{0}] = {1};\n".format(self.currentFeatureIndex, pyobj2js(f)))
def writeMultiResDEM(writer, properties, progress=None): settings = writer.settings mapSettings = settings.mapSettings mapTo3d = settings.mapTo3d baseExtent = settings.baseExtent progress = progress or dummyProgress prop = DEMPropertyReader(properties) # DEM provider provider = settings.demProviderByLayerId(prop.layerId) if isinstance(provider, GDALDEMProvider): demLayer = QgsMapLayerRegistry.instance().mapLayer(prop.layerId) layerName = demLayer.name() else: demLayer = None layerName = provider.name() # layer layer = DEMLayer(writer, demLayer, prop) lyr = layer.layerObject() lyr.update({"name": layerName}) lyrIdx = writer.writeLayer(lyr) # quad tree quadtree = settings.quadtree if quadtree is None: return # (currently) dem size is 2 ^ quadtree.height * a + 1, where a is larger integer than 0 # with smooth resolution change, this is not necessary dem_width = dem_height = max(64, 2 ** quadtree.height) + 1 # material options texture_scale = properties["comboBox_TextureSize"] / 100 transparency = properties["spinBox_demtransp"] transp_background = properties.get("checkBox_TransparentBackground", False) layerImageIds = properties.get("layerImageIds", []) def materialIndex(extent, image_width, image_height): # display type if properties.get("radioButton_MapCanvas", False): return layer.materialManager.getMapImageIndex(image_width, image_height, extent, transparency, transp_background) elif properties.get("radioButton_LayerImage", False): return layer.materialManager.getLayerImageIndex(layerImageIds, image_width, image_height, extent, transparency, transp_background) else: #.get("radioButton_SolidColor", False) return layer.materialManager.getMeshLambertIndex(properties["lineEdit_Color"], transparency, True) blocks = DEMBlocks() def addDEMBlock(quad_rect, dem_width, dem_height, dem_values, image_width, image_height): planeWidth = quad_rect.width() * mapTo3d.planeWidth planeHeight = quad_rect.height() * mapTo3d.planeHeight extent = baseExtent.subrectangle(quad_rect) npt = baseExtent.normalizePoint(extent.center().x(), extent.center().y()) offsetX = (npt.x() - 0.5) * mapTo3d.planeWidth offsetY = (npt.y() - 0.5) * mapTo3d.planeHeight block = DEMBlock(dem_width, dem_height, dem_values, planeWidth, planeHeight, offsetX, offsetY) #block.zShift(mapTo3d.verticalShift) #block.zScale(mapTo3d.multiplierZ) block.set("m", materialIndex(extent, image_width, image_height)) blocks.appendBlock(block) # image size canvas_size = mapSettings.outputSize() image_width = canvas_size.width() * texture_scale image_height = canvas_size.height() * texture_scale quads = quadtree.quads() unites_center = True centerQuads = DEMQuadList(dem_width, dem_height) stats = None for i, quad in enumerate(quads): progress(15 * i / len(quads) + 5) # block extent extent = baseExtent.subrectangle(quad.rect) # warp dem dem_values = provider.read(dem_width, dem_height, extent) if stats is None: stats = {"max": max(dem_values), "min": min(dem_values)} else: stats["max"] = max(max(dem_values), stats["max"]) stats["min"] = min(min(dem_values), stats["min"]) # shift and scale if mapTo3d.verticalShift != 0: dem_values = map(lambda x: x + mapTo3d.verticalShift, dem_values) if mapTo3d.multiplierZ != 1: dem_values = map(lambda x: x * mapTo3d.multiplierZ, dem_values) quad.setData(dem_width, dem_height, dem_values) # process edges to eliminate opening between blocks quadtree.processEdges() for i, quad in enumerate(quads): progress(15 * i / len(quads) + 20) if unites_center and quad.height == quadtree.height: centerQuads.addQuad(quad) else: addDEMBlock(quad.rect, quad.dem_width, quad.dem_height, quad.dem_values, image_width, image_height) if unites_center: dem_width = (dem_width - 1) * centerQuads.width() + 1 dem_height = (dem_height - 1) * centerQuads.height() + 1 dem_values = centerQuads.unitedDEM() image_width *= centerQuads.width() image_height *= centerQuads.height() addDEMBlock(centerQuads.rect(), dem_width, dem_height, dem_values, image_width, image_height) blocks.write(writer, separated=True) writer.write("lyr.stats = {0};\n".format(pyobj2js(stats))) writer.writeMaterials(layer.materialManager)
def writeSimpleDEM(writer, properties, progress=None): settings = writer.settings mapTo3d = settings.mapTo3d progress = progress or dummyProgress prop = DEMPropertyReader(properties) # DEM provider provider = settings.demProviderByLayerId(prop.layerId) if isinstance(provider, GDALDEMProvider): demLayer = QgsMapLayerRegistry.instance().mapLayer(prop.layerId) layerName = demLayer.name() else: demLayer = None layerName = provider.name() # layer layer = DEMLayer(writer, demLayer, prop) lyr = layer.layerObject() lyr.update({"name": layerName}) lyrIdx = writer.writeLayer(lyr) # material option texture_scale = properties["comboBox_TextureSize"] / 100 transparency = properties["spinBox_demtransp"] transp_background = properties.get("checkBox_TransparentBackground", False) # display type canvas_size = settings.mapSettings.outputSize() if properties.get("radioButton_MapCanvas", False): if texture_scale == 1: mat = layer.materialManager.getCanvasImageIndex(transparency, transp_background) else: mat = layer.materialManager.getMapImageIndex(canvas_size.width() * texture_scale, canvas_size.height() * texture_scale, settings.baseExtent, transparency, transp_background) elif properties.get("radioButton_LayerImage", False): layerids = properties.get("layerImageIds", []) mat = layer.materialManager.getLayerImageIndex(layerids, canvas_size.width() * texture_scale, canvas_size.height() * texture_scale, settings.baseExtent, transparency, transp_background) elif properties.get("radioButton_ImageFile", False): filepath = properties.get("lineEdit_ImageFile", "") mat = layer.materialManager.getImageFileIndex(filepath, transparency, transp_background, True) else: #.get("radioButton_SolidColor", False) mat = layer.materialManager.getMeshLambertIndex(properties["lineEdit_Color"], transparency, True) #elif properties.get("radioButton_Wireframe", False): # block["m"] = layer.materialManager.getWireframeIndex(properties["lineEdit_Color"], transparency) # get DEM values dem_width, dem_height = prop.width(), prop.height() dem_values = provider.read(dem_width, dem_height, settings.baseExtent) # DEM block block = DEMBlock(dem_width, dem_height, dem_values, mapTo3d.planeWidth, mapTo3d.planeHeight, 0, 0) block.zShift(mapTo3d.verticalShift) block.zScale(mapTo3d.multiplierZ) block.set("m", mat) surroundings = properties.get("checkBox_Surroundings", False) if prop.layerId else False if surroundings: blocks = DEMBlocks() blocks.appendBlock(block) blocks.appendBlocks(surroundingDEMBlocks(writer, layer, provider, properties, progress)) blocks.processEdges() blocks.write(writer) writer.write("lyr.stats = {0};\n".format(pyobj2js(blocks.stats()))) else: # clipping if properties.get("checkBox_Clip", False): clip_layerId = properties.get("comboBox_ClipLayer") clip_layer = QgsMapLayerRegistry.instance().mapLayer(clip_layerId) if clip_layerId else None if clip_layer: block.setClipGeometry(dissolvePolygonsOnCanvas(writer, clip_layer)) # sides and bottom if properties.get("checkBox_Sides", False): block.set("sides", True) # frame if properties.get("checkBox_Frame", False) and not clip_option: block.set("frame", True) block.write(writer) writer.write("lyr.stats = {0};\n".format(pyobj2js(block.orig_stats))) # materials writer.writeMaterials(layer.materialManager)
def writeMultiResDEM(writer, properties, progress=None): settings = writer.settings mapSettings = settings.mapSettings mapTo3d = settings.mapTo3d() baseExtent = settings.baseExtent progress = progress or dummyProgress prop = DEMPropertyReader(properties) # DEM provider provider = settings.demProviderByLayerId(prop.layerId) if isinstance(provider, GDALDEMProvider): demLayer = QgsMapLayerRegistry.instance().mapLayer(prop.layerId) layerName = demLayer.name() else: demLayer = None layerName = provider.name() # layer layer = DEMLayer(writer, demLayer, prop) lyr = layer.layerObject() lyr.update({"name": layerName}) writer.writeLayer(lyr) # quad tree quadtree = settings.quadtree() if quadtree is None: return # (currently) dem size is 2 ^ quadtree.height * a + 1, where a is larger integer than 0 # with smooth resolution change, this is not necessary dem_width = dem_height = max(64, 2**quadtree.height) + 1 # material options texture_scale = properties.get("comboBox_TextureSize", 100) / 100 transparency = properties.get("spinBox_demtransp", 0) transp_background = properties.get("checkBox_TransparentBackground", False) layerImageIds = properties.get("layerImageIds", []) def materialIndex(extent, image_width, image_height): # display type if properties.get("radioButton_MapCanvas", False): return layer.materialManager.getMapImageIndex( image_width, image_height, extent, transparency, transp_background) elif properties.get("radioButton_LayerImage", False): return layer.materialManager.getLayerImageIndex( layerImageIds, image_width, image_height, extent, transparency, transp_background) else: # .get("radioButton_SolidColor", False) return layer.materialManager.getMeshLambertIndex( properties.get("lineEdit_Color", ""), transparency, True) blocks = DEMBlocks() def addDEMBlock(quad_rect, dem_width, dem_height, dem_values, image_width, image_height): planeWidth = quad_rect.width() * mapTo3d.planeWidth planeHeight = quad_rect.height() * mapTo3d.planeHeight extent = baseExtent.subrectangle(quad_rect) npt = baseExtent.normalizePoint(extent.center().x(), extent.center().y()) offsetX = (npt.x() - 0.5) * mapTo3d.planeWidth offsetY = (npt.y() - 0.5) * mapTo3d.planeHeight block = DEMBlock(dem_width, dem_height, dem_values, planeWidth, planeHeight, offsetX, offsetY) # block.zShift(mapTo3d.verticalShift) # block.zScale(mapTo3d.multiplierZ) block.set("m", materialIndex(extent, image_width, image_height)) blocks.appendBlock(block) # image size canvas_size = mapSettings.outputSize() image_width = canvas_size.width() * texture_scale image_height = canvas_size.height() * texture_scale quads = quadtree.quads() unites_center = True centerQuads = DEMQuadList(dem_width, dem_height) stats = None for i, quad in enumerate(quads): progress(15 * i / len(quads) + 5) # block extent extent = baseExtent.subrectangle(quad.rect) # warp dem dem_values = provider.read(dem_width, dem_height, extent) if stats is None: stats = {"max": max(dem_values), "min": min(dem_values)} else: stats["max"] = max(max(dem_values), stats["max"]) stats["min"] = min(min(dem_values), stats["min"]) # shift and scale if mapTo3d.verticalShift != 0: dem_values = map(lambda x: x + mapTo3d.verticalShift, dem_values) if mapTo3d.multiplierZ != 1: dem_values = map(lambda x: x * mapTo3d.multiplierZ, dem_values) quad.setData(dem_width, dem_height, dem_values) # process edges to eliminate opening between blocks quadtree.processEdges() for i, quad in enumerate(quads): progress(15 * i / len(quads) + 20) if unites_center and quad.height == quadtree.height: centerQuads.addQuad(quad) else: addDEMBlock(quad.rect, quad.dem_width, quad.dem_height, quad.dem_values, image_width, image_height) if unites_center: dem_width = (dem_width - 1) * centerQuads.width() + 1 dem_height = (dem_height - 1) * centerQuads.height() + 1 dem_values = centerQuads.unitedDEM() image_width *= centerQuads.width() image_height *= centerQuads.height() addDEMBlock(centerQuads.rect(), dem_width, dem_height, dem_values, image_width, image_height) blocks.write(writer, separated=True) writer.write("lyr.stats = {0};\n".format(pyobj2js(stats))) writer.writeMaterials(layer.materialManager)
def writeSimpleDEM(writer, properties, progress=None): settings = writer.settings mapTo3d = settings.mapTo3d() progress = progress or dummyProgress prop = DEMPropertyReader(properties) # DEM provider provider = settings.demProviderByLayerId(prop.layerId) if isinstance(provider, GDALDEMProvider): demLayer = QgsMapLayerRegistry.instance().mapLayer(prop.layerId) layerName = demLayer.name() else: demLayer = None layerName = provider.name() # layer layer = DEMLayer(writer, demLayer, prop) lyr = layer.layerObject() lyr.update({"name": layerName}) writer.writeLayer(lyr) # material option texture_scale = properties.get("comboBox_TextureSize", 100) / 100 transparency = properties.get("spinBox_demtransp", 0) transp_background = properties.get("checkBox_TransparentBackground", False) # display type canvas_size = settings.mapSettings.outputSize() if properties.get("radioButton_MapCanvas", False): if texture_scale == 1: mat = layer.materialManager.getCanvasImageIndex( transparency, transp_background) else: mat = layer.materialManager.getMapImageIndex( canvas_size.width() * texture_scale, canvas_size.height() * texture_scale, settings.baseExtent, transparency, transp_background) elif properties.get("radioButton_LayerImage", False): layerids = properties.get("layerImageIds", []) mat = layer.materialManager.getLayerImageIndex( layerids, canvas_size.width() * texture_scale, canvas_size.height() * texture_scale, settings.baseExtent, transparency, transp_background) elif properties.get("radioButton_ImageFile", False): filepath = properties.get("lineEdit_ImageFile", "") mat = layer.materialManager.getImageFileIndex(filepath, transparency, transp_background, True) else: # .get("radioButton_SolidColor", False) mat = layer.materialManager.getMeshLambertIndex( properties.get("lineEdit_Color", ""), transparency, True) # elif properties.get("radioButton_Wireframe", False): # block["m"] = layer.materialManager.getWireframeIndex(properties["lineEdit_Color"], transparency) # get DEM values dem_size = prop.demSize(settings.mapSettings.outputSize()) dem_width, dem_height = dem_size.width(), dem_size.height() dem_values = provider.read(dem_width, dem_height, settings.baseExtent) # DEM block block = DEMBlock(dem_width, dem_height, dem_values, mapTo3d.planeWidth, mapTo3d.planeHeight, 0, 0) block.zShift(mapTo3d.verticalShift) block.zScale(mapTo3d.multiplierZ) block.set("m", mat) surroundings = properties.get("checkBox_Surroundings", False) if prop.layerId else False if surroundings: blocks = DEMBlocks() blocks.appendBlock(block) blocks.appendBlocks( surroundingDEMBlocks(writer, layer, provider, properties, progress)) blocks.processEdges() blocks.write(writer) writer.write("lyr.stats = {0};\n".format(pyobj2js(blocks.stats()))) else: # clipping clip_option = properties.get("checkBox_Clip", False) if clip_option: clip_layerId = properties.get("comboBox_ClipLayer") clip_layer = QgsMapLayerRegistry.instance().mapLayer( clip_layerId) if clip_layerId else None if clip_layer: block.setClipGeometry( dissolvePolygonsOnCanvas(writer, clip_layer)) # sides and bottom if properties.get("checkBox_Sides", False): block.set("sides", True) # frame if properties.get("checkBox_Frame", False) and not clip_option: block.set("frame", True) block.write(writer) writer.write("lyr.stats = {0};\n".format(pyobj2js(block.orig_stats))) # materials writer.writeMaterials(layer.materialManager)