ST_EliminateHoleByBuffer#
Table of Contents
Part 0: Setup BDT#
[ ]:
import bdt
bdt.auth("bdt.lic")
from bdt.processors import *
from bdt.functions import *
from pyspark.sql.functions import *
from pyspark.sql.types import StructType, StructField, StringType, IntegerType
BDT has been successfully authorized!
Welcome to
___ _ ___ __ ______ __ __ _ __
/ _ ) (_) ___ _ / _ \ ___ _ / /_ ___ _ /_ __/ ___ ___ / / / /__ (_) / /_
/ _ | / / / _ `/ / // // _ `// __// _ `/ / / / _ \/ _ \ / / / '_/ / / / __/
/____/ /_/ \_, / /____/ \_,_/ \__/ \_,_/ /_/ \___/\___//_/ /_/\_\ /_/ \__/
/___/
BDT python version: v3.3.0-v3.3.0
BDT jar version: v3.3.0-v3.3.0
Part 1: Generate Sample Data#
The below code creates one square polygon with a square hole inside.
The diminsions of the polygon are 5x5, with a total area of 25 units.
The diminsions of its hole are 3x3, with a total area of 9.
The area of the hole is 36% of the total area of the polygon.
[ ]:
poly_wkt = "POLYGON((0 0, 5 0, 5 5, 0 5, 0 0), (1 1, 4 1, 4 4, 1 4, 1 1))"
poly_df = spark.createDataFrame([
(poly_wkt,)
], schema="wkt string").select(st_fromText("wkt").alias("SHAPE"))
(
poly_df
.select(st_asText("SHAPE").alias("wkt"))
.show(truncate=False)
)
+---------------------------------------------------------------------+
|wkt |
+---------------------------------------------------------------------+
|MULTIPOLYGON (((0 0, 5 0, 5 5, 0 5, 0 0), (1 1, 1 4, 4 4, 4 1, 1 1)))|
+---------------------------------------------------------------------+
The above code produces the following geometry:
Part 2: ST_EliminateHoleByBuffer#
Part 2.1: Function Call#
ST_EliminateHoleByBuffer takes the following arguments:
The polygon SHAPE.
The distance to buffer (and un-buffer) the input polygon.
The percentage threshold. A hole with an area less than this percentage of the total area of the polygon will be eliminated.
The maximum number of vertices in a circle (or curve). The recommended default value is 96. Increase this value for polygon detail over performance and decrease for peformance over detail.
The output is converted to well-known text format to make the internal BDT shape readable.
The below code sets the buffer distance to 1.0 units, and the percentage threshold to 8.0%
[ ]:
result_df = poly_df.select(
st_asText(
st_eliminate_hole_by_buffer(
"SHAPE", 1.0, 8.0, 96)
.alias("SHAPE")
).alias("WKT")
)
result_df.show(truncate=False)
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|WKT |
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|MULTIPOLYGON (((4.9836360778646815 3.560011134901632e-22, 4.999481281734015 5.187182659846673e-4, 5 0.01636392213531342, 5 4.983636077864691, 4.999481281734016 4.999481281734015, 4.983636077864686 5, 0.016363922135308462 5, 5.187182659843588e-4 4.999481281734016, 0 4.983636077864687, 0 0.016363922135318894, 5.187182659846685e-4 5.187182659843526e-4, 0.016363922135313347 1.0842021724855044e-19, 4.9836360778646815 3.560011134901632e-22)))|
+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
The internal hole is removed because even though it is 36% of the polygon area before buffering, it is only about 2% of the polygon area after buffering. 2% is less than the threshold of 8%, so it is removed.
The below steps will show in detail why this happens.
Part 2.2: Internal Steps Explained#
Step 1: Buffer and Simplify the polygon. The dimensions of the outer ring increase, and the dimensions of the inner ring (hole) decrease. The hole becomes only about 2% of the total area of the polygon.
Step 2: Remove Holes in the polygon. A buffered hole with an area that is less than the percentageThreshold of the total area of the buffered polygon will be eliminated. 2% is less than 8%, so the hole is removed.
Step 3: Simplify and Negative Buffer the polygon. Negative buffer the above result to effectively shrink the polygon back to its original size.
Note: The input polygon for this example was already simple, so simplification did not do anything in this case. However, if the polygon is complex with a lot of verticies, it will be simplified too.