|
POST
|
Thanks Richard. This script is really kicking my butt! I made another mod to the script to change if arcLength > ' ': to if arcLength > '0':. That will exclude arclengths of ' ' and '0', but include '1'-'9'.
... View more
09-03-2013
11:40 AM
|
0
|
0
|
2367
|
|
POST
|
Using Jake's example, I was unable to get any results. Using, Rich's example, I was able to return either ARCLENGTH or Shape_Length. But, it only returns one record at a time and the record with the largest OID. For instance, if I have 3 Shape_Length records selected, Shape_Length = 302.5 is returned. The script returns only the record with the highest OID value. Any ideas on how to return all three values? Something along the lines of: Shape_Length = 244.5 Shape_Length = 692.9 Shape_Length = 302.5 for lyr in arcpy.mapping.ListLayers(mxd):
dsc = arcpy.Describe(lyr)
sel_set = dsc.fidSet.replace(";",",")
if dsc.shapeType == "Polyline" and dsc.fidSet != "":
cursor = arcpy.da.SearchCursor(lyr, ["OID@", "ARCLENGTH", "Shape_Length"], "OBJECTID IN (" + sel_set + ")")
for row in cursor:
arcLength = row[1]
shapeLength = row[2]
if arcLength > '0':
arcpy.AddMessage("ArcLength = " + arcLength)
else:
arcpy.AddMessage("ShapeLength = " + str(shapeLength))
del row
del cursor It is another case of the indent being at the wrong level. By indenting as I have above the loop includes the message as each record is processed. Before it only processed once after all rows had been read, so only the last row data was left. Also, I believe the line that reads if len(arcLength) > 0: should be replaced by the line I have shown above (if arcLength > '0': ) to ensure than even single digit above 0 arclength's are included in the output as an ArcLength.
... View more
09-03-2013
11:30 AM
|
0
|
0
|
2367
|
|
POST
|
Thanks Tim I'm going to do the manual approach you suggested for now, but will likely transition to doing it in Python. I'm not great with the update cursor, but having the python is a better approach over the long term. Jared Construct the process through a Model in Model Builder and then export the Model as a Python script. That way you have a start on the process and can decide if you want to replace geoprocessing tools with cursors later. In any event the script can be run as either a model or a Python script without having to do it manually each time you want to run it.
... View more
09-03-2013
09:41 AM
|
0
|
0
|
1839
|
|
POST
|
I would have expected an indentation error, but not the name error. Thanks. It was only logically wrong, not syntactically wrong. The level it was at was possible for other lines of code, but the objects referred to in that particular line only come into existence if you make it to the next indent level.
... View more
09-03-2013
06:43 AM
|
0
|
0
|
2367
|
|
POST
|
I am receiving an error in line 66, del row, rows. The error code is an NameError: name row and rows are not defined. How are they not defined? If I comment the del row, rows statement out the script runs. import arcpy
mxd = arcpy.mapping.MapDocument ("CURRENT")
df = arcpy.mapping.ListDataFrames (mxd)[0]
lyr = arcpy.mapping.ListLayers(mxd, "Lot_Lines", df)[0]
arcpy.AddMessage(lyr.name)
for lyr in arcpy.mapping.ListLayers(mxd):
dsc = arcpy.Describe(lyr)
sel_set = dsc.fidSet
if dsc.shapeType == "Polyline":
if len(sel_set) > 0:
sel_set = sel_set.replace(";", ",")
arcLengthList = []
shapeLengthList = []
rows = arcpy.SearchCursor(lyr, "OBJECTID IN (" + sel_set + ")")
for row in rows:
arcLengthList.append(row.ARCLENGTH)
shapeLengthList.append(row.Shape_Length)
i = 0
while i < len(arcLengthList):
if len(arcLengthList) > 0:
print arcLengthList
else:
print shapeLengthList
i += 1
arcpy.AddMessage("Good")
else:
rows = arcpy.SearchCursor(lyr, "OBJECTID = " + sel_set)
for row in rows:
arcLength = row.ARCLENGTH
shapeLength = row.Shape_Length
if len(arcLength) > ' ':
arcpy.AddMessage("ArcLength = " + arcLength)
else:
arcpy.AddMessage("ShapeLength = " + str(shapeLength))
del row, rows Just indent the del row, rows one more time and that will fix that line. It is at the wrong indent level.
... View more
09-03-2013
06:29 AM
|
0
|
0
|
1637
|
|
POST
|
Thank you for your reply. After continuing to work on the problem, I discovered the same problem myself. So I changed all my CalculateField lines adding the critical "PYTHON_9.3" to the end of my line. After a lot of testing, I can confirm that this fix was exactly what was needed and it works perfectly. Glad you fixed it, fellow Riv. Co. coworker. Have a happy Labor Day holiday.
... View more
09-01-2013
06:12 PM
|
0
|
0
|
1376
|
|
POST
|
Kept working on the issue to try to simplify code. Saw no need to use cursor at all. However, the CalculateField still presents issues. If I hardcode the values for AOI and SharedAOI within the PLines attribute table, the entire process works perfectly. However, if I attempt to use a variable, ie: myaoi = '69257', mysharedaoi = 'value_from_current_selected_AOI', still resulting in the values being shown as 'xxxxx', exactly like hardcoded values, then I will get an error everytime. It seems that each combination of quotes, double quotes, etc. will produce a different error. Sometimes an empty selection set, and sometimes can't acquire data lock. #Hardcoded AOI's & SharedAOI's for CalculateField works as expected.
#This sequence uses selected aoi to grab all parcel lines sharing segment, then selects adjacent AOI's
#sharing segment with parcel lines.
arcpy.SelectLayerByLocation_management("PLines","SHARE_A_LINE_SEGMENT_WITH","AOI")
arcpy.SelectLayerByLocation_management("AOI","SHARE_A_LINE_SEGMENT_WITH","PLines")
aoilst = []
with arcpy.da.SearchCursor("AOI","AOI") as cursor:
for row in cursor:
print row[0]
aoilst.append(row[0])
del cursor, row
myaoi = '69257'
fc = "AOI"
for eachaoi in aoilst:
mysharedaoi = "'" + eachaoi + "'"
print "mysharedaoi = " + mysharedaoi
sbaAOI = "AOI = '" + eachaoi + "'"
print ("Current AOI selected = " + eachaoi)
print sbaAOI
arcpy.SelectLayerByAttribute_management("AOI","NEW_SELECTION",sbaAOI)
arcpy.RefreshActiveView()
arcpy.RefreshTOC()
arcpy.SelectLayerByLocation_management("PLines","SHARE_A_LINE_SEGMENT_WITH","AOI")
arcpy.RefreshActiveView()
arcpy.RefreshTOC()
if int(eachaoi) < int(myaoi):
print ("SharedAOI needs to be calc'd with myaoi")
#arcpy.CalculateField_management("PLines", "SharedAOI",myaoi) Variables replaced with hardcoded values
#arcpy.CalculateField_management("PLines", "AOI", mysharedaoi) Variables replaced with hardcoded values
arcpy.CalculateField_management("PLines", "SharedAOI",'69257')
arcpy.CalculateField_management("PLines", "AOI", '99999')
arcpy.RefreshTOC()
arcpy.RefreshActiveView()
print ("lines calculated")
elif int(eachaoi) > int(myaoi):
print ("AOI needs to be calc'd with myaoi")
#arcpy.CalculateField_management("PLines", "AOI", myaoi)
#arcpy.CalculateField_management("PLines", "SharedAOI", mysharedaoi)
arcpy.CalculateField_management("PLines", "SharedAOI",'99999')
arcpy.CalculateField_management("PLines", "AOI", '69257')
arcpy.RefreshTOC()
arcpy.RefreshActiveView()
print ("lines calculated") Once again, thank you for any assistance with this problem. At least part of your problem is that you are not specifying that your calculations are to be done using Python_9.3 as the Field Calculator parser. Therefore your calculations are defaulting to using VB Script instead, which only supports double quotes for strings. Specify that you want Python_9.3 as the parser so you can use Python syntax throughout your code. I.e.: arcpy.CalculateField_management("PLines", "SharedAOI", mysharedaoi, "PYTHON_9.3") The fact that you did not get an error with the hardcoded values is probably because the hardcoded '99999' is being sent to the calculator as a number, which VB will convert to a string. But it won't accept a string of '99999' itself, i.e., "'99999'" will fail. Your variable is passing in the latter value, not the former. The failure is due the the fact that the single quotes around a number is all VB sees, which is not a number or a string as far as VB is concerned. It is strictly an invalid entry to VB. Anyway, only Python is agnostic about single and double quotes for strings, not VB Script, and in this case it would be best to eliminate VB Script from the workflow so you only need to follow Python rules. You may still need to add some kind of test for NULL values if you think any exist, but your problems are probably due to SQL requiring single quoted strings, while VB wants double quotes strings, so nothing you do will satisfy both with a single value.
... View more
09-01-2013
02:52 PM
|
0
|
0
|
1376
|
|
POST
|
If you would like to make 1 mile line segments instead of or in addition to mile post points, modify the Excel spreadsheet to include 2 columns for miles called From_Mile and To_Mile and two for your other units (in my case From_Feet and To_Feet). Make the first two rows below the headings with these values (or their equivalent for your measure units): From_Mile To_Mile From_Feet To_Feet
0 1 0 5280
1 2 5280 10560 Then drag the lower right corner of that two row group down as many rows until the From_Mile is greater than your highest mile post measure on your routes. Then include all of those fields in the Make Query Table field list and make the query expression Mile_Post.From_Feet <= MyRoutes.To_Meas Then you can make that event table into two different mile-post point event layers (marking either the beginning or end of the mile) or into a one-mile line segments layer with the Display Route Events context menu option. Note: To make the same set of points that my original method made create the Route Event layer as points using the From_Feet field and then put a definition query on the event layer with the expressioin: FROM_FEET <> 0.
... View more
08-31-2013
10:52 PM
|
0
|
0
|
2784
|
|
POST
|
Just to be clear, I actually did my method with my route network of 32,000 roads derived from a Centerline network. I created over 7,000 mile post points within about 60 minutes. Almost of that time was spent writing the post as I went. I also did have to do some experimentation with the Make Query Table tool, which I don't use a lot (I tried 3 different settings for the ObjectID field before settling on the Virtual ObjectID option). Now with the steps laid out I could easily do it again in under 15 minutes since my Route Network is already to go. Building the routes can take considerably more time if you have never created a route system from your streams, but the uses of LR are extensive and the only way I would ever work with polylines and points that need to match up with each other. And LR offers a lot more options than standard lines or points in my opinion so I would recommend developing LR routes even if you didn't need mile post points.
... View more
08-31-2013
09:17 PM
|
0
|
0
|
2784
|
|
POST
|
Did u got any answers, as i am also struck with similar problem...?? Here is how I have done it. The instructions are fairly detailed so they are a bit long, but hopefully understandable to even the most novice user. I first create or use a file geodatabase, since several of the tools will not work with shapefiles or dbf tables. Everything I am describing will be placed in this file geodatabase unless I indicate otherwise. Then I created Linear Referenced Routes from my line network using the Create Routes Tool in the Linear Referencing Toolbox. This tool provides several ways to convert your input network to routes affecting the way the lines are chained together and measures are created. For your data you should use a unique stream ID for each stream segment. Click the Environments... option button and expand the M values section to set the M tolerance and M resolution to fractional values to get correctly applied measures on each vertex and make sure they are small enough for the units and precision you will want. In my case, my units are in feet and my M tolerance is set to .001 and my M resolution is set to .0001 (M resolution should always be 10 times the M tolerance as a general rule). In general try to avoid branched routes unless you control the stream measures to flow with the same initial measure at each branch point. This can require more sophisticated route construction techniques, which are beyond the scope of this post. Similar control is needed if you are just merging lines prior to creating your routes. Add two double fields to the Route Feature Class and name them FROM_MEAS and TO_MEAS. Use the Field Calculator and using the Python option to calculate each field to be !Shape.FirstPoint.M! and !Shape.LastPoint.M! respectively. Create a Long field and call it Parts. Use the Field Calculator and using the Python option to calculate this field to be !Shape.PartCount!. Select streams with PARTS > 1. Compare the TO_MEAS value to the reported Line Length (accounting for any unit conversion needed). The differences in measures will indicate how gaps and branches affected the way the line was measured and may indicate additional editing is needed to get the ultimate results you want. Sort the table on the TO_MEAS field and find the highest measure value and convert that measure value to miles (if your measures are not already in miles). This will define the highest mile post possible. In a new Excel spreadsheet add a name in the first column called MILES. Type the numbers 1 in the next row and then 2 in the row after that. Highlight these two numbered rows and drag the lower right little black box that should appear to extend the numbering pattern down for as many rows as you need to exceed your highest measure (you can go several rows beyond what you currently need as a precaution). If your routes use measures that are not actually in miles, in the next column to the right place a name indicating the measure units of your actual route measures, such as Feet. Below that heading name place a unit conversion calculation to convert the miles in the first column to those units. In my case the second column was named FEET and the formula was =A2*5280. Double click the lower right corner of the formula cell to extend it downward next to every row that has a mileage number. Save this file to a cvs file and call it Mile_Posts.cvs. In ArcCatalog right click the cvs file you just created with mile post numbers and convert it at first to a dbf file called Mile_Posts.dbf. This file will not be inside the file geodatabase where your routes are. Now export the dbf file to make another new table in your file geodatabase and call it Mile_Posts. Now use the Make Query Table tool in the Data Management toolbox in the Layers and Table Views toolset. Use these settings: Input Tables: First add your Route feature class and then add the Mile_Post table from the same file geodatabase to the table list. Fields: Check the unique Route ID field defining your routes and then check the Miles field and then your Feet field (or whatever actual measure units you used on your route other than miles, if applicable). Expression: Create an expression where the actual units field of your routes is less than or equal to the TO_MEAS field value of your routes. In my case it was: Mile_Posts.Feet <= MyRoutes.TO_M Use the Add Virtual Key Field option. The Query Table output is only created in memory within a given map document or model. To make the output permanent use the Table to Table tool under the Conversion Tools toolbox in the To Geodatabase toolset. Use the field name list of this tool to rename the filed so that they will be saved without creating long qualified field names that include the origin table names for the fields. The table can now act as an event table that can be used to create points on your stream network. Right click the table in the Table of Contents of a map that has the Route features in it and click the context menu option to Display Route Events. Set the Route ID values for the Routes and the Events to be the same and use the field that contains the mile posts values in the actual units of your measures (in my case the Feet field). You don't need an offset field. You should also check the Advanced Options button at the lower right and check the Generate a field for locating errors option. You can also check the Create an angle field for point events option if you would like to know the actual angle of orientation of the stream at the mile post location. The resulting output will place points at every mile post on every stream that is at least one mile in length. Shorter streams will not have any points. If you don't like the location of a given mile post for some reason and want to offset it up or down the stream simply select that point and recalculate the measure value by adding or subtracting a distance in the units of your measures. So if I wanted a given mile post to adjust by 1000 down a stream I would simply add 1000 to the selected point's FEET field. Examine the LOC_ERROR field which was generated to show location errors of he events. Select all values where "LOC_ERROR" <> 'NO ERROR'. These are locations that fell in measure gaps or off the ends of the stream lines for some reason. This may indicate routes where you would want to fix gaps, adjust the line part order, or adjust the measure assigned at branch points. Reverse the selection to see all of the mile post points that actually fell on the lines or use the query "LOC_ERROR" = 'NO ERROR' eitehr to select them or as a layer definition query to filter them. The event layer can be used directly for your split points, although it only exists in memory within a given map or model. You can export the layer or use the Feature Class to Feature Class tool with the layer to make it a normal point feature class that is permanently stored. That should be all you need to split your lines at the mile posts or mark the mile posts with points.
... View more
08-31-2013
09:38 AM
|
0
|
0
|
2784
|
|
POST
|
The perimeter to area ratio should also be used to help separate circular shapes from non-circular shapes. I forget the ratio of a perfect circle but a little experimentation with a few circular examples should come up with the ratio fairly easily.
... View more
08-30-2013
01:05 PM
|
0
|
0
|
8284
|
|
POST
|
It wasn't too confusing. 🙂 And I thought it might work for a few minutes. However, since some of the addresses are font size 1 and others are as big as font size 9, there is no "one size fits all" buffer that will work on all the points. Also, when I converted the addresses over from annotation, they lost all their attributes, so I have no way to select them by font size to work on them as groups. On the Polygon features add a double field called Parts. Calculate it using Python in the Field Calculator to be: !Shape.PartCount! Shapes that enclose other shapes should have counts of 2 or more. Doughnut holes should have counts of 1 (as well as the numbers 1, 2, 3, 5, and 7). Select all of the features that have Part > 1. Then Select by Location on the layer itself using the feature selection with a very small buffer distance and the Intersect option. Now use the Select from Current Selection option of the Select by Attributes dialog to select Parts = 1 These should be all of the doughnut holes, but it could also include numbers from different labels that overlapped at map book boundaries or which were tightly packed together so that adjacent numbers touched. Reverse the selection and export that set of features to a new feature class (a non-destructive way of getting rid of the suspected doughnut holes, so you have the original to use for recovery of the kinds of overlaps that should not have been deleted). Review the results and restore any touched real text that should not have been deleted. You can use the original feature class with a different symbol color on the removed shapes, and also use a definition query of PARTS = 1 to only show single part features. Overlay that layer with the exported text. That should help you spot real text values that were accidentally removed due to the way they were touched by multipart numbers.
... View more
08-30-2013
12:50 PM
|
0
|
0
|
8284
|
|
POST
|
I was hoping ESRI or the forums contained attitional information. I also have a book that covers Python and the OBJECTID IN operator is not mentioned. The IN operatot is not a python expression. It is an SQL expression and it is fine to use with all of the databases and the only efficient way to work with lists of values in SQL. It is also fine to use with Python lists, since Python code that uses the IN expression will be found all over the Python forum by every advanced user of Python here. So ignore that recommendation for both SQL and Python. So use the IN operator as shown in my example or Jakes example (as corrected by me for the arcLength field test) and you will get the idea soon enough about what it does.
... View more
08-30-2013
12:21 PM
|
0
|
0
|
1637
|
|
POST
|
James, Here is tech article that discusses selecting multiple values: http://support.esri.com/en/knowledgebase/techarticles/detail/32024 Try the below. It should work whether you select one line or multiple lines: mxd = arcpy.mapping.MapDocument("CURRENT")
for lyr in arcpy.mapping.ListLayers(mxd):
dsc = arcpy.Describe(lyr)
sel_set = dsc.fidSet
if dsc.shapeType == "Polyline":
if len(sel_set) > 1:
sel_set = sel_set.replace(";", ",")
arcLengthList = []
shapeLengthList = []
rows = arcpy.SearchCursor(lyr, "OBJECTID IN (" + sel_set + ")")
for row in rows:
arcLengthList.append(row.ARCLENGTH)
shapeLengthList.append(row.shape.length)
i = 0
while i < len(arcLengthList):
if len(arcLengthList) > 1:
print arcLengthList
else:
print shapeLengthList
i += 1
else:
rows = arcpy.SearchCursor(lyr, "OBJECTID = " + sel_set)
for row in rows:
arcLength = row.ARCLENGTH
shapeLength = row.shape.length
if len(arcLength) > ' ':
print arcLength
else:
print shapeLength
del row, rows ArcLength is a string field with spaces, so the test will fail unless it converts the string to a number and tests for a space. IN works even if there are no listed object (nothing is selected but no error occurs), a single item, or a list of items, so the else clause is not necessary. = fails and produces an error if there is no listed objectID value or a list, so IN is all you need.
... View more
08-30-2013
12:17 PM
|
0
|
0
|
1637
|
|
POST
|
Richard, Can you point me in the direction to read up on the OBJECTID IN operator? It looks like I may need to select more than one Polyline at a time. Thanks ESRI has virtually nothing about it. It's a simple expression. All you need is the field name followed by the word IN and then a comma separated list of correctly typed values within a pair of parentheses. I already gave several examples. Any single value in the list that matches the value of the field for any given record will be included in the selection. You would need to output the python list as a comma separated list in one string. I believe this will work to convert a python list of numbers to a comma separated list: myList = [12,34,56,78,90] myString = ",".join(myList) and then you could make the where clause using the appropriate field delimiters for your database: '"OBJECTID" IN (' + myString + ')' In the case of your latest code, I think that the dsc.fidSet is already a string so I think you can use replace to substitute semicolons with commas: mxd = arcpy.mapping.MapDocument("CURRENT")
for lyr in arcpy.mapping.ListLayers(mxd):
dsc = arcpy.Describe(lyr)
sel_set = dsc.fidSet.replace(";",",")
if dsc.shapeType == "Polyline":
rows = arcpy.da.SearchCursor(lyr, ["OID@", "ARCLENGTH", "SHAPE@LENGTH"], "OBJECTID IN (" + sel_set + ")")
for row in rows:
arcLength = row.[1]
shapeLength = row.[2]
if arcLength > ' ':
print arcLength
else:
print shapeLength
del row, rows I changed it to a da cursor, since performance is about 10 times faster or more than the old cursor style. You would still need to replace the print methods with AddMessages and I indented the arcLength test so that each line feature will print. The test also will handle single digit arcLength values now that I know it is a string field (although you probably don't have any single digit values in the field).
... View more
08-30-2013
11:42 AM
|
0
|
0
|
1637
|
| Title | Kudos | Posted |
|---|---|---|
| 1 | 03-24-2026 11:37 PM | |
| 1 | 03-24-2026 08:01 PM | |
| 7 | 02-23-2026 08:34 AM | |
| 1 | 03-31-2025 03:25 PM | |
| 1 | 03-28-2025 06:54 PM |
| Online Status |
Offline
|
| Date Last Visited |
07-09-2026
12:59 AM
|