Rysowanie równoległych linii wewnątrz wielokątów (Ścieżek studni) za pomocą ArcGIS Desktop?


11

Chciałbym wziąć klasę cech wielokąta z wieloma nieregularnymi wielokątami i pozwolić, aby łuk rysował równoległe linie wewnątrz każdego wielokąta. Idealnie byłoby miło, gdyby Arc obliczył kąt najdłuższego boku wielokąta i narysował równoległe linie do tej strony, ale dla uproszczenia myślę, że gdybym mógł po prostu wprowadzić jeden kąt dla wszystkich równoległych linii, to byłoby łatwiejsze.

Tak więc moje podstawowe kryteria to kąt linii, szerokość między liniami, długość min./maks. I szerokość bufora z boków wielokątów.

Obraz w załączeniu, jeśli to pomaga.

wprowadź opis zdjęcia tutaj


Czy linie muszą się kończyć w pewnej odległości od krawędzi wielokąta?
cndnflyr

tak, muszę mieć bufor z dala od krawędzi. Gdybym mógł zadeklarować tę wartość, byłoby świetnie. Dzięki.
Tx_Dan

Odpowiedzi:


9

Jak wspomina @cndnflyr, można to zrobić w Pythonie.

Interfejs narzędzia skryptowego:

wprowadź opis zdjęcia tutaj

Przykładowe dane wyjściowe: wprowadź opis zdjęcia tutaj

# import libraries
import arcpy

# set input/output parameters
polyFC = arcpy.GetParameterAsText(0)        # input polygons
outParallel = arcpy.GetParameterAsText(1)   # output parallel lines
lineSpacing = arcpy.GetParameterAsText(2)   # line spacing
buffDist = arcpy.GetParameterAsText(3)      # inner buffer distance

# parse numbers from parameters
lineSpaceNum = float(lineSpacing.split(' ')[0])
buffNum = float(buffDist.split(' ')[0])

# establish spatial reference
desc = arcpy.Describe(polyFC)
SR = desc.spatialReference

# set overwrite environment
arcpy.env.overwriteOutput = True
arcpy.env.outputCoordinateSystem = SR

parallels = []
# loop through each input shape
for row in arcpy.da.SearchCursor(polyFC, ["SHAPE@"], spatial_reference=SR):

    # create inner buffer
    polyBuff = row[0].buffer(buffNum * -1)

    # create hull rectangle to establish a rotated area of interest
    coordSplit = row[0].hullRectangle.split(' ')

    # collect corner coordinates
    coordList = arcpy.Array([arcpy.Point(coordSplit[0],coordSplit[1]),arcpy.Point(coordSplit[2],coordSplit[3]),arcpy.Point(coordSplit[4],coordSplit[5]),arcpy.Point(coordSplit[6],coordSplit[7]),arcpy.Point(coordSplit[0],coordSplit[1])])

    # create lines from hull rectangle
    currentLines = []
    for pointNum in range(0,4):
        arcpy.Array([coordList.getObject(pointNum),coordList.getObject(pointNum+1)])
        hullRecLine = arcpy.Polyline(arcpy.Array([coordList.getObject(pointNum),coordList.getObject(pointNum+1)]))
        currentLines.append(hullRecLine)

    # compare first and second line to determine if first line is short or long
    firstLong = 0
    if currentLines[0].length > currentLines[1].length:
        firstLong = 1

    # calculate number of points needed along short axis
    numPoints = int(math.floor(currentLines[firstLong].length/lineSpaceNum))

    # create and join points to create parallel lines
    for point in range(1,numPoints+1):
        shortPoint1 = currentLines[firstLong].positionAlongLine(lineSpaceNum*point)
        shortPoint2 = currentLines[firstLong + 2].positionAlongLine(currentLines[firstLong + 2].length - (lineSpaceNum*point))
        parallel = arcpy.Polyline(arcpy.Array([shortPoint1.centroid,shortPoint2.centroid]), SR)

        # intersect parallel lines with buffer
        parallelBuff = parallel.intersect(polyBuff,2)
        parallels.append(parallelBuff)

# write geometries to disk
arcpy.CopyFeatures_management(parallels, outParallel)

# add to map
mxd = arcpy.mapping.MapDocument("CURRENT")
dataFrame = arcpy.mapping.ListDataFrames(mxd, "*")[0]
addLayer = arcpy.mapping.Layer(outParallel)
arcpy.mapping.AddLayer(dataFrame, addLayer)

del row

Wow, ten piękny, łyko! Spójrz. Dziękuję bardzo!
Tx_Dan

To świetne wykorzystanie metod w obiekcie SHAPE. Jest elegancki. Brakuje tylko ustawienia kąta linii. W tym momencie narysuje linie wzdłuż najdłuższego boku wielokąta.
cndnflyr

4

Można to zrobić za pomocą Pythona, ale napisanie go zajęłoby trochę czasu.

Myślę, że najszybszym sposobem na wdrożenie go bez Pythona jest posiadanie szablonu pliku SHP tych równoległych linii. Miej kilka, jeśli potrzebujesz różnych szerokości, i po prostu użyj odpowiedniej dla tego wielokąta. Spraw, aby linie szablonu obejmowały wystarczającą powierzchnię, aby pokryć największy wielokąt, jaki napotkasz.

  1. Podczas edycji przesuń linie nad wielokątem.
  2. Użyj narzędzia Obróć, przenieś punkt kontrolny do miejsca, w którym linia równoległa i krawędź wielokąta, pasują, a następnie obróć linie, aby przyciągnęły się do krawędzi wielokąta, na której została ustawiona.
  3. Przekształć wielokąt w polilinię
  4. Buforuj polilinię, niezależnie od odległości, jaką mają mieć linie równoległe od krawędzi wielokąta.
  5. Użyj narzędzia Wymaż, aby usunąć polilinie zakryte zbuforowaną krawędzią wielokąta
  6. Wybierz według lokalizacji wszystkie linie, które nie znajdują się w wielokącie, i usuń je. Albo myślę, że narzędzie Clip też by działało.
  7. Wybierz według atrybutu wszystkie linie, które są mniejsze niż pewna długość (zbyt krótka, aby zachować, chociaż może być konieczne dodanie pola i obliczenie geometrii w pierwszej kolejności), oraz większa niż pewna długość (zbyt długa, aby zachować, jeśli to jest to, czego chcesz ), Usuń ich.
  8. Wypłukać i powtórzyć...

Kroki od 3 do 7 można modelować bez konieczności pisania kodu.

Do kodowania tego procesu można zastosować ten sam proces, ale zamiast linii szablonu, możesz narysować linie pod odpowiednim kątem, w odległości od siebie itp. Nie robiłem tego przez jakiś czas, ale myślę, że Pomogłaby biblioteka Python jak foremna . Po prostu upewnij się, że obejmuje większy obszar niż Wielokąt, i użyj narzędzi do automatycznej konwersji na polilinię, buforowania, wymazywania, zaznaczania linii spoza wieloboku i usuwania ich.


Dziękuję za szczegółową odpowiedź. Spróbuję i zobaczę, jak to działa. Dzięki!
Tx_Dan
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.