| 1 | = Split Polygon With Line String = |
| 2 | |
| 3 | |
| 4 | This example demonstrates how to Split a Polygon into multiple polygons using a Line. |
| 5 | |
| 6 | '''[http://postgis.refractions.net/pipermail/postgis-users/2008-May/019750.html James asks]:''' |
| 7 | |
| 8 | I think the steps below will work but I have one question. I am creating |
| 9 | an application that allows a user to split a polygon by drawing a |
| 10 | linestring across the polygon they wish to change. The crossing |
| 11 | linestring has parts that are outside the polygon and I want to remove |
| 12 | that before I geomunion. What's the easiest way to do that? |
| 13 | |
| 14 | - extract the lines that make up the polygon |
| 15 | - add to this your crossing linestring |
| 16 | - geomunion the lines together. |
| 17 | - polygonize the union-ed set |
| 18 | |
| 19 | Thanks, |
| 20 | |
| 21 | Jim |
| 22 | |
| 23 | --THE BELOW solution may not work with holes --- |
| 24 | |
| 25 | '''[http://postgis.refractions.net/pipermail/postgis-users/2008-May/019902.html Kevin answers]:''' |
| 26 | |
| 27 | Here's an example splitting a polygon with a line. Note that the |
| 28 | dangling cutlines outside the polygon are quietly dropped. |
| 29 | |
| 30 | |
| 31 | {{{ |
| 32 | |
| 33 | SELECT astext(geom ) |
| 34 | FROM dump (( |
| 35 | |
| 36 | SELECT polygonize(geomunion(boundary(poly), line)) AS mpoly |
| 37 | FROM |
| 38 | (SELECT 'POLYGON ((1 1, 1 3, 3 3, 3 1, 1 1 ))'::geometry AS poly) AS a, |
| 39 | (SELECT 'LINESTRING (0 2, 4 2)'::geometry AS line) AS b |
| 40 | |
| 41 | )); |
| 42 | |
| 43 | }}} |
| 44 | |
| 45 | |
| 46 | Result: |
| 47 | |
| 48 | |
| 49 | {{{ |
| 50 | astext |
| 51 | -------------------------------- |
| 52 | POLYGON((1 1,1 2,3 2,3 1,1 1)) |
| 53 | POLYGON((1 2,1 3,3 3,3 2,1 2)) |
| 54 | (2 rows) |
| 55 | |
| 56 | }}} |
| 57 | |
| 58 | |
| 59 | Cheers, |
| 60 | Kevin |
| 61 | |
| 62 | '''[http://postgis.refractions.net/pipermail/postgis-users/2008-May/019903.html Regina asks]:''' |
| 63 | |
| 64 | This doesn't work with holes does it? |
| 65 | |
| 66 | '''[http://postgis.refractions.net/pipermail/postgis-users/2008-May/019904.html Kevin answers]''' |
| 67 | |
| 68 | Things would get a little bit more complicated when holes are involved, |
| 69 | but I don't think overly so. |
| 70 | |
| 71 | The polygonizer builds polygons from all linework - this includes |
| 72 | building polygons for what should be holes. What you would need to do |
| 73 | as a post-process is remove all polygons that don't belong. (In the |
| 74 | following example, I use contains and pointonsurface to determine which |
| 75 | polygons I should exclude from the final result. |
| 76 | |
| 77 | Here is another sample polygon splitting, this time the polygon has two |
| 78 | holes where one is intersected by the splitting line. |
| 79 | |
| 80 | |
| 81 | {{{ |
| 82 | CREATE TABLE poly AS |
| 83 | SELECT 'POLYGON (( 1 1, 1 7, 7 7, 7 1, 1 1 ), |
| 84 | ( 2 3, 4 3, 4 5, 2 5, 2 3 ), |
| 85 | ( 5 5, 6 5, 6 6, 5 6, 5 5 ))'::geometry AS geom; |
| 86 | |
| 87 | CREATE TABLE line AS |
| 88 | SELECT 'LINESTRING (0 4, 8 4)'::geometry AS geom; |
| 89 | |
| 90 | CREATE TABLE split_polys AS |
| 91 | SELECT geom FROM dump (( |
| 92 | SELECT polygonize(geomunion(boundary(poly.geom), line.geom)) |
| 93 | FROM poly, line |
| 94 | )); |
| 95 | |
| 96 | DELETE FROM split_polys a |
| 97 | USING poly b |
| 98 | WHERE NOT contains(b.geom, pointonsurface(a.geom)); |
| 99 | |
| 100 | SELECT astext(geom) FROM split_polys; |
| 101 | |
| 102 | }}} |
| 103 | |
| 104 | Result: |
| 105 | |
| 106 | {{{ |
| 107 | astext |
| 108 | ---------------------------------------------------------------------- |
| 109 | POLYGON((1 1,1 4,2 4,2 3,4 3,4 4,7 4,7 1,1 1)) |
| 110 | POLYGON((1 4,1 7,7 7,7 4,4 4,4 5,2 5,2 4,1 4),(5 5,6 5,6 6,5 6,5 5)) |
| 111 | (2 rows) |
| 112 | |
| 113 | ---------------------------------------------------------------------- |
| 114 | |
| 115 | }}} |
| 116 | |
| 117 | You can also make mosaic from polygons from one table. |
| 118 | When you have for example this table |
| 119 | |
| 120 | |
| 121 | {{{ |
| 122 | CREATE TABLE geoms |
| 123 | ( |
| 124 | id serial NOT NULL, |
| 125 | geom geometry, |
| 126 | CONSTRAINT geoms_pkey PRIMARY KEY (id), |
| 127 | CONSTRAINT enforce_dims_geom CHECK (ndims(geom) = 2), |
| 128 | CONSTRAINT enforce_srid_geom CHECK (srid(geom) = (-1)) |
| 129 | ) |
| 130 | WITH (OIDS=FALSE); |
| 131 | |
| 132 | }}} |
| 133 | |
| 134 | This is the query that returns mosaic: |
| 135 | |
| 136 | |
| 137 | {{{ |
| 138 | SELECT geom FROM (SELECT (ST_Dump(g)).geom as geom FROM ( |
| 139 | SELECT polygonize(g) as g FROM ( |
| 140 | SELECT geomunion(boundary(geom)) as g FROM geoms |
| 141 | ) r |
| 142 | )t) a WHERE EXISTS (SELECT geom FROM geoms b WHERE contains(b.geom, pointonsurface(a.geom))); |
| 143 | |
| 144 | }}} |
| 145 | |
| 146 | Yo!Zik |