Python geojson.loads() Examples

The following are 23 code examples of geojson.loads(). You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may also want to check out all available functions/classes of the module geojson , or try the search function .
Example #1
Source File: reporting.py    From swmmio with MIT License 6 votes vote down vote up
def read_report_dir(rptdir, total_parcel_count=0):
    #rpt dir passed in, just read the preprossed report data
    rpt = FloodReport()
    rpt.total_parcel_count = total_parcel_count
    rpt.model = swmmio.Model(os.path.dirname(rptdir))
    rpt.scenario = rpt.model.scenario
    rpt.parcel_flooding = pd.read_csv(os.path.join(rptdir,
                                                   'parcel_flood_comparison.csv'))
    rpt.parcel_hrs_flooded = rpt.parcel_flooding.HoursFloodedProposed.sum()
    rpt.parcel_vol_flooded = rpt.parcel_flooding.TotalFloodVolProposed.sum()
    costcsv = os.path.join(rptdir, 'cost_estimate.csv')
    conduits_geojson_path = os.path.join(rptdir, 'new_conduits.json')

    if os.path.exists(costcsv):
        #calc the cost estimate total in millions
        cost_df =  pd.read_csv(costcsv)
        rpt.cost_estimate = cost_df.TotalCostEstimate.sum() / math.pow(10, 6)

    if os.path.exists(conduits_geojson_path):
        with open (conduits_geojson_path, 'r') as f:
            rpt.new_conduits_geojson = geojson.loads(f.read())

    return rpt 
Example #2
Source File: dataset.py    From minerva with Apache License 2.0 6 votes vote down vote up
def downloadDataset(self, item, funcAllowed=False):
        minervaMeta = item['meta']['minerva']
        if not minervaMeta.get('postgresGeojson'):
            fileId = None
            # The storing of file id on item is a little bit messy, so multiple place
            # needs to be checked
            if 'original_files' in minervaMeta:
                fileId = minervaMeta['original_files'][0]['_id']
            elif 'geojson_file' in minervaMeta:
                fileId = minervaMeta['geojson_file']['_id']
            else:
                fileId = minervaMeta['geo_render']['file_id']
            file = self.model('file').load(fileId, force=True)
            result = self.model('file').download(file, headers=False)
        else:
            result = self._getPostgresGeojsonData(item)
        if not callable(result) or funcAllowed:
            return result
        return geojson.loads(''.join(list(result()))) 
Example #3
Source File: dataset.py    From minerva with Apache License 2.0 6 votes vote down vote up
def _getPostgresGeojsonData(self, item):
        user = self.getCurrentUser()
        minervaMeta = item['meta']['minerva']
        file = self.model('file').load(minervaMeta['geo_render']['file_id'], user=user)
        assetstore = self.model('assetstore').load(file['assetstoreId'])
        adapter = assetstore_utilities.getAssetstoreAdapter(assetstore)
        func = adapter.downloadFile(
            file, offset=0, headers=False, endByte=None,
            contentDisposition=None, extraParameters=None)

        geometryField = item['meta']['minerva']['postgresGeojson']['geometryField']

        if geometryField['type'] == 'built-in':
            return func
        elif geometryField['type'] == 'link':
            records = json.loads(''.join(list(func())))
            featureCollection, _ = self.linkAndAssembleGeometry(
                geometryField['links'], geometryField['itemId'], records)
            if len(featureCollection.features) == 0:
                raise GirderException('Dataset is empty')
            return featureCollection 
Example #4
Source File: models.py    From tracker_project with MIT License 5 votes vote down vote up
def geojson_feature(self):
        return Feature(
            geometry=loads(self.polygon.geojson),
            id='AreaOfInterest:{pk}'.format(pk=self.pk),
            properties={
                'name': self.name,
                'severity': self.get_severity_display(),
                'centroid': self.polygon.centroid.geojson,
                'model': 'AreaOfInterest',
                'pk': self.pk,
                'url': reverse('tracker:area-of-interest-detail', kwargs={'pk': self.pk}),
            }
        ) 
Example #5
Source File: views.py    From indrz with GNU General Public License v3.0 5 votes vote down vote up
def get_room_centroid_node(space_id):
    '''
    Find the room center point coordinates
    and find the closest route node point
    :param building_id: integer value of building
    :param space_id: internal space id as integer
    :return: Closest route node to submitted room number
    '''

    room_center_q = """SELECT  layer,
            ST_asGeoJSON(st_centroid(geom))
            AS geom FROM geodata.search_index_v
            WHERE id ={0};""".format(space_id)

    cur = connection.cursor()
    cur.execute(room_center_q)

    res = cur.fetchall()

    res2 = res[0]

    space_floor = res2[0]
    space_geom_x = json.loads(res2[1])
    space_geom_y = json.loads(res2[1])

    x_coord = float(space_geom_x['coordinates'][0])
    y_coord = float(space_geom_y['coordinates'][1])

    space_node_id = find_closest_network_node(x_coord, y_coord, space_floor)
    try:
        return space_node_id
    except:
        logger.error("error get room center " + str(space_node_id))
        logger.error(traceback.format_exc())
        return {'error': 'error get room center'} 
Example #6
Source File: validate_geojson.py    From tiler with MIT License 5 votes vote down vote up
def validate_geojson(geojson_path):
    """ Validate a GeoJSON file """

    ## Validate the GeoJSON file
    with open(geojson_path, 'r') as geojson_file:
        geojson_dump = geojson_file.read()
        features = geojson.loads(geojson_dump)
        validation = features.is_valid
        
        print "Is the geojson file valid? ", str(validation)
        # if validation["message"]:
        #     print "Info: ", validation["message"]

        return validation 
Example #7
Source File: test_spatial_geography.py    From FlowKit with Mozilla Public License 2.0 5 votes vote down vote up
def test_valid_geojson(make_spatial_unit_params):
    """
    Check that valid geojson is returned.
    """
    spatial_unit = make_spatial_unit(**make_spatial_unit_params)
    geo = Geography(spatial_unit)
    assert geojson.loads(geo.to_geojson_string()).is_valid 
Example #8
Source File: test_geomixin.py    From FlowKit with Mozilla Public License 2.0 5 votes vote down vote up
def test_valid_geojson(exemplar_spatial_unit_param):
    """
    Check that valid geojson is returned.

    """
    if not exemplar_spatial_unit_param.has_geography:
        pytest.skip("Query with spatial_unit=CellSpatialUnit() has no geometry.")
    dl = daily_location(
        "2016-01-01", "2016-01-02", spatial_unit=exemplar_spatial_unit_param
    ).aggregate()
    assert geojson.loads(dl.to_geojson_string()).is_valid 
Example #9
Source File: test_flows.py    From FlowKit with Mozilla Public License 2.0 5 votes vote down vote up
def test_valid_flows_geojson(exemplar_spatial_unit_param):
    """
    Check that valid geojson is returned for Flows.

    """
    if not exemplar_spatial_unit_param.has_geography:
        pytest.skip("Query with spatial_unit=CellSpatialUnit() has no geometry.")
    dl = daily_location("2016-01-01", spatial_unit=exemplar_spatial_unit_param)
    dl2 = daily_location("2016-01-02", spatial_unit=exemplar_spatial_unit_param)
    fl = Flows(dl, dl2)
    assert geojson.loads(fl.to_geojson_string()).is_valid 
Example #10
Source File: geo_json_processor.py    From urbanfootprint with GNU General Public License v3.0 5 votes vote down vote up
def importer(self, config_entity, db_entity, **kwargs):
        """
            Creates various GeojsonFeature classes by importing geojson and saving it to the database via a dynamic subclass of GeojsonFeature
        :schema: The optional schema to use for the dynamic subclass's meta db_table attribute, which will allow the class's table to be saved in the specified schema. Defaults to public
        :data: Optional python dict data to use instead of loading from the db_entity.url
        :return: a list of lists. Each list is a list of features of distinct subclass of GeoJsonFeature that is created dynamically. To persist these features, you must first create the subclass's table in the database using create_table_for_dynamic_class(). You should also register the table as a DbEntity.
        """
        if self.seed_data:
            data = geojson.loads(jsonify(self.seed_data), object_hook=geojson.GeoJSON.to_instance)
        else:
            fp = open(db_entity.url.replace('file://', ''))
            data = geojson.load(fp, object_hook=geojson.GeoJSON.to_instance)
        feature_class_creator = FeatureClassCreator(config_entity, db_entity)
        # find all unique properties
        feature_class_configuration = feature_class_creator.feature_class_configuration_from_geojson_introspection(data)
        feature_class_creator.update_db_entity(feature_class_configuration)
        feature_class = feature_class_creator.dynamic_model_class(base_only=True)
        # Create our base table. Normally this is done by the import, but we're just importing into memory
        create_tables_for_dynamic_classes(feature_class)
        # Now write each feature to our newly created table
        for feature in map(lambda feature: self.instantiate_sub_class(feature_class, feature), data.features):
            feature.save()
        # Create the rel table too
        rel_feature_class = feature_class_creator.dynamic_model_class()
        create_tables_for_dynamic_classes(rel_feature_class)

        # PostGIS 2 handles this for us now
        # if InformationSchema.objects.table_exists(db_entity.schema, db_entity.table):
        #     # Tell PostGIS about the new geometry column or the table
        #     sync_geometry_columns(db_entity.schema, db_entity.table)

        # Create association classes and tables and populate them with data
        create_and_populate_relations(config_entity, db_entity) 
Example #11
Source File: layer_selection.py    From urbanfootprint with GNU General Public License v3.0 5 votes vote down vote up
def bounds(self):
        """
            Always the same as the geometry field for read-access
        :return:
        """
        return loads(self.geometry.json) 
Example #12
Source File: layer_selection_resource.py    From urbanfootprint with GNU General Public License v3.0 5 votes vote down vote up
def create_layer_from_layer_selection(self, params):
        """
            Used to create a new Layer from the current LayerSelection features
        :param params:
        :return:
        """
        # Resolve the source layer from the layer_selection__id
        source_layer = self.resolve_layer(params)
        config_entity = source_layer.config_entity
        db_entity = source_layer.db_entity_interest.db_enitty
        feature_class = FeatureClassCreator(config_entity, db_entity).dynamic_model_class()
        layer = Layer.objects.get(presentation__config_entity=config_entity, db_entity_key=db_entity.key)
        layer_selection = get_or_create_layer_selection_class_for_layer(layer, config_entity, False).objects.all()[0]
        # TODO no need to do geojson here
        feature_dict = dict(
            type="Feature"
        )
        feature_dicts = map(lambda feature:
                            deep_merge(feature_dict, {"geometry":geojson.loads(feature.wkb_geometry.json)}),
                            layer_selection.selected_features or feature_class.objects.all())
        json = dict({"type": "FeatureCollection", "features": feature_dicts})
        db_entity_configuration = update_or_create_db_entity(config_entity, **dict(
            class_scope=FutureScenario,
            name='Import From Selection Test',
            key='import_selection_test',
            url='file://notusingthis'
        ))
        self.make_geojson_db_entity(config_entity, db_entity_configuration, data=json) 
Example #13
Source File: geometry_util.py    From jacs with Apache License 2.0 5 votes vote down vote up
def parse_geometry(geometry_raw, rewrite_circle=False):


    geometry_statement = None
    # is it WKT?
    try:
        geometry_statement = sqlalchemy.sql.expression.func.GeomFromText(
            geomet.wkt.dumps(geomet.wkt.loads(geometry_raw)))
    except ValueError as err:
        logging.debug('    ... not WKT')
    # is it GeoJSON?
    if not geometry_statement:
        try:
            geometry_statement = sqlalchemy.sql.expression.func.GeomFromText(
                geomet.wkt.dumps(geojson.loads(geometry_raw)))
        except ValueError as err:
            logging.debug('    ... not GeoJSON')
    if not geometry_statement and rewrite_circle and 'CIRCLE' in geometry_raw:
        # now see if it a CIRCLE(long lat, rad_in_m)
        re_res = re.findall(
            r'CIRCLE\s*\(\s*([0-9.-]+)\s+([0-9.-]+)\s*,\s*([0-9.]+)\s*\)',
            geometry_raw)
        if re_res and len(re_res[0]) == 3:
            lng = float(re_res[0][0])
            lat = float(re_res[0][1])
            rad = float(re_res[0][2])
            geometry_statement = sqlalchemy.sql.expression.func.Buffer(
                sqlalchemy.sql.expression.func.POINT(lng, lat),
                rad / 1000 / 111.045)
        else:
            logging.warn('ignoring malformed intersects statement:%s',
                         geometry_raw)
    logging.info('%s becomes %s', geometry_raw, geometry_statement)
    return geometry_statement 
Example #14
Source File: forms.py    From udata with GNU Affero General Public License v3.0 5 votes vote down vote up
def process_formdata(self, valuelist):
        if valuelist:
            value = valuelist[0]
            try:
                if isinstance(value, str):
                    self.data = geojson.loads(value)
                else:
                    self.data = geojson.GeoJSON.to_instance(value)
            except:
                self.data = None
                log.exception('Unable to parse GeoJSON')
                raise ValueError(self.gettext('Not a valid GeoJSON')) 
Example #15
Source File: test_geographic.py    From sentinelsat with GNU General Public License v3.0 5 votes vote down vote up
def test_footprints_s2(products, fixture_path):
    footprints = SentinelAPI.to_geojson(products)
    for footprint in footprints["features"]:
        assert not footprint["geometry"].errors()

    with open(fixture_path("expected_search_footprints_s2.geojson")) as geojson_file:
        expected_footprints = geojson.loads(geojson_file.read())
    # to compare unordered lists (JSON objects) they need to be sorted or changed to sets
    assert set(footprints) == set(expected_footprints) 
Example #16
Source File: test_geographic.py    From sentinelsat with GNU General Public License v3.0 5 votes vote down vote up
def test_footprints_s1(api, test_wkt, read_fixture_file):
    products = api.query(
        test_wkt, (datetime(2014, 10, 10), datetime(2014, 12, 31)), producttype="GRD"
    )

    footprints = api.to_geojson(products)
    for footprint in footprints["features"]:
        assert not footprint["geometry"].errors()

    expected_footprints = geojson.loads(read_fixture_file("expected_search_footprints_s1.geojson"))
    # to compare unordered lists (JSON objects) they need to be sorted or changed to sets
    assert set(footprints) == set(expected_footprints) 
Example #17
Source File: dump1090_to_nearest_flight.py    From flyover with MIT License 5 votes vote down vote up
def within_area(flight, area_geojson_location):
      if not area_geojson_location:
        return True
      try:
        with open(path.expanduser(area_geojson_location), 'r') as geo:
          bounds = geojson.loads(geo.read())["features"][0]["geometry"]
          flight_loc = Point(f.get("lon", 0), f.get("lat", 0))
          return shape(bounds).contains(flight_loc)
      except IOError:
        print("couldn't find geojson file at %s, ignoring" % area_geojson_location, file=stderr)
        return True 
Example #18
Source File: models.py    From tracker_project with MIT License 5 votes vote down vote up
def geojson_feature(self):
        return Feature(
            geometry=loads(self.location.geojson),
            id='Incident:{pk}'.format(pk=self.pk),
            properties={
                'name': self.name,
                'description': self.description,
                'severity': self.get_severity_display(),
                'created': str(self.created),
                'closed': self.closed,
                'model': 'Incident',
                'pk': self.pk,
                'url': reverse('tracker:incident-detail', kwargs={'pk': self.pk}),
            }
        ) 
Example #19
Source File: features.py    From jacs with Apache License 2.0 4 votes vote down vote up
def update(self, table, features):
        """ Updates a feature with corresponding values. Only properties of the feature
        that have a value will be updated. If geometry is given, it is replaced.

        Args:
          table: The Table to use.
          features: String of GeoJSON features.
        Returns:
            On success an empty dictionary is returned.
            On error, a dictionary with error information is returned.
        """
        if not auth.authorize("write", table):
            return error_message('Unauthorized', status=401)

        #attempt to parse geojson
        try:
            features = geojson.loads(features)['features']
        except ValueError as e:
            return error_message("Unable to parse request data. %s" % (e))

        tbl = self.initialize_table(table)
        primary_key = get_primary_key(tbl)
        if primary_key is None:
            return error_message('Primary key is not defined for table')
        index = None
        feature_id = None
        try:
            connection = self._engine.connect()
            transaction = connection.begin()
            for index, feature in enumerate(features):
                query = tbl.update()

                feature_id = get_feature_id(primary_key.name, feature)
                if feature_id is None:
                    return error_message("No primary key", index=index)

                #Make sure all attributes are columns in the table
                try:
                    verify_attributes(tbl.columns, feature['properties'])
                except ValueError as e:
                    return error_message(e, index=index, feature_id=feature_id)

                query = query.where(primary_key == feature_id)
                del(feature['properties'][primary_key.name])

                if 'geometry' in feature and feature['geometry'] is not None:
                    feature['properties'][self._geometry_field] = feature['geometry']
                query = query.values(feature['properties'])
                connection.execute(query)
            transaction.commit()
        except sqlalchemy.exc.SQLAlchemyError as e:
            transaction.rollback()
            return error_message(("Database error: %s" % e), feature_id=feature_id, index=index)
        return [] 
Example #20
Source File: features.py    From jacs with Apache License 2.0 4 votes vote down vote up
def create(self, table, features):
        """ Creates new records in table corresponding to the pass GeoJSON features.

        Args:
          table: The Table to use.
          features: String of GeoJSON features.

        Returns:
            On success an empty dictionary is returned.
            On error, a dictionary with error information is returned.
        """
        if not auth.authorize("write", table):
            return error_message('Unauthorized', status=401)

        #attempt to parse geojson
        try:
            features = geojson.loads(features)['features']
        except ValueError as e:
            return error_message("Unable to parse request data. %s" % (e))

        #loads the table schema from the database
        tbl = self.initialize_table(table)
        data = []
        for index, feature in enumerate(features):
            #Make sure all attributes are columns in the table
            try:
                verify_attributes(tbl.columns, feature['properties'])
            except ValueError as e:
                return error_message(e, index=index)

            properties = feature['properties']
            #Add the geometry field
            properties[self._geometry_field] = geomet.wkt.dumps(feature['geometry'])
            data.append(properties)

        try:
            connection = self._engine.connect()
            transaction = connection.begin()
            connection.execute(tbl.insert(), data)
            transaction.commit()
        except sqlalchemy.exc.SQLAlchemyError as e:
            transaction.rollback()
            return error_message("Database error: %s" % e)
        return [] 
Example #21
Source File: views.py    From indrz with GNU General Public License v3.0 4 votes vote down vote up
def route_to_nearest_poi(request, start_xy, floor, poi_cat_id):

    coords = start_xy.split("=")[1]
    x_start_coord = float(coords.split(',')[0])
    y_start_coord = float(coords.split(',')[1])
    start_floor_num = int(floor.split('=')[1])
    poi_cat_id_v = int(poi_cat_id.split("=")[1])

    startid = find_closest_network_node(x_start_coord, y_start_coord, start_floor_num)

    cur = connection.cursor()

    # bus = pk 27  underground= 26
    qs_nearest_poi = Poi.objects.filter(fk_poi_category=poi_cat_id_v)

    if qs_nearest_poi:
        dest_nodes = []
        pois_found = []

        for i, res in enumerate(qs_nearest_poi):
            network_node_id = find_closest_network_node(res.geom.coords[0][0], res.geom.coords[0][1], res.floor_num )
            if network_node_id:
                pois_found.append({"result_index": i, 'name': res.name, 'floor': res.floor_num, 'id': res.id,
                                 'network_node_id': network_node_id, 'geometry':loads(res.geom.geojson)})

                dest_nodes.append(network_node_id)
            else:
                return Response({"error": "no network node found close to poi"}, status=status.HTTP_400_BAD_REQUEST)



        pgr_query = """SELECT end_vid, sum(cost) as distance_to_poi
            FROM pgr_dijkstra(
                'SELECT id, source, target, cost FROM geodata.networklines_3857',
                {start_node_id}, ARRAY{poi_ids},FALSE
                -- 2, ARRAY[1077, 1255],
                 )
            GROUP BY end_vid
            ORDER BY distance_to_poi asc
            LIMIT 1;""".format(start_node_id=startid, poi_ids=dest_nodes)


        cur.execute(pgr_query)
        res = cur.fetchall()

        node_id_closest_poi = res[0][0]

        closest_poi = None

        for x in pois_found:
            if node_id_closest_poi == x['network_node_id']:
                closest_poi = x


        geojs_fc = run_route(startid, node_id_closest_poi, 1)
        geojs_fc.update({'route_info':[{'destination':closest_poi},{'start': 'work in progress'}]})

        return Response(geojs_fc)
    else:
        return Response({"error":"no Pois with that poi_cat_id found"}, status=status.HTTP_400_BAD_REQUEST) 
Example #22
Source File: reporting.py    From swmmio with MIT License 4 votes vote down vote up
def write(self, rpt_dir):
        #write cost per sewer segment spreadsheet
        self.newconduits.to_csv(os.path.join(rpt_dir,'cost_estimate.csv'))
        self.flood_comparison.to_csv(os.path.join(rpt_dir,'parcel_flood_comparison.csv'))

        #write parcel json files
        parcels = spatial.read_shapefile(sg.config.parcels_shapefile)
        parcels = parcels[['PARCELID', 'ADDRESS', 'OWNER1', 'coords']]
        flooded = self.flood_comparison
        flooded = flooded.loc[flooded.Category.notnull()] #parcels with significant flood delta
        flooded = pd.merge(flooded, parcels, right_on='PARCELID', left_index=True)
        colors = flooded.apply(lambda row:'#%02x%02x%02x' % drawing.parcel_draw_color(row, style='delta'), axis=1)
        flooded = flooded.assign(fill=colors)
        geoparcelpath = os.path.join(rpt_dir,'delta_parcels.json')
        spatial.write_geojson(flooded, filename=geoparcelpath, geomtype='polygon')

        #write new conduit json, shapefiles
        shpdir = os.path.join(os.path.dirname(rpt_dir), 'shapefiles')
        if not os.path.exists(shpdir):os.mkdir(shpdir)
        geocondpath = os.path.join(rpt_dir,'new_conduits.json')
        shpcondpath = os.path.join(shpdir, self.alt_report.model.inp.name + '_new_conduits.shp')
        spatial.write_geojson(self.newconduits, filename=geocondpath)
        spatial.write_shapefile(self.newconduits, filename=shpcondpath)

        #write node and conduit report csvs
        self.alt_report.model.nodes().to_csv(os.path.join(rpt_dir,'nodes.csv'))
        self.alt_report.model.conduits().to_csv(os.path.join(rpt_dir,'conduits.csv'))

        #write a html map
        with open (geocondpath, 'r') as f:
            geo_conduits = geojson.loads(f.read())


        proposed_flooded = self.alt_report.parcel_flooding
        proposed_flooded = pd.merge(proposed_flooded, parcels, right_on='PARCELID', left_index=True)
        geo_parcels = spatial.write_geojson(proposed_flooded)
        # with open (geoparcelpath, 'r') as f:
        #     geo_parcels = geojson.loads(f.read())

        with open(BETTER_BASEMAP_PATH, 'r') as bm:
            filename = os.path.join(os.path.dirname(geocondpath), self.alt_report.model.name + '.html')
            with open(filename, 'wb') as newmap:
                for line in bm:
                    if '//INSERT GEOJSON HERE ~~~~~' in line:
                        newmap.write('conduits = {};\n'.format(geojson.dumps(geo_conduits)))
                        newmap.write('nodes = {};\n'.format(0))
                        newmap.write('parcels = {};\n'.format(geojson.dumps(geo_parcels)))
                    else:
                        newmap.write(line)


        #create figures 
Example #23
Source File: make_wkt.py    From kaggle-satellite-imagery-feature-detection with MIT License 4 votes vote down vote up
def img_to_wkt(img, scale_rate, target_name, W, H, Xmax, Ymin, t_value, cla):

    W_dash = W * W / (W + 1)
    H_dash = H * H / (H + 1)

    if scale_rate < 0.99:
        img_tiny = rescale(img, scale_rate)
    else:
        img_tiny = img

    bmp_image_path = '_temp/' + target_name + '.bmp'
    target_json_path = '_temp/' + target_name + '.json'

    with warnings.catch_warnings():
        warnings.simplefilter("ignore")
        imsave(bmp_image_path, img_tiny)

    os.system('potrace -a 2 -t ' + str(t_value) + ' -b geojson -i ' + bmp_image_path + ' -o ' + target_json_path)

    f = open(target_json_path)
    data = json.load(f)
    f.close()

    os.remove(target_json_path)
    os.remove(bmp_image_path)

    # type of 'data' is feature collection 
    # we only need focus on features
    features = data['features']

    list_polygons = list()

    for i in range(len(features)):

        shapely_polygon = shape(geojson.loads(json.dumps(features[i]['geometry'])))

        if scale_rate < 0.99:
            shapely_polygon = scale(shapely_polygon, 1/scale_rate, 1/scale_rate, origin=(0, 0))

        list_polygons.append(shapely_polygon.buffer(0.0))

    multi = MultiPolygon(list_polygons)

    multi = scale(multi, 1, -1, 1, origin=(float(W)/2, float(H)/2))
    multi = scale(multi, Xmax / W_dash, Ymin / H_dash, origin=(0, 0))

    if cla != 6:
        multi = multi.simplify(1e-6, preserve_topology=True)
    else:
        multi = multi.simplify(1e-5, preserve_topology=True)

    multi = multi.buffer(0)

    if multi.type == 'Polygon':
        multi = MultiPolygon([multi])

    return multi

# tpex's evaluation code can validate topology more strictly
# https://github.com/cxz/tpex