Exemplo n.º 1
0
def read_sf_polyline(sf_filepath):
    sf = shapefile.Reader(sf_filepath)
    attrib_name_list = shp2citygml.get_field_name_list(sf)[1:]
    shapeRecs = sf.shapeRecords()
    shpatt_list = []

    for rec in shapeRecs:
        poly_atts = rec.record
        pypolygon_list2d = shp2citygml.get_geometry(rec)
        if pypolygon_list2d:
            pypolygon_list3d = shp2citygml.pypolygon_list2d_2_3d(
                pypolygon_list2d, 0.0)
            for polyline in pypolygon_list3d:
                shpatt = shapeattributes.ShapeAttributes()
                shpatt.set_shape(polyline)
                att2shpatt(shpatt, attrib_name_list, poly_atts)
                shpatt_list.append(shpatt)

    return shpatt_list
collada_filepath = "F:\\kianwee_work\\smart\\DeliveryHeightDTM\\extracted_info\\punggol_primary\\collada\\punggol_primary_extruded.dae"
#dimensions of boundary
bdimx = 1000
bdimy = 1000
#specify the name of the height attribute
height_attrib = "heightmedi"

#options to keep the geo reference or move the model to the origin
geo_ref = False
#===========================================================================================
#GENERATE THE 1000X1000 BOUNDARY AROUND THE SHPFILE_PT FILE
#===========================================================================================
sf_pt = shapefile.Reader(shpfile_pt)
shapeRecs_pt = sf_pt.shapeRecords()
for rec_pt in shapeRecs_pt:
    pypt_list2d = shp2citygml.get_geometry(rec_pt)

pypt2d = pypt_list2d[0]
pypt3d = (pypt2d[0], pypt2d[1], 0.0)

#create a rectangle boundary
occrec = py3dmodel.construct.make_rectangle(bdimx, bdimy)
#move the rec to pypt3d
m_occrec = py3dmodel.modify.move((0, 0, 0), pypt3d, occrec)
m_occrec = py3dmodel.fetch.topo2topotype(m_occrec)

#===========================================================================================
#GET ALL THE SHAPES WITHIN THIS BOUNDARY
#===========================================================================================
sf = shapefile.Reader(shpfile)
shapeRecs = sf.shapeRecords()
Exemplo n.º 3
0
def convert_apolygon_origlvl(rec, landuse_index, building_index, name_index,
                             plot_ratio_index, count_shapes, citygml,
                             building_list):
    poly_attribs = rec.record
    landuse = poly_attribs[landuse_index]
    landuse.strip()
    building = poly_attribs[building_index]
    building.strip()
    name = poly_attribs[name_index]
    name.strip()
    total_build_up = 0
    constr_buildings = []
    blevel_list = []
    #print "CONDITIONS:", building, landuse
    #=======================================================================================================
    #if the polygon has no building attrib and has no landuse attribute it is a boundary
    #=======================================================================================================
    if building == "" and landuse == "":
        pypolygon_list2d = shp2citygml.get_geometry(rec)
        if pypolygon_list2d:
            pypolygon_list3d = shp2citygml.pypolygon_list2d_2_3d(
                pypolygon_list2d, 0.0)
            occface_list = py3dmodel.construct.make_occfaces_frm_pypolygons(
                pypolygon_list3d)
            occface_list2 = []
            for occface in occface_list:
                pyptlist = py3dmodel.fetch.points_frm_occface(occface)
                is_anticlockwise = py3dmodel.calculate.is_anticlockwise(
                    pyptlist, (0, 0, 1))
                if is_anticlockwise:
                    r_face = py3dmodel.modify.reverse_face(occface)
                    #nrml = py3dmodel.calculate.face_normal(r_face)
                    occface_list2.append(r_face)
                else:
                    occface_list2.append(occface)

            geometry_list = gml3dmodel.write_gml_triangle(occface_list2)

            citygml.add_tin_relief("lod1", "terrain", geometry_list)
    #=======================================================================================================
    #if the polygon has no building attrib and has a landuse attribute it is a landuse
    #=======================================================================================================
    if building == "" and landuse != "":
        #the geometry is stored in parts and points
        pypolygon_list2d = shp2citygml.get_geometry(rec)
        if pypolygon_list2d:
            pypolygon_list3d = shp2citygml.pypolygon_list2d_2_3d(
                pypolygon_list2d, 0.0)
            occface_list = py3dmodel.construct.make_occfaces_frm_pypolygons(
                pypolygon_list3d)
            geometry_list = gml3dmodel.write_gml_srf_member(occface_list)

            if name.isspace():
                name = "plot" + str(count_shapes)

            function = shp2citygml.map_osm2citygml_landuse_function(landuse)
            generic_attrib_dict = {"landuse": landuse}

            plot_ratio = poly_attribs[plot_ratio_index]
            if plot_ratio != None:
                generic_attrib_dict["plot_ratio"] = plot_ratio

            plot_area = shp2citygml.get_plot_area(rec)
            generic_attrib_dict["plot_area"] = plot_area

            citygml.add_landuse("lod1",
                                name,
                                geometry_list,
                                function=function,
                                generic_attrib_dict=generic_attrib_dict)

            #=======================================================================================================
            #find the buildings that belong to this plot
            #=======================================================================================================
            buildings_on_plot_list = shp2citygml.buildings_on_plot(
                rec, building_list)
            in_construction = False
            #check if any of the buildings are under construction
            for cbuilding in buildings_on_plot_list:
                if cbuilding["building"] == "construction":
                    in_construction = True
                    constr_buildings.append(cbuilding)

            if not in_construction:
                #then separate the buildings that are parkings and usable floor area
                parking_list = []
                not_parking_list = list(buildings_on_plot_list)
                for building in buildings_on_plot_list:
                    if "amenity" in building:
                        if building["amenity"] == "parking" or building[
                                "amenity"] == "carpark":
                            parking_list.append(building)
                            not_parking_list.remove(building)

                #then measure the total building footprint on this plot
                build_footprint = 0
                for not_parking in not_parking_list:
                    bgeom_list = not_parking["geometry"]
                    for bgeom in bgeom_list:
                        build_footprint = build_footprint + py3dmodel.calculate.face_area(
                            bgeom)

                #then measure the total parking footprint on this plot
                multi_parking_footprint = 0
                for parking in parking_list:
                    bgeom_list = parking["geometry"]
                    for bgeom in bgeom_list:
                        multi_parking_footprint = multi_parking_footprint + py3dmodel.calculate.face_area(
                            bgeom)

                #base on the footprints calculate how many storeys are the buildings
                if build_footprint != 0:
                    residential_height = 3
                    commercial_height = 4

                    if plot_ratio != None:
                        total_build_up = total_build_up + (plot_area *
                                                           plot_ratio)
                        num_storeys = int(
                            round(total_build_up / build_footprint))

                        if landuse == "residential":
                            height = num_storeys * residential_height

                            if multi_parking_footprint != 0:
                                #base on the parking footprint estimate how high the multistorey carpark should be
                                total_parking_area = shp2citygml.calc_residential_parking_area(
                                    total_build_up)
                                parking_storeys = int(
                                    round(total_parking_area /
                                          multi_parking_footprint))
                                parking_storey_height = 2.5
                                parking_height = parking_storey_height * parking_storeys

                                #write the carparks as buildings
                                for parking in parking_list:
                                    if "building_l" in parking:
                                        blevel_list.append(parking)
                                        parking_storeys = parking["building_l"]
                                        parking_height = parking_storey_height * parking_storeys
                                        shp2citygml.building2citygml(
                                            parking, parking_height, citygml,
                                            landuse, parking_storeys)
                                    else:
                                        shp2citygml.building2citygml(
                                            parking,
                                            parking_height,
                                            citygml,
                                            landuse,
                                            parking_storeys,
                                        )

                        #TODO: calculate for commercial buildings in terms of parking space too
                        else:
                            height = num_storeys * commercial_height

                        for not_parking in not_parking_list:
                            if "building_l" in not_parking:
                                blevel_list.append(not_parking)
                                num_storeys = not_parking["building_l"]
                                if landuse == "residential":
                                    height = residential_height * num_storeys
                                else:
                                    height = commercial_height * num_storeys
                                shp2citygml.building2citygml(
                                    not_parking, height, citygml, landuse,
                                    num_storeys)
                            else:
                                shp2citygml.building2citygml(
                                    not_parking, height, citygml, landuse,
                                    num_storeys)

                    #================================================================================================================
                    #for those plots without plot ratio and might be educational or civic buildings
                    #================================================================================================================
                    else:
                        if landuse == "transport" or landuse == "recreation_ground" or landuse == "civic" or landuse == "place_of_worship" or landuse == "utility" or landuse == "health":
                            num_storeys = 2

                        elif landuse == "education" or landuse == "commercial":
                            num_storeys = 4

                        elif landuse == "residential":
                            num_storeys = 10

                        elif landuse == "reserve":
                            num_storeys = 1

                        else:
                            num_storeys = 1

                        for not_parking in not_parking_list:
                            if "building_l" in not_parking:
                                blevel_list.append(not_parking)
                                num_storeys = not_parking["building_l"]
                                height = commercial_height * num_storeys
                                shp2citygml.building2citygml(
                                    not_parking, height, citygml, landuse,
                                    num_storeys)
                            else:
                                height = num_storeys * commercial_height
                                shp2citygml.building2citygml(
                                    not_parking, height, citygml, landuse,
                                    num_storeys)

    return total_build_up, constr_buildings, blevel_list
Exemplo n.º 4
0
    def convert(self):
        import time
        QtGui.QApplication.processEvents()
        self.progress = 0
        self.update_bar()
        self.params.param('Result View').param('Progress').setValue("")
        #get the shpfile
        height_attrib = str(
            self.params.param('Height Attrib').param(
                'Height Attribute').value())
        bldg_footprint_shp_file = self.params.param('Shape File').param(
            'Shapefile Loaded').value()
        dtm_tif_file = self.params.param('DTM File').param(
            'DTM Loaded').value()
        result_directory = self.params.param('Result Directory').param(
            'Result Directory Chosen').value()
        #viewer = self.params.param('Interactive View').param('Viewer On').value()

        self.timer.timeout.connect(self.update_bar)
        self.timer.start(20)

        #===========================================================================================
        #FUNCTIONS
        #===========================================================================================
        def raster_reader(input_terrain_raster):
            '''
            __author__ = "Paul Neitzel, Kian Wee Chen"
            __copyright__ = "Copyright 2016, Architecture and Building Systems - ETH Zurich"
            __credits__ = ["Paul Neitzel", "Jimeno A. Fonseca"]
            __license__ = "MIT"
            __version__ = "0.1"
            __maintainer__ = "Daren Thomas"
            __email__ = "*****@*****.**"
            __status__ = "Production"
            '''
            # read raster records
            raster_dataset = gdal.Open(input_terrain_raster)
            band = raster_dataset.GetRasterBand(1)
            a = band.ReadAsArray(0, 0, raster_dataset.RasterXSize,
                                 raster_dataset.RasterYSize)
            (y_index, x_index) = np.nonzero(a >= 0)
            (upper_left_x, x_size, x_rotation, upper_left_y, y_rotation,
             y_size) = raster_dataset.GetGeoTransform()
            x_coords = x_index * x_size + upper_left_x + (
                x_size / 2)  # add half the cell size
            y_coords = y_index * y_size + upper_left_y + (
                y_size / 2)  # to centre the point

            return [(x, y, z)
                    for x, y, z in zip(x_coords, y_coords, a[y_index,
                                                             x_index])]

        #===========================================================================================
        #THE RESULT FILES
        #===========================================================================================
        north_facade_collada_filepath = os.path.join(result_directory,
                                                     "north_facade.dae")
        south_facade_collada_filepath = os.path.join(result_directory,
                                                     "south_facade.dae")
        east_facade_collada_filepath = os.path.join(result_directory,
                                                    "east_facade.dae")
        west_facade_collada_filepath = os.path.join(result_directory,
                                                    "west_facade.dae")
        roof_collada_filepath = os.path.join(result_directory, "roof.dae")
        footprint_collada_filepath = os.path.join(result_directory,
                                                  "footprint.dae")
        terrain_collada_filepath = os.path.join(result_directory,
                                                "terrain.dae")

        try:
            #===========================================================================================
            #CONSTRUCT THE TERRAIN
            #===========================================================================================

            time1 = time.clock()
            display_2dlist = []
            #read the tif terrain file and create a tin from it
            pyptlist = raster_reader(dtm_tif_file)
            QtGui.QApplication.processEvents()
            self.params.param('Result View').param('Progress').setValue(
                "Constructing the Terrain ... ...")
            self.progress = 10
            tin_occface_list = py3dmodel.construct.delaunay3d(pyptlist)
            terrain_shell = py3dmodel.construct.sew_faces(tin_occface_list)[0]
            #===========================================================================================
            #EXTRUDE THE BUILDING
            #===========================================================================================

            sf = shapefile.Reader(bldg_footprint_shp_file)
            shapeRecs = sf.shapeRecords()
            attrib_name_list = shp2citygml.get_field_name_list(sf)
            height_index = attrib_name_list.index(height_attrib) - 1

            solid_list = []
            face_list = []

            QtGui.QApplication.processEvents()
            self.params.param('Result View').param('Progress').setValue(
                "Extruding the Buildings ... ...")
            self.progress = 20
            cnt = 0
            for rec in shapeRecs:

                QtGui.QApplication.processEvents()

                poly_attribs = rec.record
                height = poly_attribs[height_index]
                pypolygon_list2d = shp2citygml.get_geometry(rec)
                if pypolygon_list2d:
                    pypolygon_list3d = shp2citygml.pypolygon_list2d_2_3d(
                        pypolygon_list2d, 0.0)
                    occface_list = shp2citygml.shp_pypolygon_list3d_2_occface_list(
                        pypolygon_list3d)
                    for occface in occface_list:
                        if height > 0:
                            occsolid = py3dmodel.construct.extrude(
                                occface, (0, 0, 1), height)
                            solid_list.append(occsolid)
                            face_list.append(occface)
                cnt += 1

            #move all the faces to a very high elevation and project them down onto the terrain so that we know where to place the buildings
            face_cmpd = py3dmodel.construct.make_compound(face_list)
            f_midpt = py3dmodel.calculate.get_centre_bbox(face_cmpd)
            loc_pt = [f_midpt[0], f_midpt[1], 1000]
            t_face_cmpd = py3dmodel.modify.move(f_midpt, loc_pt, face_cmpd)
            face_list2 = py3dmodel.fetch.topo_explorer(t_face_cmpd, "face")
            #face_list2 = face_list2[0:10]

            msolid_list = []

            QtGui.QApplication.processEvents()
            self.params.param('Result View').param('Progress').setValue(
                "Placing the Buildings ... ...")
            self.progress = 50
            fcnt = 0
            for face2 in face_list2:
                pyptlist = py3dmodel.fetch.points_frm_occface(face2)
                #print "NUM PTS:", len(pyptlist)
                z_list = []
                for pypt in pyptlist:

                    QtGui.QApplication.processEvents()

                    interpt, interface = py3dmodel.calculate.intersect_shape_with_ptdir(
                        terrain_shell, pypt, (0, 0, -1))
                    if interpt:
                        z = interpt[2]
                        z_list.append(z)
                if z_list:
                    min_z = min(z_list)
                    #print min_z
                    face = face_list[fcnt]
                    face_midpt = py3dmodel.calculate.face_midpt(face)
                    bldg_loc_pt = [face_midpt[0], face_midpt[1], min_z]
                    bsolid = solid_list[fcnt]
                    m_bsolid = py3dmodel.modify.move(face_midpt, bldg_loc_pt,
                                                     bsolid)
                    msolid_list.append(m_bsolid)
                fcnt += 1

            self.params.param('Result View').param('Progress').setValue(
                "Classfying the Building Surfaces ... ...")
            QtGui.QApplication.processEvents()

            self.progress = 70
            total_facade_list = []
            total_roof_list = []
            total_footprint_list = []
            for solid in msolid_list:

                QtGui.QApplication.processEvents()

                facade_list, roof_list, footprint_list = urbangeom.identify_building_surfaces(
                    solid)
                total_facade_list.extend(facade_list)
                total_roof_list.extend(roof_list)
                total_footprint_list.extend(footprint_list)

            n_list, s_list, e_list, w_list = urbangeom.identify_surface_direction(
                total_facade_list)

            QtGui.QApplication.processEvents()
            self.params.param('Result View').param('Progress').setValue(
                "Writing the Building Surfaces ... ...")
            self.progress = 100
            py3dmodel.export_collada.write_2_collada(
                n_list, north_facade_collada_filepath)
            py3dmodel.export_collada.write_2_collada(
                s_list, south_facade_collada_filepath)
            py3dmodel.export_collada.write_2_collada(
                e_list, east_facade_collada_filepath)
            py3dmodel.export_collada.write_2_collada(
                w_list, west_facade_collada_filepath)
            py3dmodel.export_collada.write_2_collada(total_roof_list,
                                                     roof_collada_filepath)
            py3dmodel.export_collada.write_2_collada(
                total_footprint_list, footprint_collada_filepath)
            py3dmodel.export_collada.write_2_collada([terrain_shell],
                                                     terrain_collada_filepath)

            time2 = time.clock()
            time = (time2 - time1) / 60.0

            time_str = "Total Processing Time: " + str(round(time,
                                                             2)) + " mins"
            QtGui.QApplication.processEvents()
            self.progress = 100
            self.params.param('Result View').param('Progress').setValue(
                time_str)
            #if viewer == True:
            #    cmpd = pyliburo.py3dmodel.construct.make_compound(msolid_list)
            #    display_2dlist.append([cmpd])
            #    display_2dlist.append([terrain_shell])
            #    pyliburo.py3dmodel.construct.visualise(display_2dlist, ["RED", "WHITE"])

            self.timer.stop()
        except:
            if self.progress == 10:
                self.params.param('Result View').param('Progress').setValue(
                    str("there is an error at terrain construction !!!"))
            if self.progress == 20:
                self.params.param('Result View').param('Progress').setValue(
                    str("there is an error at building extrusion !!!"))
            if self.progress == 50:
                self.params.param('Result View').param('Progress').setValue(
                    str("there is an error at building placement !!!"))
            if self.progress == 70:
                self.params.param('Result View').param('Progress').setValue(
                    str("there is an error at building classification !!!"))
            self.timer.stop()