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 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 writeProject(self): # write project information self.write(u"// PhyloGeoRec 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 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)
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)))