Skip to content

Latest commit

 

History

History
149 lines (128 loc) · 16.2 KB

note.org

File metadata and controls

149 lines (128 loc) · 16.2 KB

Detailed Spec

  • Note taken on [2016-10-09 Du 19:06]
    This spec should be updated with the part that describes when the polygon should be split with just one line, and when it should be split with two lines.

    There’s also some details that are pending related to rotation of the polygon in order to reduce the number of cases to be analyzed.

We have a polygon P (also known as big parcel) and the nearest road R. We get the bounding box B for P and all our searches for cutting points/lines will be confined to B. We get the points that are on the boundary and on the bounding box at the same time, we call these “extreme points” and denote them with E, and we label them with their cardinal direction.

Goal: We want to cut a corner C (also called subdivision) from P that contains the nearest-to-road point. The cut will be done using two lines, one horizontal (the green-line) and one vertical (the red-line). We want C to be of a given area A.

Now get the closest two points on E to R, and depending on them, we decide which corner to cut.

We’ll use sweeping-lines for this. Any sweeping-lines mentioned will be moving away from the corner (in other words, away from the closest road point).

In what follows, we assume the north-west corner needs to be cut.

We place an inset (a horizontal line) that will be located sqrt(A) to the south (relative to the north edge). The inset is positioned there because we anticipate the target area to have a rectangular shape.

If the area above the inset (the one we aim for) is larger than our target, we split the polygon, take the upper half and use another sweeping (the red-line) line that goes from west to east, to find another cutting line that allows us to get to target area.

If the area above the inset is insufficient (below the target area), we search for a better position for it, using binary search, along the north-south direction.

Additional details: The way the cut search works, using the inset, is such that we avoid getting thin horizontal strips when our initial polygon is a square/rectangle (and it is expected to be a square in the vast majority of cases).

Details about corner cases (other than NW which was covered above):

  • NE corner: green-line goes north->south and red-line goes east->west
  • SE corner: green-line goes south->north and red-line goes east->west
  • SW corner: green-line goes south->north and red-line goes west->east

So the green and red-lines always move away from the corner.

Query to get test parcels

SELECT
name, way
FROM planet_osm_polygon
WHERE tags->'leisure'='park'
AND name LIKE '%Herăstrău%'
ORDER BY ST_Area(way) DESC
LIMIT 1;
Parcul Herăstrău010300002031BF0D0001000000A4000000713D0AF7CC254641F6285CCF30225541AE47E1BACE254641B81E852B3D2255411F85EB71D4254641666666464522554152B81EE5DB254641AE47E1BA462255410AD7A370F2254641713D0A174A22554185EB51F8192646413D0AD7434F225541E17A148E1F2646417B14AE474D2255411F85EBF12C264641F6285C4F4E225541295C8F2237264641333333134F2255410AD7A3104F264641E17A148E532255413333335367264641F6285C5F582255415C8FC2D582264641EC51B86E5F22554152B81E259E2646415C8FC2E567225541D7A370BDAA264641E17A147E6C225541B81E85CBBB26464148E17A7475225541713D0A57CC264641CDCCCC1C802255413D0AD723E4264641F6285CCF8D225541D7A370DDE42646413D0AD7D3902255417B14AEE7E826464185EB5158942255410AD7A3B0EB2646418FC2F56898225541000000E0F3264641AE47E14A98225541C3F528BCF52646413D0AD713992255418FC2F5E8F3264641295C8F229B225541A4703D6AF3264641C3F5281C9D2255411F85EB1100274641000000F0A7225541000000E005274641CDCCCCECA822554185EB515806274641D7A3702DAC225541D7A370BD0B27464114AE4711B0225541B81E852B132746415C8FC2C5B6225541C3F5287C1C274641713D0AA7BA225541F6285C4F23274641295C8F82BD2255419A999979272746410AD7A3B0C1225541E17A142E2E274641C3F5281CC92255419A999959402746417B14AE27DE2255417B14AEA7432746415C8FC2C5E5225541F6285C0F4827464100000080E8225541E17A14EE4B2746411F85EB71F3225541666666464E274641B81E852BF4225541D7A370DD4D274641F6285C0FF82255410AD7A3F04C274641F6285CCFFF225541000000604C27464185EB51B80B235541333333734D2746416666669614235541295C8FC246274641713D0A771823554152B81E4542274641295C8FE21F235541EC51B8BE3B2746418FC2F5682323554152B81E2541274641EC51B8CE27235541E17A142E3F2746417B14AE272F235541AE47E15A39274641F6285C5F33235541CDCCCCEC2427464152B81E853923554114AE47A11E27464148E17A243C2355417B14AE4718274641AE47E17A3E235541E17A14CE0F274641CDCCCC5C41235541000000600D274641CDCCCC7C44235541C3F528DC04274641F6285C3F48235541D7A3703D02274641D7A3707D4823554185EB5158FD2646413D0AD7F34923554148E17A74F7264641AE47E14A52235541A4703DAAF5264641EC51B81E55235541E17A146EF3264641666666D65923554185EB5158F4264641EC51B89E5E235541E17A146EF2264641AE47E1DA662355418FC2F588EB2646417B14AEE76E2355419A999959E2264641713D0A377E23554100000080D82646417B14AE4788235541295C8F42D02646417B14AEB78F235541A4703D8AC4264641D7A370AD97235541A4703D8AB72646419A9999899F235541333333B3A3264641CDCCCC8CA5235541EC51B8DE9126464152B81E35A9235541333333337E264641333333C3AB235541A4703DCA6726464166666676AE2355419A999979512646417B14AEB7B0235541AE47E1DA392646417B14AE57B1235541E17A14EE30264641000000A0AF235541D7A370DD292646410AD7A3C0AD235541C3F5289C27264641A4703D2AB0235541295C8F02382646410AD7A3F0B6235541A4703DEA552646415C8FC2D5B52355418FC2F56871264641333333D3B2235541D7A3703D8E264641F6285C0FAF2355410AD7A350A6264641AE47E14AAA235541295C8FA2C22646418FC2F558A32355415C8FC275D9264641F6285CFF9C2355415C8FC255EC264641CDCCCCFC97235541EC51B81EFB26464148E17A3494235541C3F5287C3F2746415C8FC2157F2355410AD7A3B04D27464148E17A54792355419A9999395A274641B81E85AB72235541E17A142E7B274641295C8F925C235541C3F5287C8E27464148E17AC455235541C3F5281C95274641666666C64823554185EB51F896274641295C8FF23B235541F6285C2F9F27464166666626DE2255418FC2F548A1274641000000B0C32255415C8FC2F5A22746417B14AE27AB22554185EB51B8A4274641713D0AF7922255410AD7A3D0A5274641295C8F62822255417B14AEE7A82746417B14AED764225541A4703DEAAE274641333333034E22554100000040B627464185EB51883E2255415C8FC215C0274641713D0A9730225541AE47E13ACB274641666666D6222255418FC2F508DC27464166666646152255410AD7A3F0FD274641666666E6F82155419A9999D91F2846418FC2F548DD215541295C8F222728464185EB5198D521554148E17A344828464100000020B72155411F85EB71562846419A999999AB215541AE47E15A6C2846410AD7A3809C21554166666686B3284641666666C67621554114AE4781B728464152B81E156E215541D7A3701DB728464114AE475165215541AE47E1BAB4284641E17A14EE5D215541C3F5285CAD2846415C8FC295572155411F85EBF1BB2846415C8FC2154D215541EC51B87EB1284641CDCCCCFC462155410AD7A3308B28464152B81EA53B215541C3F5287C612846413D0AD7C32F2155413D0AD7C352284641295C8FD23E2155411F85EBF15628464114AE473143215541D7A370FD4F284641C3F528FC4F215541EC51B8FE402846411F85EB717721554114AE47413A284641000000C08921554185EB51582F28464152B81EB59821554185EB51D817284641EC51B84EAB215541AE47E1FA0C2846413D0AD793B0215541B81E85EBFE2746410AD7A3F0B42155413D0AD7A3DE27464166666686BE215541F6285C4FB4274641AE47E1AAC6215541B81E85AB9D274641A4703DFACA215541EC51B89E762746417B14AE87CF2155418FC2F508542746410AD7A360D4215541D7A3709D1C274641C3F528ACCF21554114AE47A10B27464114AE4731CD215541C3F528FCFA264641F6285C4FC82155410AD7A310EA2646410AD7A3A0C2215541C3F5283CC6264641A4703D7AB9215541B81E858BB7264641A4703D8AB8215541AE47E1DAA9264641E17A14AEBB215541000000409F264641713D0A47BE215541C3F5289C942646417B14AE17C02155410AD7A3107D2646417B14AE87C1215541EC51B8BE69264641B81E859BC021554185EB5138592646413D0AD703BF215541F6285CCF41264641E17A145EBC215541F6285CAF29264641295C8F02B9215541AE47E15A18264641295C8F62B6215541D7A3703D0C2646413D0AD723B8215541C3F528FCFF2546419A9999B9BC215541F6285CCFF625464148E17A84C221554152B81EA5F42546417B14AE27CA21554100000040F625464133333313D12155417B14AE67FE2546411F85EB11DC215541C3F528BC042646415C8FC245E4215541B81E856B06264641713D0A07EA21554185EB511807264641A4703D9AF4215541295C8F4201264641A4703D2A0622554152B81E25FB25464185EB51B80E225541666666E6F525464152B81E8519225541295C8F62EC2546418FC2F5B821225541666666E6E3254641D7A3701D2622554185EB5198D8254641295C8F52272255413D0AD743CE254641C3F528AC29225541713D0AF7CC254641F6285CCF30225541

Get roads near parcels (using KNN)

WITH
parcels AS (
    SELECT
    osm_id, name, way
    FROM planet_osm_polygon
    WHERE
    tags->'leisure'='park'
    AND name LIKE '%Herăstrău%'
    LIMIT 3
), roads AS (
    SELECT
    osm_id, name, way
    FROM planet_osm_line
    WHERE tags->highway = 'motorway'
)
-- do KNN cross-join between parcels and roads
-- to get nearby roads (rn)
SELECT
DISTINCT ON (rn.osm_id)
rn.osm_id, rn.name, p.osm_id, p.name, dr
FROM parcels p
CROSS JOIN LATERAL (
    SELECT
    *,
    -- distance to road
    ST_Distance(p.way,r.way) as dr
    FROM roads r
    ORDER BY p.way <-> r.way
    LIMIT 5
) rn;
osm_idnameosm_idnamedr
256097200Autostrada A3 București - Brașov88337012Parcul Herăstrău3886.49711984996
284325578Autostrada A3 București - Brașov91797290Parcul Herăstrău5643.86537188825
284325581Autostrada A3 București - Brașov88337012Parcul Herăstrău4716.35617574639
284325583Autostrada A3 București - Brașov91797290Parcul Herăstrău4810.48244180351
284325584Autostrada A3 București - Brașov88337012Parcul Herăstrău4886.17496682222

Implementation

Visualization

  • [X] Need to use ST_GeometryType to draw parcels and roads differently
  • [X] Refactoring
  • [ ] Round off coordinates to save space on the SVG.

Core algorithm

  • [X] Need to sort clock-wise to determine cardinal directions for boundary extremes and label them. This is needed so we know which corner to cut.
  • [X] Need to look again at specs and write down with examples, when the red-line cut will be used.
  • [X] Get green-line sweep trajectory
  • [X] Find green-line
  • [X] Use inset-based green-line and red-line search as described in the spec
  • [X] Update the cut polygon and insert the corner in the DB

Other

CREATE VIEW roads_by_type AS SELECT *, tags->’highway’ AS road_type FROM planet_osm_line WHERE tags ? ‘highway’;

Progress

  • Note taken on [2016-10-10 Lu 18:26]
    Refined spec and simplified some parts of the code.
  • Note taken on [2016-10-10 Lu 14:32]
    Need to detail how the red-line cut works and when it’s being used.
  • Note taken on [2016-10-09 Du 17:52]
    I noticed that the first cut would solve the problem, meaning it’s able to find the required line.

    After discussing with John, we agreed that a 2nd cut is actually required but only under certain conditions.