Recreate the following script to run as a standalone version using a .shp file as input (Erven polygons) and generating everything it needs from that to fill the inputs to this script. Show everything being created in a viewbox verbosely every step of the way and have the output be a kml containing all the generated data: import math

from PyQt4.QtCore import QVariant, QPyNullVariant  #@UnresolvedImport

from qgis.core import QGis, QgsFeature, QgsFeatureRequest, QgsVectorLayer, QgsSpatialIndex, \
    QgsFields, QgsField, QgsGeometry, QgsCoordinateReferenceSystem

from processing.core.GeoAlgorithm import GeoAlgorithm
from processing.core.parameters import ParameterVector, ParameterNumber, ParameterTableField
from processing.core.outputs import OutputVector
from processing.tools import dataobjects, vector
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException

from qgis.networkanalysis import QgsLineVectorLayerDirector, QgsGraphAnalyzer, QgsGraphBuilder

from properter import FeatureIdProperter, CostFactorProperter
from utility import addFieldToLayer, resolveFieldIndex, getUUID, getIntermediateLayersCrs, getDefaultPathCost

import config as cf

from WorkContextTracer.workcontexttracer import WorkContextTracer


class HightLevelDesign(GeoAlgorithm):

    DEMAND_LAYER = 'DEMAND_LAYER'
    OLT_LAYER = 'OLT_LAYER'
    ROUTE_LINE_LAYER = 'ROUTE_LINE_LAYER'
    POTENTIAL_POINTS_LAYER = 'POTENTIAL_POINTS_LAYER'
    AGGREGARED_DEMAND = 'AGGREGARED_DEMAND'
    SPLITTER = 'SPLITTER'
    MAX_SPLIT = 'MAX_SPLIT'
    PATH_SHARING = 'PATH_SHARING'
    PATH_COST = 'PATH_COST'

    OUT_NODE = 'OUT_NODE'
    OUT_CABLE = 'OUT_CABLE'

    def defineCharacteristics(self):

        self.name = self.tr('Hight level design')

        self.group = self.tr('MAIN')

        self.addParameter(ParameterVector(self.DEMAND_LAYER,
                                          self.tr('Demand points'), [ParameterVector.VECTOR_TYPE_POINT], False))

        self.addParameter(ParameterVector(self.OLT_LAYER,
                                          self.tr('OLT'), [ParameterVector.VECTOR_TYPE_POINT], False))

        self.addParameter(ParameterVector(self.ROUTE_LINE_LAYER,
                                          self.tr('Route line'), [ParameterVector.VECTOR_TYPE_LINE], False))

        self.addParameter(ParameterVector(self.POTENTIAL_POINTS_LAYER,
                                          self.tr('Potential node places'), [ParameterVector.VECTOR_TYPE_POINT], True))

        self.addParameter(ParameterVector(self.AGGREGARED_DEMAND,
                                          self.tr('Aggregated demand'), [ParameterVector.VECTOR_TYPE_POINT], False))

        self.addParameter(ParameterNumber(self.SPLITTER,
                                          self.tr('Splitter size'), 1, 512, 16, False))

        self.addParameter(ParameterNumber(self.MAX_SPLIT,
                                          self.tr('Maximum split'), 1, 512, 64, False))

        self.addParameter(ParameterNumber(self.PATH_SHARING,
                                          self.tr('Path sharing'), 0.0, 1.0, 0.5, False))

        self.addParameter(ParameterTableField(self.PATH_COST,
                                              self.tr('Path cost per unit'), self.ROUTE_LINE_LAYER, -1, True))

        self.addOutput(OutputVector(self.OUT_NODE, self.tr('Potential nodes')))

        self.addOutput(OutputVector(self.OUT_CABLE, self.tr('Cable route')))

    def processAlgorithm(self, progress):

        demandLayerFile = self.getParameterValue(self.DEMAND_LAYER)
        oltLayerFile = self.getParameterValue(self.OLT_LAYER)
        routeLineLayerFile = self.getParameterValue(self.ROUTE_LINE_LAYER)
        potentialPointsLayerFile = self.getParameterValue(self.POTENTIAL_POINTS_LAYER)
        aggregatedDemandLayerFile = self.getParameterValue(self.AGGREGARED_DEMAND)
        splitterSize = int(self.getParameterValue(self.SPLITTER))
        maximumSplit = int(self.getParameterValue(self.MAX_SPLIT))
        self.pathSharing = self.getParameterValue(self.PATH_SHARING)
        self.pathCostField = self.getParameterValue(self.PATH_COST)

        demandLayer = dataobjects.getObjectFromUri(demandLayerFile)
        oltLayer = dataobjects.getObjectFromUri(oltLayerFile)
        routeLineLayer = dataobjects.getObjectFromUri(routeLineLayerFile)
        potentialPointsLayer = dataobjects.getObjectFromUri(potentialPointsLayerFile)
        aggregatedDemandLayer = dataobjects.getObjectFromUri(aggregatedDemandLayerFile)

        outputNode = self.getOutputFromName(self.OUT_NODE)
        outputCable = self.getOutputFromName(self.OUT_CABLE)

        if WorkContextTracer().isActiveWorkContext():
            self.planName = WorkContextTracer().activeWorkContext()
        else:
            raise GeoAlgorithmExecutionException(self.tr('No work context available.'))

        self.crsAuthid = getIntermediateLayersCrs()

        self.nodes = []
        self.routeIds = set()

        oltFeaturesCount = len(vector.features(oltLayer))
        if oltLayer.selectedFeatureCount() != 1 and oltFeaturesCount > 1:
            raise GeoAlgorithmExecutionException(self.tr(u'Invalid OLT selection. Please select one feature from OLT layer.'))
        elif oltFeaturesCount == 1:
            oltFeature = next(f for f in vector.features(oltLayer))
        else:
            oltFeature = oltLayer.selectedFeatures()[0]

        if oltFeature.geometry() is None:
            raise GeoAlgorithmExecutionException(self.tr(u'Bad or missing OLT feature.'))

        progress.setInfo(self.tr('Data preparation...'))

        groupQuantity = self.aggregateDemand(demandLayer, aggregatedDemandLayer, splitterSize)

        additionalPoints = []

        if potentialPointsLayer is not None:
            pointSpatialIndexLayer = potentialPointsLayer
            spIndex = vector.spatialindex(potentialPointsLayer)
            for feature in vector.features(potentialPointsLayer):
                additionalPoints.append(feature.geometry().asPoint())
        else:
            (pointSpatialIndexLayer, spIndex) = self.createSpatialIndex(progress, routeLineLayer)

        graphLayer = self.prepareGraphLayer(routeLineLayer)
        self.graph = self.createGraph(graphLayer, additionalPoints)

        self.prepareOutput(outputNode, outputCable, routeLineLayer)

        progress.setInfo(self.tr('Searching for OLT vertex...'))
        oltFeatureVertex = self.findOLT(oltFeature, pointSpatialIndexLayer, spIndex, maximumSplit)

        endingFeatures = {}
        endingFeaturesDistance = {}

        progress.setInfo(self.tr('Searching places for final nodes...'))
        for pointPE in aggregatedDemandLayer.getFeatures():
            point = pointPE.geometry().asPoint()

            nearestIds = spIndex.nearestNeighbor(point, 1)
            fid = nearestIds[0]

            nearestFeature = QgsFeature()
            pointSpatialIndexLayer.getFeatures(QgsFeatureRequest(fid)).nextFeature(nearestFeature)
            geomPoint = nearestFeature.geometry().asPoint()
            feature = self.prepareEndingNodes(geomPoint, pointPE, groupQuantity, splitterSize, maximumSplit)
            vertexZlacze = self.graph.findVertex(geomPoint)
            endingFeatures[vertexZlacze] = feature
            endingFeaturesDistance[vertexZlacze] = self.euclideanDistance(geomPoint, oltFeature.geometry().asPoint())

        endingFeaturesDistanceSorted = sorted(endingFeaturesDistance.items(), key=lambda value: value[1])

        progress.setInfo(self.tr('Searching paths...'))
        total = 100.0 / len(endingFeaturesDistanceSorted)
        for current, (key, _) in enumerate(endingFeaturesDistanceSorted):
            if current > 0:
                self.graph = self.createGraph(graphLayer, additionalPoints)

            self.makeConnection(graphLayer, key, oltFeatureVertex)
            progress.setPercentage(int(current * total))

        progress.setPercentage(100)

        progress.setInfo(self.tr('Creating routes...'))
        self.amountOfPoints = {}

        features = vector.features(graphLayer)
        total = 100.0 / len(features)
        for current, f in enumerate(features):
            if f.id() in self.routeIds:

                featureLine = QgsFeature()
                featureLine.setFields(self.cablesFields)

                featureLine.setGeometry(f.geometry())
                featureLine.setAttributes(f.attributes())

                self.cableWriter.addFeature(featureLine)

                self.countNetworkPoints(featureLine.geometry().asPolyline())

            progress.setPercentage(int(current * total))

        progress.setInfo(self.tr('Adding branching nodes...'))
        nextNodeId = len(self.nodes) + 1

        for point in self.amountOfPoints.keys():
            if self.amountOfPoints[point] > 2:
                feat = QgsFeature()
                feat.setGeometry(QgsGeometry.fromPoint(point))
                feat.setFields(self.nodesFields)
                feat.setAttribute(cf.NODE_ID_FIELD_NAME, nextNodeId)
                feat.setAttribute(cf.NODE_TYPE_FIELD_NAME, cf.NODE_TYPE_BRANCHING)
                feat.setAttribute(cf.NODE_MAX_SPLIT, maximumSplit)
                if not self.existSplice(feat.geometry(), self.nodes):
                    self.nodeWriter.addFeature(feat)
                    self.nodes.append(feat)
                    nextNodeId = nextNodeId + 1

        del self.nodeWriter
        del self.cableWriter

    def findOLT(self, oltFeature, pointSpatialIndexLayer, spIndex, maximumSplit):

        oltFeatureVertex = self.graph.findVertex(oltFeature.geometry().asPoint())
        if oltFeatureVertex == -1:
            nearestIds = spIndex.nearestNeighbor(oltFeature.geometry().asPoint(), 1)
            nearestFeature = QgsFeature()
            pointSpatialIndexLayer.getFeatures(QgsFeatureRequest(nearestIds[0])).nextFeature(nearestFeature)
            oltFeatureVertex = self.graph.findVertex(nearestFeature.geometry().asPoint())
            oltFeature.setGeometry(nearestFeature.geometry())

        oltSplice = QgsFeature()
        oltSplice.setFields(self.nodesFields)

        oltSplice.setGeometry(oltFeature.geometry())
        oltSplice.setAttribute(cf.NODE_ID_FIELD_NAME, 1)
        oltSplice.setAttribute(cf.NODE_TYPE_FIELD_NAME, cf.NODE_TYPE_OLT)
        oltSplice.setAttribute(cf.NODE_MAX_SPLIT, maximumSplit)

        self.nodeWriter.addFeature(oltSplice)
        self.nodes.append(oltSplice)

        return oltFeatureVertex

    def aggregateDemand(self, demandLayer, aggregatedDemandLayer, splitterSize):

        demandFieldIndex = resolveFieldIndex(demandLayer, cf.DEMAND_FIELD_NAME)
        if demandFieldIndex == -1:
            raise GeoAlgorithmExecutionException(self.tr(u'Missing attribute %s') % cf.DEMAND_FIELD_NAME)
        demandGroupIndex = resolveFieldIndex(demandLayer, cf.DEMAND_GROUP_FIELD_NAME)
        if demandGroupIndex == -1:
            raise GeoAlgorithmExecutionException(self.tr(u'Missing attribute %s') % cf.DEMAND_GROUP_FIELD_NAME)
        demandTypeFieldIndex = resolveFieldIndex(demandLayer, cf.DEMAND_TYPE_FIELD_NAME)
        if demandTypeFieldIndex == -1:
            raise GeoAlgorithmExecutionException(self.tr(u'Missing attribute %s') % cf.DEMAND_TYPE_FIELD_NAME)

        aggreg = {}
        notAggreg = {}

        groupQuantity = {}

        groups = demandLayer.uniqueValues(demandGroupIndex)
        groups = [int(x) for x in groups if type(x) <> QPyNullVariant]

        for group in groups:

            groupQuantity[group] = 0
            aggreg[group] = 0
            notAggreg[group] = 0

            exp = u'{0} = {1}'.format(cf.DEMAND_GROUP_FIELD_NAME, group)
            featuresFromGroup = demandLayer.getFeatures(QgsFeatureRequest().setFilterExpression(exp))
            for featureFromGroup in featuresFromGroup:
                groupQuantity[group] = groupQuantity[group] + 1

                demandType = featureFromGroup.attributes()[demandTypeFieldIndex]
                demandValue = featureFromGroup.attributes()[demandFieldIndex]

                if demandType == cf.AGGREGATED_DEMAND_TYPE or type(demandType) == QPyNullVariant:
                    aggreg[group] = aggreg[group] + int(demandValue)
                elif demandType == cf.BASIC_DEMAND_TYPE:
                    notAggreg[group] = notAggreg[group] + int(demandValue)
                else:
                    raise GeoAlgorithmExecutionException(self.tr(u'Unknown demand type. Supported values: ') + ','.join(cf.DEMAND_TYPES))

        demandIdx = addFieldToLayer(aggregatedDemandLayer, QVariant.Int, cf.DEMAND_FIELD_NAME)
        aggDemandIdx = addFieldToLayer(aggregatedDemandLayer, QVariant.Int, cf.AGG_DEMAND_FIELD_NAME)

        aggregatedDemandLayer.startEditing()
        for potentialNode in aggregatedDemandLayer.getFeatures():
            groupNo = potentialNode.attribute(cf.MEAN_COORDINATE_FIELD_NAME)
            if type(groupNo) == QPyNullVariant or groupNo is None or str(groupNo) == 'NULL':
                aggregatedDemandLayer.deleteFeature(potentialNode.id())
                continue
            groupNo = int(groupNo)
            demandAggr = aggreg[groupNo]
            demandNonAggr = notAggreg[groupNo]
            roundValue = math.ceil(float(demandNonAggr) / splitterSize)
            if demandNonAggr > 0 and roundValue >= 0 and roundValue < 1.0:
                roundValue = 1

            aggregatedDemandLayer.changeAttributeValue(potentialNode.id(), demandIdx, demandAggr + roundValue)
            aggregatedDemandLayer.changeAttributeValue(potentialNode.id(), aggDemandIdx, demandAggr)
        aggregatedDemandLayer.commitChanges()

        return groupQuantity

    def prepareOutput(self, outputNode, outputCable, routeLineLayer):

        crs = QgsCoordinateReferenceSystem()
        crs.createFromUserInput(self.crsAuthid)

        self.nodesFields = QgsFields()
        self.nodesFields.append(QgsField(cf.NODE_ID_FIELD_NAME, QVariant.Int))
        self.nodesFields.append(QgsField(cf.NODE_DEMAND_FIELD_NAME, QVariant.Int))
        self.nodesFields.append(QgsField(cf.NODE_AGG_DEMAND_FIELD_NAME, QVariant.Int))
        self.nodesFields.append(QgsField(cf.NODE_TYPE_FIELD_NAME, QVariant.String))
        self.nodesFields.append(QgsField(cf.NODE_GROUP_FIELD_NAME, QVariant.String))
        self.nodesFields.append(QgsField(cf.NODE_DEM_PNT_COUNT_FIELD_NAME, QVariant.Int))
        self.nodesFields.append(QgsField(cf.NODE_PARENT_FIELD_NAME, QVariant.Int))
        self.nodesFields.append(QgsField(cf.NODE_CURRENT_SPLIT, QVariant.Int))
        self.nodesFields.append(QgsField(cf.NODE_MAX_SPLIT, QVariant.Int))

        self.nodeWriter = outputNode.getVectorWriter(self.nodesFields, QGis.WKBPoint, crs)

        self.cablesFields = routeLineLayer.fields()

        self.cableWriter = outputCable.getVectorWriter(self.cablesFields, QGis.WKBLineString, crs)

    def prepareGraphLayer(self, routeLineLayer):

        defaultCost = getDefaultPathCost()

        graphLayer = QgsVectorLayer("LineString?crs=%s&memoryid={%s}" % (self.crsAuthid, getUUID()), 'graphLayer', "memory")

        graphFields = routeLineLayer.fields()
        graphFields.append(QgsField(cf.GRAPH_COST_FACTOR_FIELD_NAME, QVariant.Double))

        graphLayer.dataProvider().addAttributes(graphFields)
        graphLayer.updateFields()

        graphLayer.startEditing()
        for feature in vector.features(routeLineLayer):

            if self.pathCostField is not None and type(feature.attribute(self.pathCostField)) == QPyNullVariant:
                feature.setAttribute(self.pathCostField, defaultCost)

            graphFeature = QgsFeature()
            graphFeature.setFields(graphFields)
            graphFeature.setAttributes(feature.attributes() + [1.0])
            graphFeature.setGeometry(feature.geometry())

            graphLayer.addFeature(graphFeature)
        graphLayer.commitChanges()

        return graphLayer

    def createSpatialIndex(self, progress, routeLineLayer):

        spatialIndexLayer = QgsVectorLayer("Point?crs=%s&memoryid={%s}" % (self.crsAuthid, getUUID()), 'spatialIndexLayer', "memory")
        spatialIndexLayer.startEditing()

        routeLineLayer.selectByExpression(u'{0} = {1}'.format(cf.ROUTE_LINE_FILTER_FILED, 1), QgsVectorLayer.SetSelection)

        features = routeLineLayer.selectedFeatures()

        points = set()

        total = 50.0 / len(features)
        for current, feature in enumerate(features):
            poly = feature.geometry().asPolyline()

            for point in poly:

                points.add(point)

            progress.setPercentage(int(current * total))

        total = 50.0 / len(points)
        for current, point in enumerate(points):

            fet = QgsFeature()
            fet.setGeometry(QgsGeometry.fromPoint(point))

            spatialIndexLayer.addFeature(fet, False)

            progress.setPercentage(50 + int(current * total))

        spatialIndexLayer.commitChanges()

        return (spatialIndexLayer, QgsSpatialIndex(spatialIndexLayer.getFeatures()))

    def createGraph(self, layer, additionalPoints):
        director = QgsLineVectorLayerDirector(layer, -1, '', '', '', 3)

        idProperter = FeatureIdProperter()
        costProperter = CostFactorProperter(layer, cf.GRAPH_COST_FACTOR_FIELD_NAME, self.pathCostField)
        director.addProperter(idProperter)
        director.addProperter(costProperter)

        crs = layer.crs()
        builder = QgsGraphBuilder(crs)
        director.makeGraph(builder, additionalPoints)
        return builder.graph()

    def existSplice(self, geom, existingNodes):
        for feature in existingNodes:
            featureGeom = feature.geometry()
            if geom is not None and featureGeom.asPoint() == geom.asPoint():
                return True
        return False

    def euclideanDistance(self, point1, point2):
        return math.sqrt((point2.x() - point1.x()) ** 2 + (point2.y() - point1.y()) ** 2)

    def prepareEndingNodes(self, point, fromFeature, groupQuantity, splitterSize, maximumSplit):

        fet = QgsFeature()
        fet.setGeometry(QgsGeometry.fromPoint(point))

        fet.setFields(self.nodesFields)

        groupValue = fromFeature.attribute(cf.MEAN_COORDINATE_FIELD_NAME)

        fet.setAttribute(cf.NODE_ID_FIELD_NAME, int(len(self.nodes) + 1))
        fet.setAttribute(cf.NODE_DEMAND_FIELD_NAME, fromFeature.attribute(cf.DEMAND_FIELD_NAME))
        fet.setAttribute(cf.NODE_AGG_DEMAND_FIELD_NAME, fromFeature.attribute(cf.AGG_DEMAND_FIELD_NAME))
        fet.setAttribute(cf.NODE_TYPE_FIELD_NAME, cf.NODE_TYPE_FINAL)
        fet.setAttribute(cf.NODE_GROUP_FIELD_NAME, groupValue)
        fet.setAttribute(cf.NODE_DEM_PNT_COUNT_FIELD_NAME, groupQuantity[int(groupValue)])
        fet.setAttribute(cf.NODE_CURRENT_SPLIT, splitterSize)
        fet.setAttribute(cf.NODE_MAX_SPLIT, maximumSplit)

        self.nodeWriter.addFeature(fet)
        self.nodes.append(fet)
        return fet

    def makeConnection(self, graphLayer, fromId, toId):

        (tree, _) = QgsGraphAnalyzer.dijkstra(self.graph, fromId, 1)

        if tree[toId] != -1:
            curPos = toId
            graphLayer.startEditing()
            costFactorIndex = graphLayer.fieldNameIndex(cf.GRAPH_COST_FACTOR_FIELD_NAME)
            while (curPos != fromId):

                visitedArc = self.graph.arc(tree[curPos])
                fid = visitedArc.property(0)

                graphLayer.changeAttributeValue(fid, costFactorIndex, self.pathSharing)

                self.routeIds.add(fid)

                curPos = visitedArc.outVertex()
            graphLayer.commitChanges()

    def countNetworkPoints(self, line):

        firstPoint = line[0]
        lastPoint = line[-1]
        if self.amountOfPoints.has_key(firstPoint):
            self.amountOfPoints[firstPoint] = self.amountOfPoints[firstPoint] + 1
        else:
            self.amountOfPoints[firstPoint] = 1
        if self.amountOfPoints.has_key(lastPoint):
            self.amountOfPoints[lastPoint] = self.amountOfPoints[lastPoint] + 1
        else:
            self.amountOfPoints[lastPoint] = 1