Více

Připojte se pouze v případě, že jeden řádek protíná vyrovnávací paměť. Ne, pokud dva

Připojte se pouze v případě, že jeden řádek protíná vyrovnávací paměť. Ne, pokud dva


Mám silniční síť (funkce linky) a výlet GPS bodů. Chci spojit atributy ze silniční sítě do každého bodu. Takže pro každý bod vytvořím vyrovnávací paměť. Pokud se vyrovnávací paměť protíná s čárovou funkcí, jsou atribuce zapsány do bodu. To není problém. Nechci však zapisovat atributy bodům, pokud se vyrovnávací paměť protíná s nebo více řádky. Nějaké nápady, jak to udělat? Pracuji v ArcGIS. Existuje způsob, jak to udělat bez použití pythonu?


Toho lze dosáhnout v několika krocích.

  1. Spusťte prostorové spojení pro polygony vyrovnávací paměti a vrstvy silniční sítě (pravým tlačítkem klikněte na vrstvu polygonů vyrovnávací paměti v TOC a zvolte Připojit a vztahy> Připojit).

Získáte třídu výstupních polygonových prvků, která obsahuje informace o tom, kolik silničních prvků se nacházelo (i částečně) v polygonech s vyrovnávací pamětí.

  1. Spusťte spojení mezi třídou výstupních funkcí získanou v kroku 1 a vrstvou polygonů se zdrojovou vyrovnávací pamětí, abyste zjistili, které funkce nechcete analyzovat (když spustíte Průsečík a kopírování atributů).

  2. Když vyberete ty funkce, které mají buď hodnotu null, nebo 1 (které jsou ve vašem případě platné) v poli Počet, nastavte buď definiční dotaz, nebo proveďte výběr> exportovat data do nové třídy funkcí.

Pokud používáte ModelBuilder k automatizaci pracovního postupu, použijte prosím nástroj Add Join GP a Spatial Join GP.


Rozdělení samoprotínajícího se polygonu vrátilo v Shapely pouze jeden polygon

Používám Python 3.5 64 bit ve Windows 7 64 bit, urostlá verze 1.5.13.

Mám následující kód, který mi vrátil samo-protínající se polygon:

Toto je správně. Pak jsem se pokusil získat dva jednotlivé polygony pomocí bufferu (0):

Bohužel se vrátil pouze ze dvou polygonů:

Mohl by někdo prosím pomoci? Dík!


Nechejte koncové body segmentu čáry $ vec

_1 = (x_1, y_1) $ a $ vec

_2 = (x_2, y_2) $ a čára prochází body $ vec

_3 = (x_3, y_3) $ a $ vec

_4 = (x_4, y_4) $. Potom právě tehdy, když $ Bigl (( vec

_4 - vec

_3) times ( vec

_1 - vec

_3) Bigr) Bigl (( vec

_4 - vec

_3) times ( vec

_2 - vec

_3) Bigr) le 0 $ segment čáry protíná čáru. Ve tvaru kartézské souřadnice $ Bigl ((x_4 - x_3) (y_1 - y_3) - (x_1 - x_3) (y_4 - y_3) Bigr) Bigl ((x_4 - x_3) (y_2 - y_3) - (x_2 - x_3) (y_4 - y_3) Bigr) le 0 $ Znak prvního multiplikátu závisí na tom, na které straně $ vec

_1 $ je k přímce a znaménko druhého multiplikandu závisí na tom, na které straně $ vec

_2 $ je na řadě. Pokud je produkt nula, $ vec

_1 $ a/nebo $ vec

Na řadě je _2 $. Pokud je součin záporný, pak musí být dva body na různých stranách čáry.

Pokud jsou dva body na různých stranách (nekonečně dlouhé) čáry, pak úsečka musí čáru protnout. Pokud jsou dva body na stejné straně, úsečka nemůže čáru protnout.


2 odpovědi 2

Pro jednoduchost použijme $ begin (p_x, p_y, p_z) = vec

_0 (d_x, d_y, d_z) = vec (a_x, a_y, a_z) = vec (b_x, b_y, b_z) = vec konec$

Pokud jsou všechny tři jmenovatele nula, čára a úsečka se neprotnou. (K tomu může také dojít, pokud $ vec

_0 = vec$ nebo $ vec = vec$ nebo obojí.)

Všimněte si, že odpovídající vzorce pro $ s $ mají stejné jmenovatele, tj. $ Eqref <1> $ a $ eqref <4> $ mají stejné jmenovatele, $ eqref <2> $ a $ eqref <5> $ mají stejné jmenovatele a $ eqref <3> $ a $ eqref <6> $ mají stejné jmenovatele. (To znamená, že pokud existuje řešení pro $ t $, existuje řešení také pro $ s $. V případě OP nezáleží na $ s $, protože je to parametr pro nekonečnou čáru a jakýkoli skutečný $ s $ je přijatelný .)


4 odpovědi 4

V případě 2D si myslím, že se problém trochu zjednodušuje.

Čára rozdělí prostor na dvě oblasti.

Pokud je mnohoúhelník přítomen pouze v jedné z těchto oblastí, pak jej čára neprotíná.

Pokud je mnohoúhelník přítomen v obou oblastech, pak jej čára protíná.

Vezměte jakoukoli kolmici na přímku, přičemž průnik s čarou bude původem.

Promítněte každý vrchol mnohostěnu na kolmici.

Pokud se tyto projekce vyskytují s oběma znaménky, pak polygon protíná čáru.

[Aktualizace po komentáři elexhobby.]

Zapomněli jsme zahrnout zpracování neomezeného případu.

Chtěl jsem dodat, že by bylo možné vytvořit „virtuální vrchol“, který by představoval otevřenou oblast. To, co opravdu potřebujeme, je „směr“ otevřené oblasti. Můžeme to vzít jako průměr vektorů pro ohraničující hrany otevřené oblasti.

Poté zacházíme s bodovým součinem tohoto směru s normálkou a přidáme to do množiny projekcí vrcholů.

V geometrii, obvykle viz wikipedie, je mnohoúhelník ohraničený. To, co popisujete, se obvykle nazývá polytop nebo mnohostěn viz wikipedie

K dispozici je několik knihoven geometrie, dvě, které mě napadnou, jsou boost (polygon) a CGAL. Obecně existuje zřetelné rozdělení mezi výpočetními metodami, které se zabývají 2d, 3d a N -d - ze zřejmých důvodů.

Pro váš problém bych použil poněkud přístupový strom s rozdělením binárních prostorů. Vzal bych první řádek vašeho „poly“ a ořízl dotazový řádek proti němu a vytvořil paprsek. Paprsek by začínal v průsečíku obou linií a pokračoval ve směru vnitřku půlprostoru generovaného první linií „poly“. Nyní bych postup zopakoval s paprskem a druhým řádkem „poly“. (to by mohlo generovat segment místo paprsku) Pokud v určitém bodě původ paprsku (nebo nyní segmentu) leží na vnější straně aktuálně uvažované poly čáry a neprotíná ji, pak odpověď zní ne - čára se neprotíná váš „poly“. Jinak se to protíná. Zvláštní pozornost věnujte různým pouzdrům s rovnoběžnými hranami. Docela přímočarý a funguje pro vícerozměrné případy.


2 odpovědi 2

Jedná se o nákladnou metodu, která začala způsobovat problémy s výkonem. Jaký by byl doporučený algoritmus pro tento problém? Existuje příklad kódu?

Velmi záleží na tom, jak reprezentujete samotnou linku. Zdá se, že používáte přerušovanou čáru, to je srovnání přímek.

První myšlenka, která mě napadne, je provést jednoduchou kontrolu regionu. Každý řádek můžete sbalit do malého obdélníku (jeho ohraničujícího rámečku) a je velmi snadné zkontrolovat, zda se dvě ohraničující rámečky překrývají nebo ne - můžete to provést několika odečty, což je mnohem levnější než výpočet determinantu! Pokud kontrola regionu selže, pak se řádky určitě neprotínají, takže není nutné počítat determinant.

S tím byste měli přeskočit ze složitosti (nˆ4) na (nˆ2), kde n je počet malých přímek ve vaší přímce.

Pokud to nestačí, druhou běžnou technikou je rozdělit plátno na regiony a reprezentovat tuto oblast jako binární strom. Začnete plným plátnem, poté rozříznete na poloviny a každou polovinu rozdělíte na dvě části znovu a znovu, dokud nedosáhnete počtu rozdělení, které si předem zvolíte. (Můžete provést empirické testy, abyste určili hodnotu vhodnou pro vaše data.) Poté můžete každý segment čáry připojit k oblasti, kam se vejde jeho ohraničující rámeček - Obvykle list, ale může to být uzel vyšší úrovně, pokud segment čáry ořízne hranice regionu. Jakmile zabalíte každý segment čáry do stromu oblastí, lze jej snadno načíst sousedů úsečky, kde může dojít k průsečíku.

Toto je původně komentář hledající vysvětlení, ale je příliš dlouhý na to, aby se vešel. Zveřejnil jsem tedy každou otázku zde spolu s mými odpověďmi typu „co kdyby“ na základě možných odpovědí.

Před hledáním vysvětlení by každý měl vidět, že současná implementace má časovou složitost, která je kvadratická v počtu trasových bodů. Zápis je O (N^2).

Zjednodušeně řečeno, pokud se počet trasových bodů zdvojnásobí (zvýší na dvojnásobek), doba provádění bude přibližně čtyřnásobná (zvýšena na čtyřnásobek).

(1) Jaký je typický počet trasových bodů, které musíte zvládnout? Pokud neexistuje žádné typické číslo, uveďte maximální možný počet trasových bodů, které váš kód potřebuje podporovat.

Pokud například zjistíte, že problém s výkonem nenastane, když je N (počet trasových bodů) nižší než několik stovek, můžete uložit softwarové omezení, že pohyb myši nemůže být delší než tento počet pixelů. Zda je to přijatelné nebo ne, závisí na účelu vašeho softwaru.

(2) Je dovoleno používat techniky zjednodušení čar ke snížení počtu trasových bodů před kontrolou křižovatek?

Technika zjednodušení čáry může snížit počet trasových bodů desetkrát (jednu desetinu) nebo více (méně), když je jako vstup použit pohyb myši. Uživatel bude muset velmi zběsile hýbat myší, aby tato redukce selhala.

(3) Víte, jak implementovat a používat QuadTree sami?

Quadtree umožňuje dotaz na průměrný případ O (log N) do kolekce (stromu) ohraničujících rámečků, které se překrývají s ohraničujícím rámečkem dotazu. Chcete -li najít všechna párově překrývající se ohraničující pole, nejprve do něj přidejte všechna ohraničující pole a poté proveďte dotaz na každé ohraničující rámeček. To dává celkový průměrný případ O (N log N), což je lepší než původní implementace, která je O (N^2).

(4) Jakou šířku a výšku pohybové oblasti, měřenou v pixelech, musíte podporovat?

Pokud je celková pohybová plocha (ve čtvercových pixelech, tj. Součin šířky a výšky) menší než několik milionů, a pokud je povoleno přidělit pole, které pojme několik milionů bajtů (nebo bitů - potřebujeme pouze každý Pokud má být prvek pravdivý nebo nepravdivý), pak lze takové pole přidělit tak, aby fungovalo jako bitmapa (doslova mapa bitů).

Bitmapa bude inicializována pomocí false. Poté, co uživatel „maluje“ pohybem myši, budou odpovídající pixely v bitmapě nastaveny na hodnotu true.

Upozornění. Všimněte si, že pokud je uživatelská stopa pixelu široká pouze jeden pixel (1 na 1), dojde k následujícímu okrajovému případu:

Předpokládejme, že stopa jde od (10, 10) do (11, 11). Později ve stopě překročí tento segment přechodem (10, 11) na (11, 10). Protože se pixely samy nepřekrývají, toto schéma založené na bitmapách nedokáže detekovat průnik tohoto druhu.

Řešením námitky je, že je třeba zkontrolovat sousedství 3 na 3 na pixely, které byly dříve namalovány. Přitom je také třeba pamatovat na ignorování čerstvě namalovaných pixelů. Je možné, že jeden bude muset použít jeden bajt na pixel (na rozdíl od jednoho bitu na pixel), aby mohl ukládat další informace, které pomohou při řešení tohoto upozornění.


Bohužel byla zvolena špatná odpověď. Vypočítat skutečné průsečíky je hodně drahé, potřebujete pouze srovnání. Klíčové slovo, které byste měli hledat, je „Oříznutí řádku“ (http://en.wikipedia.org/wiki/Line_clipping). Wikipedia doporučuje Cohen-Sutherlandův algoritmus (http://en.wikipedia.org/wiki/Cohen%E2%80%93Sutherland), pokud chcete rychlé odmítnutí, což je pravděpodobně nejběžnější scénář. Na stránce wikipedie je implementace C ++. Pokud nemáte zájem skutečně ořezat linku, můžete většinu z ní přeskočit. Odpověď @Johanna vypadá velmi podobně jako tento algoritmus, ale nepodíval jsem se na to podrobně.

Nejprve zkontrolujte, zda je rekt vlevo nebo vpravo od koncových bodů čáry:

  • Stanovte hodnoty X nejvíce vlevo a nejvíce vpravo koncových bodů čáry: XMIN a XMAX
  • Pokud Rect.Left> XMAX, pak žádná křižovatka.
  • Pokud Rect.Right & lt XMIN, pak žádná křižovatka.

Pokud výše uvedené nestačilo k vyloučení křižovatky, zkontrolujte, zda je konečný bod nad nebo pod koncovými body čáry:

  • Stanovte nejvyšší a nejnižší hodnoty Y koncových bodů čáry: YMAX a YMIN
  • Pokud Rect.Bottom> YMAX, pak žádná křižovatka.
  • Pokud Rect.Top & lt YMIN, pak žádná křižovatka.

Pokud výše uvedené nestačilo k vyloučení průsečíku, musíte zkontrolovat rovnici přímky y = m * x + b, abyste zjistili, zda je přímka nad čárou:

  • Stanovte hodnotu Y řádku na Rect.Left a Rect.Right: LINEYRECTLEFT a LINEYRECTRIGHT
  • Pokud Rect.Bottom> LINEYRECTRIGHT & amp & amp Rect.Bottom> LINEYRECTLEFT, pak žádná křižovatka.

Pokud výše uvedené nestačilo k vyloučení křižovatky, musíte zkontrolovat, zda je přímka pod čarou:

N.B. Jsem si jistý, že existuje elegantnější algebraické řešení, ale provádění těchto kroků geometricky perem a papírem je snadné.

K tomu nějaký nevyzkoušený a nekompilovaný kód:

Tento kód má lepší výkon:

Můžete také zkontrolovat, jak to funguje, v demo JS: http://jsfiddle.net/77eej/2/

Pokud máte dva body a Rect, můžete tuto funkci volat takto:

Vzal jsem řešení HABJAN, které fungovalo dobře, a převedl jsem ho na Objective-C. Kód Objective-C je následující:

Mnohokrát děkuji HABJAN. Poznamenám, že nejprve jsem napsal svou vlastní rutinu, která kontrolovala každý bod podél přechodu, a udělal jsem vše, co jsem mohl udělat pro maximalizaci výkonu, ale to bylo okamžitě mnohem rychlejší.

K tomu není možné zavolat žádnou jednoduchou předdefinovanou metodu .NET. Pomocí rozhraní Win32 API však existuje docela snadný způsob, jak to provést (snadné ve smyslu implementace, výkon není silnou stránkou): LineDDA

Tato funkce volá funkci zpětného volání pro každý pixel nakreslené čáry. V této funkci můžete zkontrolovat, zda je pixel ve vašem obdélníku - pokud ho najdete, pak se protne.

Jak říkám, toto není nejrychlejší řešení, ale implementace je docela snadná. Chcete -li jej použít v C#, budete jej samozřejmě muset ddlimportovat z gdi32.dll.

Nejjednodušší technikou výpočetní geometrie je prostě projít segmenty mnohoúhelníku a zjistit, zda se s některým z nich protíná, protože pak také musí protínat mnohoúhelník.

Jedinou výhradou této metody (a většiny CG) je, že si musíme dávat pozor na okrajové případy. Co když čára protíná obdélník v bodě - počítáme to jako průsečík nebo ne? Buďte opatrní při implementaci.

Upravit: Typickým nástrojem pro výpočet úseček protínajících segment je test LeftOf (Ray, Point), který se vrací, pokud je bod vlevo od paprsku. Vzhledem k přímce l (kterou používáme jako paprsek) a segmentu obsahujícímu body aab, přímka protíná segment, pokud je jeden bod vlevo a jeden bod není:

Opět si musíte dávat pozor na okrajové případy, kdy je bod na přímce, ale záleží na tom, jak chcete vlastně definovat křižovatku.


Všimněte si, že pokud je rovina rovnoběžná s L, pak je vektor kolmý na přímku kolmý na přímku. Najděte vektor/ (a) kolmý na rovinu, pak máte v rovině dva body a máte hotovo.

A existuje nekonečně mnoho rovin, které procházejí jakýmikoli dvěma danými body, existuje nekonečně mnoho rovin, které dokonce procházejí danou přímkou. Jakmile dostanete vektor kolmý na rovinu a dva body v rovině, máte hotovo (i když vzhledem ke dvěma bodům můžete najít N pomocí jejich křížového součinu.)

Pokud čára leží v rovině, můžete ji překládat, abyste zabránili jejímu zachycení.


2 odpovědi 2

Budete potřebovat aktivní seznam hran, který obsahuje seznam všech hran mnohoúhelníků protnutých aktuálním skenovacím řádkem. Budete také potřebovat příznak vstupu/výstupu pro každý polygon na ose skenování. Vlajky se přepínají na/z, když překračujete hranu pro mnohoúhelník.

Pravidla jsou kreslení pro každý pixel podél skeneru

  1. žádné „mnohoúhelníky“ nejsou, pak nakreslete pozadí
  2. pouze jeden polygonový příznak je „in“, nakreslí barvu tohoto polygonu
  3. jsou dva nebo více polygonových příznaků „in“, pomocí rovnice roviny zjistíte, který je v dané pozici pixelu nejbližší.
  4. když přecházíme na další pixel, zkontrolujte AEL (viz níže), abychom zjistili, zda překračujeme hranu. pokud ano, přepněte příslušný příznak.

Důležitou součástí datové struktury potřebné pro tento algoritmus je okrajový uzel. Každá hrana v polygonu je reprezentována hranovým uzlem. Okrajový uzel obsahuje následující informace

  1. yupper, souřadnice y horního koncového bodu okraje.
  2. ylower, souřadnice y dolního koncového bodu okraje.
  3. xint, zpočátku x souřadnice dolního koncového bodu hrany. Jak algoritmus postupuje, toto pole bude ukládat souřadnici x bodu průsečíku skenovací čáry.
  4. ym, převrácená hodnota sklonu čáry (1/m).
  5. odkaz na mnohoúhelník, který vlastní hranu.

Při konstrukci hranového uzlu pro hrany je třeba vzít v úvahu následující

  1. Vodorovné hrany jsou ignorovány (hraniční uzel pro ně není generován), tyto hrany budou vykresleny při zpracování sousedních hran.
  2. Pokud dvě hrany sdílejí vrchol A vrchol je horním koncovým bodem pro jednu hranu a dolním koncovým bodem pro jinou hranu, musí být yupper dolního okraje zmenšen o 1. to má umožnit správné přepínání vstup/výstup .

Na výše uvedeném obrázku se úplně horní skenovací čára protíná s okraji v horní části trojúhelníku. dva okraje způsobí, že se přepne z „ven“ na „in“ na „ven“, což je správné. Druhý řádek však také protíná dvě hrany a je přepnut „ven“, což je nesprávné. Řešením je v tomto případě snížit y-int spodního okraje. Skenovací čára nyní protíná pouze jednu hranu ve vrcholu.

Tato úprava nebude mít žádný vliv na tvar trojúhelníku, protože xint bude použit k určení, kde začít kreslit. Snížení vrcholu má za následek, že bude odstraněn o jeden skener dříve, než by tomu bylo jinak. To vše za předpokladu, že skenujete zdola nahoru.

Většina implementací udržuje Active edge list (AEL), seznam hran. který obsahuje všechny hrany protnuté aktuální skenovací linkou. AEL je třeba zachovat, když přecházíme z řádku skenování y na další řádek skenování (y+1)


& amp & amp vs. výkon ST_Intersects

Snažím se zjistit body umístěné uvnitř obdélníkové oblasti (obálky). Ve srovnání s ST_Intersect mám trochu potíže s porozuměním výkonnostním důsledkům používání & amp & amp operátoru.

Myslím si však, že jsem se pokusil formulovat svou otázku a vysvětlil jsem jí svou vlastní otázku. Každopádně to předkládám pro případ, že by to někomu bylo užitečné.

Manuál pro & amp & amp říká (ironicky název stránky je geometry_overlaps.html):

& amp & amp - Vrátí hodnotu TRUE, pokud 2D ohraničovací rámeček A protíná 2D ohraničovací rámeček B.`

Vrátí hodnotu TRUE, pokud se geometrie/geografie „prostorově protínají ve 2D“ - (sdílejte jakoukoli část prostoru) a NEPRAVDA, pokud ne (jsou nesouvislé). Pro geografii - tolerance je 0,00001 metrů (takže všechny body, které se uzavírají, jsou považovány za protínající se)

ST_Intersects vrátí v takových případech true. Pro můj objektiv & amp & amp & amp operátor dělá téměř totéž, protože v každém případě používám obdélníkové ohraničovací pole. Zajímalo by mě, jestli & amp & amp je nejrychlejší operátor pro můj účel? Zdá se, že & amp & amp musí provádět méně kontrol, takže musí být mnohem efektivnější.

Zde je příklad, který je přímou kopií z & amp & amp, ST_Intersects adaptace:

Níže je uveden jednoduchý graf, jak by tyto řádky měly vypadat. Právě jsem přidal vykreslení, abych viděl, jak ohraničovací rámeček funguje přesně pro čáry. Pro mé účely jsou body vždy uvnitř rámečku (zatímco tento příklad řádku ve skutečnosti neodráží to, co se snažím udělat, ale je to dobré pro ilustraci)

Otázka 1 zní, zda & amp & amp je při hledání s body uvnitř obdélníkového ohraničovacího rámečku výrazně rychlejší než ST_Intersects při použití s ​​ST_MakeEnvelope (obdélníková hranice).

Otázka 2 je také správně chápu, že při kontrole bodů uvnitř obdélníkové hranice & amp & amp dělá přesně to samé jako ST_Intersects?


Podívejte se na video: BI SAP Přednášky FIT 2021: 12. Paměťová hierarchie, cache