9 votos

arcgis10: crear transectos perpendiculares al flujo a intervalos especificados

Estoy tratando de hacer lo que mi título dice. El objetivo es introducir una línea, segmento en la distribución uniforme de la manera por una distancia especificada, convertir los vértices a los puntos, a continuación, dibuje las líneas perpendiculares al segmento a una distancia especificada. Estas líneas, que luego se convierte en punto en una manera similar, y devolver el máximo valor de elevación de oriente y occidente de cada punto. Todo este proceso está destinado a extraer muestras de una aproximación de banco de la altura de un río. He encontrado las herramientas y los procesos de la línea de segmentación (aunque molesto que parece que uno no puede tener acceso a la elegante barra de herramientas del Editor de procesos en python), pero estoy teniendo problemas para encontrar un script que hace que el transecto perpendicular a las líneas. Nadie ha hecho algo como esto antes? Nota: he encontrado la secuencia de comandos aquí, pero tiene demasiados fallos y dejé de tratar de solucionarlo (http://forums.arcgis.com/threads/49206-Perpendicular-transects-at-regular-intervals). Gracias!

3voto

Greg Puntos 1756

Ver también Transeptos Perpendiculares a ArcGIS 10 caja de herramientas y comandos de python por Mateus Ferreira. Crea líneas perpendiculares a intervalos regulares a lo largo de la línea, pero también tiene una opción para la obtención de la división de la distancia de un nombre de campo.

La página de enlaces a varios de los debates relacionados con soluciones parciales, aquí en SIG de Intercambio de la Pila que puede ser de interés para aquellos que la construcción o la mejora de sus propias herramientas.

Mateus' script:

# Import system modules
import arcpy
from arcpy import env
import math
arcpy.env.overwriteOutput = True

#Set environments
arcpy.env.overwriteOutput = True
arcpy.env.XYResolution = "0.00001 Meters"
arcpy.env.XYTolerance = "0.0001 Meters"

# Set local variables
env.workspace = arcpy.GetParameterAsText(0)
Lines=arcpy.GetParameterAsText(1)
SplitType=arcpy.GetParameterAsText(2)
DistanceSplit=float(arcpy.GetParameterAsText(3))
TransecLength=arcpy.GetParameterAsText(4)
TransecLength_Unit=arcpy.GetParameterAsText(5)
OutputTransect=arcpy.GetParameterAsText(6)

# Def splitline module
###START SPLIT LINE CODE IN A SAME DISTANCE### Source: http://nodedangles.wordpress.com/2011/05/01/quick-dirty-arcpy-batch-splitting-polylines-to-a-specific-length/
def splitline (inFC,FCName,alongDist):

    OutDir = env.workspace
    outFCName = FCName
    outFC = OutDir+"/"+outFCName

    def distPoint(p1, p2):
        calc1 = p1.X - p2.X
        calc2 = p1.Y - p2.Y

        return math.sqrt((calc1**2)+(calc2**2))

    def midpoint(prevpoint,nextpoint,targetDist,totalDist):
        newX = prevpoint.X + ((nextpoint.X - prevpoint.X) * (targetDist/totalDist))
        newY = prevpoint.Y + ((nextpoint.Y - prevpoint.Y) * (targetDist/totalDist))
        return arcpy.Point(newX, newY)

    def splitShape(feat,splitDist):
        # Count the number of points in the current multipart feature
        #
        partcount = feat.partCount
        partnum = 0
        # Enter while loop for each part in the feature (if a singlepart feature
        # this will occur only once)
        #
        lineArray = arcpy.Array()

        while partnum < partcount:
              # Print the part number
              #
              #print "Part " + str(partnum) + ":"
              part = feat.getPart(partnum)
              #print part.count

              totalDist = 0

              pnt = part.next()
              pntcount = 0

              prevpoint = None
              shapelist = []

              # Enter while loop for each vertex
              #
              while pnt:

                    if not (prevpoint is None):
                        thisDist = distPoint(prevpoint,pnt)
                        maxAdditionalDist = splitDist - totalDist

                        print thisDist, totalDist, maxAdditionalDist

                        if (totalDist+thisDist)> splitDist:
                              while(totalDist+thisDist) > splitDist:
                                    maxAdditionalDist = splitDist - totalDist
                                    #print thisDist, totalDist, maxAdditionalDist
                                    newpoint = midpoint(prevpoint,pnt,maxAdditionalDist,thisDist)
                                    lineArray.add(newpoint)
                                    shapelist.append(lineArray)

                                    lineArray = arcpy.Array()
                                    lineArray.add(newpoint)
                                    prevpoint = newpoint
                                    thisDist = distPoint(prevpoint,pnt)
                                    totalDist = 0

                              lineArray.add(pnt)
                              totalDist+=thisDist
                        else:
                              totalDist+=thisDist
                              lineArray.add(pnt)
                              #shapelist.append(lineArray)
                    else:
                        lineArray.add(pnt)
                        totalDist = 0

                    prevpoint = pnt                
                    pntcount += 1

                    pnt = part.next()

                    # If pnt is null, either the part is finished or there is an
                    #   interior ring
                    #
                    if not pnt:
                        pnt = part.next()
                        if pnt:
                              print "Interior Ring:"
              partnum += 1

        if (lineArray.count > 1):
              shapelist.append(lineArray)

        return shapelist

    if arcpy.Exists(outFC):
        arcpy.Delete_management(outFC)

    arcpy.Copy_management(inFC,outFC)

    #origDesc = arcpy.Describe(inFC)
    #sR = origDesc.spatialReference

    #revDesc = arcpy.Describe(outFC)
    #revDesc.ShapeFieldName

    deleterows = arcpy.UpdateCursor(outFC)
    for iDRow in deleterows:       
         deleterows.deleteRow(iDRow)

    try:
        del iDRow
        del deleterows
    except:
        pass

    inputRows = arcpy.SearchCursor(inFC)
    outputRows = arcpy.InsertCursor(outFC)
    fields = arcpy.ListFields(inFC)

    numRecords = int(arcpy.GetCount_management(inFC).getOutput(0))
    OnePercentThreshold = numRecords // 100

    #printit(numRecords)

    iCounter = 0
    iCounter2 = 0

    for iInRow in inputRows:
        inGeom = iInRow.shape
        iCounter+=1
        iCounter2+=1    
        if (iCounter2 > (OnePercentThreshold+0)):
              #printit("Processing Record "+str(iCounter) + " of "+ str(numRecords))
              iCounter2=0

        if (inGeom.length > alongDist):
              shapeList = splitShape(iInRow.shape,alongDist)

              for itmp in shapeList:
                    newRow = outputRows.newRow()
                    for ifield in fields:
                        if (ifield.editable):
                              newRow.setValue(ifield.name,iInRow.getValue(ifield.name))
                    newRow.shape = itmp
                    outputRows.insertRow(newRow)
        else:
              outputRows.insertRow(iInRow)

    del inputRows
    del outputRows

    #printit("Done!")
###END SPLIT LINE CODE IN A SAME DISTANCE###

# Create "General" file geodatabase
WorkFolder=env.workspace
General_GDB=WorkFolder+"\General.gdb"
arcpy.CreateFileGDB_management(WorkFolder, "General", "CURRENT")
env.workspace=General_GDB

#Unsplit Line
LineDissolve="LineDissolve"
arcpy.Dissolve_management (Lines, LineDissolve,"", "", "SINGLE_PART")
LineSplit="LineSplit"

#Split Line
if SplitType=="Split at approximate distance":
    splitline(LineDissolve, LineSplit, DistanceSplit)
else:
    arcpy.SplitLine_management (LineDissolve, LineSplit)

#Add fields to LineSplit
FieldsNames=["LineID", "Direction", "Azimuth", "X_mid", "Y_mid", "AziLine_1", "AziLine_2", "Distance"]
for fn in FieldsNames:
    arcpy.AddField_management (LineSplit, fn, "DOUBLE")

#Calculate Fields
CodeBlock_Direction="""def GetAzimuthPolyline(shape):
 radian = math.atan((shape.lastpoint.x - shape.firstpoint.x)/(shape.lastpoint.y - shape.firstpoint.y))
 degrees = radian * 180 / math.pi
 return degrees"""

CodeBlock_Azimuth="""def Azimuth(direction):
 if direction < 0:
  azimuth = direction + 360
  return azimuth
 else:
  return direction"""
CodeBlock_NULLS="""def findNulls(fieldValue):
    if fieldValue is None:
        return 0
    elif fieldValue is not None:
        return fieldValue"""
arcpy.CalculateField_management (LineSplit, "LineID", "!OBJECTID!", "PYTHON_9.3")
arcpy.CalculateField_management (LineSplit, "Direction", "GetAzimuthPolyline(!Shape!)", "PYTHON_9.3", CodeBlock_Direction)
arcpy.CalculateField_management (LineSplit, "Direction", "findNulls(!Direction!)", "PYTHON_9.3", CodeBlock_NULLS)
arcpy.CalculateField_management (LineSplit, "Azimuth", "Azimuth(!Direction!)", "PYTHON_9.3", CodeBlock_Azimuth)
arcpy.CalculateField_management (LineSplit, "X_mid", "!Shape!.positionAlongLine(0.5,True).firstPoint.X", "PYTHON_9.3")
arcpy.CalculateField_management (LineSplit, "Y_mid", "!Shape!.positionAlongLine(0.5,True).firstPoint.Y", "PYTHON_9.3")
CodeBlock_AziLine1="""def Azline1(azimuth):
 az1 = azimuth + 90
 if az1 > 360:
  az1-=360
  return az1
 else:
  return az1"""
CodeBlock_AziLine2="""def Azline2(azimuth):
 az2 = azimuth - 90
 if az2 < 0:
  az2+=360
  return az2
 else:
  return az2"""
arcpy.CalculateField_management (LineSplit, "AziLine_1", "Azline1(!Azimuth!)", "PYTHON_9.3", CodeBlock_AziLine1)
arcpy.CalculateField_management (LineSplit, "AziLine_2", "Azline2(!Azimuth!)", "PYTHON_9.3", CodeBlock_AziLine2) 
arcpy.CalculateField_management (LineSplit, "Distance", TransecLength, "PYTHON_9.3")

#Generate Azline1 and Azline2
spatial_reference=arcpy.Describe(Lines).spatialReference
Azline1="Azline1"
Azline2="Azline2"
arcpy.BearingDistanceToLine_management (LineSplit, Azline1, "X_mid", "Y_mid", "Distance", TransecLength_Unit, "AziLine_1", "DEGREES", "GEODESIC", "LineID", spatial_reference)
arcpy.BearingDistanceToLine_management (LineSplit, Azline2, "X_mid", "Y_mid", "Distance", TransecLength_Unit, "AziLine_2", "DEGREES", "GEODESIC", "LineID", spatial_reference)

#Create Azline and append Azline1 and Azline2
Azline="Azline"
arcpy.CreateFeatureclass_management(env.workspace, "Azline", "POLYLINE", "", "", "", spatial_reference)
arcpy.AddField_management (Azline, "LineID", "DOUBLE")
arcpy.Append_management ([Azline1, Azline2], Azline, "NO_TEST")

#Dissolve Azline
Azline_Dissolve="Azline_Dissolve"
arcpy.Dissolve_management (Azline, Azline_Dissolve,"LineID", "", "SINGLE_PART")

#Add Fields to Azline_Dissolve
FieldsNames2=["x_start", "y_start", "x_end", "y_end"]
for fn2 in FieldsNames2:
    arcpy.AddField_management (Azline_Dissolve, fn2, "DOUBLE")

#Calculate Azline_Dissolve fields
arcpy.CalculateField_management (Azline_Dissolve, "x_start", "!Shape!.positionAlongLine(0,True).firstPoint.X", "PYTHON_9.3") 
arcpy.CalculateField_management (Azline_Dissolve, "y_start", "!Shape!.positionAlongLine(0,True).firstPoint.Y", "PYTHON_9.3")
arcpy.CalculateField_management (Azline_Dissolve, "x_end", "!Shape!.positionAlongLine(1,True).firstPoint.X", "PYTHON_9.3")
arcpy.CalculateField_management (Azline_Dissolve, "y_end", "!Shape!.positionAlongLine(1,True).firstPoint.Y", "PYTHON_9.3")

#Generate output file
arcpy.XYToLine_management (Azline_Dissolve, OutputTransect,"x_start", "y_start", "x_end","y_end", "", "", spatial_reference)

#Delete General.gdb
arcpy.Delete_management(General_GDB)

3voto

Corey Puntos 700

He encontrado el código de la cortesía de Gerry Gabrisch publicado en un viejo ArcGIS 9.2 foro (http://arcscripts.esri.com/details.asp?dbid=15756) y modificado para que funcione en ArcGIS 10. La salida original de un archivo de texto con las coordenadas, y esta versión escribe la geometría a un vacío de shapefile. Asumir "en línea" es la entrada de la línea característica. Todo lo que necesita ser hecho una vez que se ejecuta este código es para llamar a la función "buildTransects". El código funciona bastante bien, pero todas las líneas perpendiculares en la salida no tienen la misma longitud. Tal vez necesita un poco más de ajuste, pero las longitudes de partido sólo lo suficiente para al menos discriminatoria usuario =D

# Create empty polyline for transects
spatialref = arcpy.Describe(inLine).spatialReference
if arcpy.Exists('transects'): 
    arcpy.Delete_management('transects')
transects = arcpy.CreateFeatureclass_management(temp,'transects.shp',"POLYLINE",'','','',spatialref)
arcpy.AddField_management(transects, "slope", "DOUBLE")

# inLine = input line, transects = new shapefile created above,
# transDist = length of transect (approximate), workspace = workspace
def buildTransects(inLine,transects,transDist,workspace):

    # Define orientation (start, mid, end) and draw transect function
    # This function is defined before it is called
    def orientTransect(feat,ix,iy):

            # If the line is horizontal or vertical, the slope and
            # negative reciprocal calculations will fail, so do this instead
            if starty==endy or startx==endx:
                if starty == endy:
                    y1 = iy + transDist
                    y2 = iy - transDist
                    x1 = ix
                    x2 = ix

                if startx == endx:
                    y1 = iy
                    y2 = iy
                    x1 = ix + transDist
                    x2 = ix - transDist


            else:

                # Get slope of line
                m = ((starty - endy)/(startx - endx))

                # Get negative reciprocal
                negativereciprocal = -1*((startx - endx)/(starty - endy))

                # For all values of slope, calculate perpendicular line
                # with length = transDist
                if m > 0:
                    if m >= 1:
                        y1 = negativereciprocal*(transDist)+ iy
                        y2 = negativereciprocal*(-transDist) + iy
                        x1 = ix + transDist
                        x2 = ix - transDist
                    if m < 1:
                        y1 = iy + transDist
                        y2 = iy - transDist
                        x1 = (transDist/negativereciprocal) + ix
                        x2 = (-transDist/negativereciprocal)+ ix

                if m < 0:
                    if m >= -1:
                        y1 = iy + transDist
                        y2 = iy - transDist
                        x1 = (transDist/negativereciprocal) + ix
                        x2 = (-transDist/negativereciprocal)+ ix

                    if m < -1:
                        y1 = negativereciprocal*(transDist)+ iy
                        y2 = negativereciprocal*(-transDist) + iy
                        x1 = ix + transDist
                        x2 = ix - transDist
            point1.X = x1
            point1.Y = y1
            point2.X = x2
            point2.Y = y2
            lineArray.add(point1)
            lineArray.add(point2)

            del x1
            del x2
            del y1
            del y2

    # Create search cursor in inLine
    rows = arcpy.SearchCursor(inLine)

    # Get number of records in inLine
    numRecords = int(arcpy.GetCount_management(inLine).getOutput(0))


    # Create new point files and array to collect values
    point1 = arcpy.Point()
    point2 = arcpy.Point()
    lineArray = arcpy.Array()

    # Define counter
    counter = 0

    # Loop over rows in outLine
    for row in rows:

        # Create the geometry object
        feat = row.Shape

        # Get coordinate values as lists
        firstpoint = feat.firstPoint
        lastpoint = feat.lastPoint
        midpoint = feat.centroid

        # Get X and Y values for each point
        startx = firstpoint.X
        starty = firstpoint.Y
        endx = lastpoint.X
        endy = lastpoint.Y
        midx = midpoint.X
        midy = midpoint.Y

        m = ((starty - endy)/(startx - endx))

        # For all points besides the last one
        if counter < numRecords - 1:
            orientTransect(feat,startx,starty)
        # For the last point
        else:
            orientTransect(feat,endx,endy)

        #Create insert cursor
        cur = arcpy.InsertCursor(transects)

        #Insert new row from array
        feat = cur.newRow()
        feat.slope = m
        feat.shape = lineArray
        cur.insertRow(feat)
        lineArray.removeAll()

        del cur

        # Increase counter by 1 and start again
        counter = counter + 1

    del row
    del rows

    printit('Added %s transects to inLine and saved to temp/transects.shp' % str(counter))

2voto

disha Puntos 16

Esto lo hice hace un tiempo. Esto es lo que hice. 1. Usando el algoritmo de referencia río líneas centrales, agregó escotillas de cada uno-milla (usted puede elegir el intervalo). Hechas las escotillas de 2 millas de ancho. (usted puede elegir el ancho) 2. Convierte escotillas gráfico de líneas (barra de herramientas draw) 3. Gráfico convertido líneas en una clase de entidad de línea. 4. La ruta asignada ID y vuelva a medir la característica clase de uso de "encontrar las características a lo largo de las Rutas". 5. Las líneas resultantes fueron perpendicular al río de la línea, no es necesario el general de la llanura aluvial. Girar varias secciones transversales para ajustarse a la llanura de las tendencias. Esto fue hecho en más de una ocasión. A partir de aquí yo era capaz de extraer de las elevaciones de los DEM y, a continuación, encontrar min, max, etc.

1voto

Pengfei Puntos 507

teníamos que hacer algo similar y encontró usted puede hacer manualmente. Es tedioso, pero mediante la creación de un punto al azar en la línea y, a continuación, agregar la igualdad de intervalo de puntos de ese origen, tienen iguales el intervalo de puntos. A continuación, coloca a cada punto y dibuje una línea perpendicular desde su línea de flujo o línea de vaguada, que se tiene que hacer de forma individual en cada dirección (derecha e izquierda). Usted puede combinar esas líneas perpendiculares y el uso de ellos como los transectos, o convertir a los puntos. Hay dos conjuntos de herramientas que pueden ser útiles, uno se llama ET GeoWizards que requiere una licencia, pero tiene herramientas que hacen más o menos exactamente lo que usted necesita. La otra opción es una herramienta gratuita conjunto, llamado "Geoespaciales Entorno de Modelización" (que solía ser Hawths' herramientas). El vector de herramientas de "generar puntos al azar" y "convertir las líneas de puntos". Espero que esto ayude...es una tarea tediosa.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X