def writeVectors(writer, legendInterface, progress=None):
  settings = writer.settings
  baseExtent = settings.baseExtent
  progress = progress or dummyProgress
  renderer = QgsMapRenderer()

  layers = []
  for layer in legendInterface.layers():
    if layer.type() != QgsMapLayer.VectorLayer:
      continue

    parentId = ObjectTreeItem.parentIdByLayer(layer)
    properties = settings.get(parentId, {}).get(layer.id(), {})
    if properties.get("visible", False):
      layers.append([layer.id(), properties])

  finishedLayers = 0
  for layerId, properties in layers:
    mapLayer = QgsMapLayerRegistry.instance().mapLayer(layerId)
    if mapLayer is None:
      continue

    prop = VectorPropertyReader(writer.objectTypeManager, mapLayer, properties)
    obj_mod = writer.objectTypeManager.module(prop.mod_index)
    if obj_mod is None:
      qDebug("Module not found")
      continue

    # prepare triangle mesh
    geom_type = mapLayer.geometryType()
    if geom_type == QGis.Polygon and prop.type_index == 1 and prop.isHeightRelativeToDEM():   # Overlay
      progress(None, "Initializing triangle mesh for overlay polygons")
      writer.triangleMesh()

    progress(30 + 30 * finishedLayers / len(layers), u"Writing vector layer ({0} of {1}): {2}".format(finishedLayers + 1, len(layers), mapLayer.name()))

    # write layer object
    layer = VectorLayer(writer, mapLayer, prop, obj_mod)
    writer.writeLayer(layer.layerObject(), layer.fieldNames)

    # initialize symbol rendering
    mapLayer.rendererV2().startRender(renderer.rendererContext(), mapLayer.pendingFields() if apiChanged23 else mapLayer)

    # features to export
    request = QgsFeatureRequest()
    clipGeom = None
    if properties.get("radioButton_IntersectingFeatures", False):
      request.setFilterRect(layer.transform.transformBoundingBox(baseExtent.boundingBox(), QgsCoordinateTransform.ReverseTransform))
      if properties.get("checkBox_Clip"):
        extent = baseExtent.clone().scale(0.999999)   # clip with slightly smaller extent than map canvas extent
        clipGeom = extent.geometry()

    for feat in layer.features(request, clipGeom):
      # write geometry
      obj_mod.write(writer, layer, feat)   # writer.writeFeature(layer, feat, obj_mod)

      # stack attributes in writer
      if layer.writeAttrs:
        writer.addAttributes(feat.attributes())

    # write attributes
    if layer.writeAttrs:
      writer.writeAttributes()

    # write materials
    writer.writeMaterials(layer.materialManager)

    mapLayer.rendererV2().stopRender(renderer.rendererContext())
    finishedLayers += 1
def writeVectors(writer):
  context = writer.context
  canvas = context.canvas
  mapTo3d = context.mapTo3d
  warp_dem = context.warp_dem
  renderer = QgsMapRenderer()

  layerProperties = {}
  for itemType in [ObjectTreeItem.ITEM_POINT, ObjectTreeItem.ITEM_LINE, ObjectTreeItem.ITEM_POLYGON]:
    for layerId, properties in context.properties[itemType].iteritems():
      if properties.get("visible", False):
        layerProperties[layerId] = properties

  for layerId, properties in layerProperties.iteritems():
    layer = QgsMapLayerRegistry().instance().mapLayer(layerId)
    if layer is None:
      continue
    geom_type = layer.geometryType()
    prop = VectorPropertyReader(context.objectTypeManager, layer, properties)
    obj_mod = context.objectTypeManager.module(prop.mod_index)
    if obj_mod is None:
      qDebug("Module not found")
      continue

    # write layer object
    lyr = {"name": layer.name(), "f": []}
    lyr["type"] = {QGis.Point: "point", QGis.Line: "line", QGis.Polygon: "polygon"}.get(geom_type, "")
    lyr["q"] = 1    #queryable
    lyr["objType"] = prop.type_name

    # make list of field names
    writeAttrs = properties.get("checkBox_ExportAttrs", False)
    fieldNames = None
    if writeAttrs:
      fieldNames = []
      fields = layer.pendingFields()
      for i in range(fields.count()):
        fieldNames.append(fields[i].name())

    hasLabel = False
    if writeAttrs:
      attIdx = properties.get("comboBox_Label", None)
      if attIdx is not None:
        labelHeight = properties.get("labelHeightWidget", [0] * 3)
        lyr["l"] = {"i": attIdx, "ht": int(labelHeight[0]), "v": float(labelHeight[2]) * mapTo3d.multiplierZ}
        hasLabel = True

    # wreite layer object
    writer.writeLayer(lyr, fieldNames)

    # initialize symbol rendering
    layer.rendererV2().startRender(renderer.rendererContext(), layer.pendingFields() if apiChanged23 else layer)

    feat = Feature(layer, prop)
    transform = QgsCoordinateTransform(layer.crs(), context.crs)
    wkt = str(context.crs.toWkt())
    request = QgsFeatureRequest().setFilterRect(transform.transformBoundingBox(canvas.extent(), QgsCoordinateTransform.ReverseTransform))
    for f in layer.getFeatures(request):
      feat.clearGeometry()
      feat.setQgsFeature(f)

      geom = f.geometry()
      geom_type == geom.type()
      wkb_type = geom.wkbType()
      if geom_type == QGis.Point:
        if prop.useZ():
          for pt in pointsFromWkb25D(geom.asWkb(), transform):
            feat.addPoint(mapTo3d.transform(pt[0], pt[1], pt[2] + prop.relativeHeight(f)))
          obj_mod.write(writer, feat)
        else:
          if geom.isMultipart():
            points = geom.asMultiPoint()
          else:
            points = [geom.asPoint()]

          for point in points:
            pt = transform.transform(point)
            if prop.isHeightRelativeToSurface():
              # get surface elevation at the point and relative height
              h = warp_dem.readValue(wkt, pt.x(), pt.y()) + prop.relativeHeight(f)
            else:
              h = prop.relativeHeight(f)
            feat.addPoint(mapTo3d.transform(pt[0], pt[1], h))
          obj_mod.write(writer, feat)

      elif geom_type == QGis.Line:
        if prop.useZ():
          for line in linesFromWkb25D(geom.asWkb(), transform):
            points = []
            for pt in line:
              h = pt[2] + prop.relativeHeight(f)
              points.append(mapTo3d.transform(pt[0], pt[1], h))
            feat.addLine(points)
          obj_mod.write(writer, feat)
        else:
          if geom.isMultipart():
            lines = geom.asMultiPolyline()
          else:
            lines = [geom.asPolyline()]
          for line in lines:
            points = []
            for pt_orig in line:
              pt = transform.transform(pt_orig)
              if prop.isHeightRelativeToSurface():
                h = warp_dem.readValue(wkt, pt.x(), pt.y()) + prop.relativeHeight(f)
              else:
                h = prop.relativeHeight(f)
              points.append(mapTo3d.transform(pt.x(), pt.y(), h))
            feat.addLine(points)
          obj_mod.write(writer, feat)

      elif geom_type == QGis.Polygon:
        useCentroidHeight = True
        labelPerPolygon = True

        if geom.isMultipart():
          polygons = geom.asMultiPolygon()
        else:
          polygons = [geom.asPolygon()]

        if hasLabel and not labelPerPolygon:
          centroidHeight = 0
          pt = transform.transform(geom.centroid().asPoint())
          if prop.isHeightRelativeToSurface():
            centroidHeight = warp_dem.readValue(wkt, pt.x(), pt.y()) + prop.relativeHeight(f)
          else:
            centroidHeight = prop.relativeHeight(f)
          feat.addCentroid(mapTo3d.transform(pt.x(), pt.y(), centroidHeight))

        for polygon in polygons:
          if useCentroidHeight or hasLabel:
            centroidHeight = 0
            pt = transform.transform(QgsGeometry.fromPolygon(polygon).centroid().asPoint())
            if prop.isHeightRelativeToSurface():
              centroidHeight = warp_dem.readValue(wkt, pt.x(), pt.y()) + prop.relativeHeight(f)
            else:
              centroidHeight = prop.relativeHeight(f)
            if hasLabel and labelPerPolygon:
              feat.addCentroid(mapTo3d.transform(pt.x(), pt.y(), centroidHeight))

          boundaries = []
          points = []
          # outer boundary
          for pt_orig in polygon[0]:
            pt = transform.transform(pt_orig)
            if useCentroidHeight:
              h = centroidHeight
            elif prop.isHeightRelativeToSurface():
              h = warp_dem.readValue(wkt, pt.x(), pt.y()) + prop.relativeHeight(f)
            else:
              h = prop.relativeHeight(f)
            points.append(mapTo3d.transform(pt.x(), pt.y(), h))
          boundaries.append(points)
          # inner boundaries
          for inBoundary in polygon[1:]:
            points = []
            for pt_orig in inBoundary:
              pt = transform.transform(pt_orig)
              if useCentroidHeight:
                h = centroidHeight
              elif prop.isHeightRelativeToSurface():
                h = warp_dem.readValue(wkt, pt.x(), pt.y()) + prop.relativeHeight(f)
              else:
                h = prop.relativeHeight(f)
              points.append(mapTo3d.transform(pt.x(), pt.y(), h))
            points.reverse()    # to counter clockwise direction
            boundaries.append(points)
          feat.addPolygon(boundaries)
        obj_mod.write(writer, feat)

      # stack attributes in writer
      if writeAttrs:
        writer.addAttributes(f.attributes())
    # write attributes
    if writeAttrs:
      writer.writeAttributes()

    layer.rendererV2().stopRender(renderer.rendererContext())

  # write materials
  writer.materialManager.write(writer)
Esempio n. 3
0
def writeVectors(writer, legendInterface=None, progress=None):
    settings = writer.settings
    baseExtent = settings.baseExtent
    progress = progress or dummyProgress
    renderer = QgsMapRenderer()

    layers = []
    if legendInterface is None:
        for parentId in [
                ObjectTreeItem.ITEM_POINT, ObjectTreeItem.ITEM_LINE,
                ObjectTreeItem.ITEM_POLYGON
        ]:
            for layerId, properties in settings.get(parentId, {}).iteritems():
                if properties.get("visible", False):
                    layers.append([layerId, properties])
    else:
        # use vector layer order in legendInterface
        for layer in legendInterface.layers():
            if layer.type() != QgsMapLayer.VectorLayer:
                continue

            parentId = ObjectTreeItem.parentIdByLayer(layer)
            properties = settings.get(parentId, {}).get(layer.id(), {})
            if properties.get("visible", False):
                layers.append([layer.id(), properties])

    finishedLayers = 0
    for layerId, properties in layers:
        mapLayer = QgsMapLayerRegistry.instance().mapLayer(layerId)
        if mapLayer is None:
            continue

        prop = VectorPropertyReader(writer.objectTypeManager, mapLayer,
                                    properties)
        obj_mod = writer.objectTypeManager.module(prop.mod_index)
        if obj_mod is None:
            logMessage("Module not found")
            continue

        # prepare triangle mesh
        geom_type = mapLayer.geometryType()
        if geom_type == QGis.Polygon and prop.type_index == 1 and prop.isHeightRelativeToDEM(
        ):  # Overlay
            progress(None, "Initializing triangle mesh for overlay polygons")
            writer.triangleMesh()

        progress(
            30 + 30 * finishedLayers / len(layers),
            u"Writing vector layer ({0} of {1}): {2}".format(
                finishedLayers + 1, len(layers), mapLayer.name()))

        # write layer object
        layer = VectorLayer(writer, mapLayer, prop, obj_mod)
        writer.writeLayer(layer.layerObject(), layer.fieldNames)

        # initialize symbol rendering
        mapLayer.rendererV2().startRender(
            renderer.rendererContext(),
            mapLayer.pendingFields()
            if QGis.QGIS_VERSION_INT >= 20300 else mapLayer)

        # features to export
        request = QgsFeatureRequest()
        clipGeom = None
        if properties.get("radioButton_IntersectingFeatures", False):
            request.setFilterRect(
                layer.transform.transformBoundingBox(
                    baseExtent.boundingBox(),
                    QgsCoordinateTransform.ReverseTransform))
            if properties.get("checkBox_Clip"):
                extent = baseExtent.clone().scale(
                    0.999999
                )  # clip with slightly smaller extent than map canvas extent
                clipGeom = extent.geometry()

        for feat in layer.features(request, clipGeom):
            # write geometry
            obj_mod.write(writer, layer,
                          feat)  # writer.writeFeature(layer, feat, obj_mod)

            # stack attributes in writer
            if layer.writeAttrs:
                writer.addAttributes(feat.attributes())

        # write attributes
        if layer.writeAttrs:
            writer.writeAttributes()

        # write materials
        writer.writeMaterials(layer.materialManager)

        mapLayer.rendererV2().stopRender(renderer.rendererContext())
        finishedLayers += 1