|
POST
|
No code exists, except for the ideal situation. While I can imagine some other methods, there is no way to know for sure what the parcel shape is without deep learning AI that I don't know how to write. All I could do is solve the problem for the ideal situation and then come up with a way to determine if it worked and try another set of geoprocessing steps for the parcels that failed. That probably would involve weeks of trial and error to come up with a 95% to 99% solution. I don't have the time to do that. Python is not the issue, the issue is coming up with the sequence of geoprocessing steps and validation checks at each stage to identify the parcels that passed and failed the previous steps you applied and coming up with an alternative geoprocessing set of steps that fits the majority of the parcels that failed. No one knows all of those steps and validation checks for this problem. Python only makes it easier to apply the steps in the right order in a repeatable manner once you figure them out, but it cannot figure out what those steps are for you (without AI). AI will only get to a 90% to 99% solution at best as well, although the benefit is that it does the learning process and applies the solutions much quicker if you can come up with a way to train it. However, no set of automated logical solutions will ever reach 100%. 100% can only be achieved at some point by coming up with some way to identify candidates that you suspect didn't get solved by all of the steps you have already applied and inspecting and manually solving each one at some point, and even then somethings won't get caught.
... View more
07-16-2019
08:18 AM
|
2
|
1
|
3892
|
|
POST
|
Based on your map example, it is an ideal situation where the parcel is rectangular. If every parcel was rectangular and at the exact tangent angle to the street, the easiest method would be to create linear referenced routes with your centerlines. Then use Feature to Point with the inside option to extract the centroid of the parcel. Then you can use the Locate Features Along Routes tool to get the measure and distance of the point along the centerline with an adequate search radius. I usually get all events for all centerlines within the radius and eliminate events that have an address street name that does not match the centerline name. I summarize the point on the parcel field to get a count of events for each parcel to determine if more than one event was created along a curve in the centerline, since technically all points along a tangent radial curve to the centroid are valid events, and manually eliminate all but one of those points. An event layer can be created which displays an angle field and that layer can be exported to a real point feature class that will store the angle field values permanently. From the angle you can determine the compass bearing of the tangent line from the parcel centroid point to the centerline. You can also tell if the parcel is on the left or right hand side of the centerline, because the distance values are positive or negative depending on which side of the line the point is on. You can join the point to the parcel using the parcel number and calculate over the angle or compass direction.
... View more
07-16-2019
01:59 AM
|
2
|
3
|
3892
|
|
BLOG
|
Ultimately I did not use this approach, since I didn't find a way to make it work over really large areas, since the quality of the footprints is resolution dependent. Also, at that time Google only had footprints covering one or two of the 29 cities in my county and nothing in the unincorporated areas. However, I have been able to get building footprints for free from Microsoft through github. They used deep learning AI to create the footprints from 2014/2015 aerials for the entire US (and it looks like now they may have also done Canada based on google search results for Microsoft Building Footprints Github). The json files with the footprints did not import with the standard json import process of desktop, partially because the json format is not standard and partially because the California file was over 2 GB, so one of our administrators used ArcGIS FME to do the import. The quality of the footprints is very good. Unfortunately the documentation is limited and I have not seen anybody figure out how to access and apply the model to their own aerials, and Microsoft may never offer updates. However, being able to get over 800K footprints for my county for free has been a game changer for me.
... View more
07-03-2019
08:22 AM
|
0
|
0
|
5532
|
|
BLOG
|
The code was designed to compile a list of values, but it can be adjusted to list only a single value based on the maximum from a set of values. Basically line 26 and 30 in your code would change. You would have change line 26 to be an elif statement that compares the current date stored in the dictionary with the date of the relate row currently being processed and if it is, replace the value of the dictionary rather than append the value. Something like: elif relateDict[relateKey][0][1] < relateRow[1]:
# if the relate key is already in the dictionary
# and the current date is greater than the dictionary date
# replace the value associated with the key
relateDict[relateKey] = [relateRow[0:]]
I did not test the code, so I am not entirely sure I got the dictionary indexing right and I am not fully revamping the code to gain greater efficiency by eliminating the list within a list structure that is no longer really needed for the dictionary value, but this should give you the idea of how to adapt the logic to your needs.
... View more
06-13-2019
04:54 PM
|
0
|
0
|
18013
|
|
POST
|
There are a lot more real world zoning configurations where the largest zone is not in the center than you may realize, such as with natural feature zoning where a thin band of a water course zone happens to go through the exact center of a parcel, but overall that zone covers just a small portion of the parcel. Or in oddly shaped parcels like flag lots where the centroid does not fall in the parcel itself and the label point may be in the driveway, not in the heart of the parcel. The archery target example was just easy to describe and visualize as a situation where the centroid is not the best place to find the largest area. In any case, my method works regardless of how the zones are laid out in the parcel.
... View more
05-10-2019
11:24 AM
|
1
|
0
|
2650
|
|
POST
|
Using a Parcel centroid to determine the largest area is unreliable. For example, in a Parcel that had Zoning in shapes that resembled an Archery Target of concentric rings, the zone with the largest area is not in the bulls eye in the center, but in the outer most ring. I normally do this by using the Summary Statistics tool in the Analysis Tools->Statistics toolset. 1. I would use the Summary Statistics tool to Sum the Area field in the Statistics Fields section and add both the Parcel and Zoning fields in the Case Fields section. This gives you the true amount of total area for each zone when the same zone occurs on separate portions of the same parcel. 2. Then I run the Summary Statistics tool again on the output of the previous summary, and this time I get the MAX of the SUM_Shape_Area field in the Statistics Fields section and only add the Parcel field to the Case Fields section. 3. Then you can do a join of the first summary table as the target and the second summary table as the join table on the PARCEL field. In Model Builder you would first have to use the Make Table View tool in the Data Management Tools->Layers and Table Views toolset on the first summary table, then use the Add Join tool in the Data Management Tools->Joins toolset. 4. Select the records where the SUM_Shape_Area field is equal to or greater than the MAX_SUM_Shape_Area field using the Select Layer By Attribute tool in the Data Management Tools->Layers and Table Views toolset. 5. Use the Remove Join tool Data Management Tools->Joins toolset to break the Join you created in step 3. 6. Export those records to a new table so it only contains the one record with Zoning that had the greatest area for each Parcel. You could use the Copy Rows tool in the Data Management Tools->Tables toolset. 7. Join the original parcel and zoning layer (or just your parcel layer if it had a Zoning field you could calculate) as the target and the exported table as the join table on the Parcel field. In Model Builder you would first have to use the Make Feature Layer tool in the Data Management Tools->Layers and Table Views toolset on the feature class with the intersected parcels and zoning and then use the Add Join tool in the Data Management Tools->Joins toolset. 8. Use the Calculate Field tool in the Data Management Tools->Fields toolset to calculate the Zoning in your layer from the exported table. 9. Use the Remove Join tool Data Management Tools->Joins toolset to break the Join you created in step 7. 10. If you used the layer with parcels and zoning intersected as the target in step 7, you should use the Dissolve tool in the Data Management Tools->Generalization toolset on that layer with the Parcel and Zoning fields checked in the Dissolve Fields section to create a single shape for each Parcel that will have the Zoning that covered the largest area in that parcel.
... View more
05-10-2019
11:07 AM
|
2
|
1
|
2650
|
|
POST
|
It does not affect the attribute, only the label. If you used the same expression in the Field Calculation you would affect the attribute. Label and the field calculator expressions are often the same, but in the label expression you only affect the label.
... View more
03-28-2019
02:44 PM
|
1
|
1
|
3469
|
|
POST
|
You have to customize the label expression of the label class in the Recreation Site Points layer. If the layer only generates one label you could hard-code the text as "DEER CREEK CAMPGROUND". If you want the expression to replace "CG CAMPGROUND" with "CAMPGROUND" for many different campgrounds and your field name was NAME, in VB you could make the expression: REPLACE([NAME], "CG CAMPGROUND", "CAMPGROUND")
... View more
03-28-2019
08:45 AM
|
2
|
3
|
3469
|
|
POST
|
After your code sets the definition query you should print it to verify that it is the string you expected: print(stru.definitionQuery)
... View more
03-27-2019
09:54 AM
|
1
|
2
|
1320
|
|
POST
|
Good to know, but in several languages the use of multiple quotes together makes the quotation mark a literal character within a string and 3 pairs of quotation marks together would return a quoted string within a string equivalent to: '"a >= 10"' So given that your examples show that only the first pair of quotation marks is required in Python to get the desired output, I consider the use of more than one pair of quotations both unnecessary and potentially confusing to those familiar with other languages (as it was to me).
... View more
03-27-2019
09:36 AM
|
0
|
1
|
3214
|
|
POST
|
You have quoted the string wrong. Just use one pair of double quotes, not 3 pairs. Also, you may want to try using code to get the area field name instead of hard coding a name that only works for a specific database. something like the following should work sqft = arcpy.GetParameterAsText(2)
stru = m.listLayers('Structures')[0]
fc = stru.dataSource
desc = arcpy.Describe(fc)
areafieldname = desc.areaFieldName
stru.definitionQuery = "{} >= {}".format(arcpy.AddFieldDelimiters(stru, areafieldname), sqft)
... View more
03-27-2019
07:22 AM
|
0
|
1
|
3214
|
|
POST
|
Use the Intersecting Feature method of Attribute Assistant. It will transfer an attribute from an intersecting feature into your edited feature during an edit session. The attribute transfer can be triggered automatically by feature creation, attribute updates and/or geometry updates or else manually. The setup for this method involves updates to the DynamicValue table, which must be included within your map for Attribute Assistant to work, and the Attribute Assistant tool in the Attribute Assistant toolbar has to be active in your edit session. You can download Attribute Assistant from here.
... View more
03-13-2019
08:26 AM
|
1
|
1
|
1449
|
|
POST
|
I reread your code and noticed your data source is coming from SQL Server. So I modified my code to change the original SQL expression which was using a date format that is compatible with file geodatabases to make it compatible with SQL Server by changing SQL = "D_DATE > DATE '{}'".format(tMinus92.strftime('%Y-%m-%d %H:%M:%S')) to SQL = "D_DATE > '{}'".format(tMinus92.strftime('%Y-%m-%d %H:%M:%S'))
... View more
02-08-2019
03:42 PM
|
0
|
1
|
6856
|
|
POST
|
Having a SearchCursor and an InsertCursor or DeleteCursor operating simultaneously is a the most suspect part of your code that could lead to corrupt data. Whenever I deal with InsertCursor and DeleteCursor operations, I do all SearchCursor operations first to build an insert dictionary containing lists of field values of the data to be inserted that are designed to be compatible with requirements of the InsertCursor and a delete dictionary of all ObjectIDs to be deleted. Then I run a separate loop where only the InsertCursor is open and insert all of the new records from the items in the insert dictionary. Then I run a separate loop where only the DeleteCursor is open and delete the objectIDs that match the ObjectID keys of the delete dictionary.
... View more
02-08-2019
03:11 PM
|
0
|
0
|
1953
|
|
POST
|
Your loops are backwards. The SearchCursor is always on the outer loop and you must do all lookups only on the dictionary in the inner loop. This way you just go through the searchcursor rows once and don't get killed instatiating a new cursor for every value in your dictionary. Also dictionaries are specifically designed to optimize the performance of lookup operations. You should also apply a query to the SearchCursor to limit it to just records where the D_DATE > tMinus92. The D_DATE field should be an indexed field to improve the performance of creating a SearchCursor that applies a query on that field. I am not bothering to time one value, since now the entire table will be completed in seconds or minutes, depending on the size of the table. table = acDaily # This is a SQL Server database table of daily water volumes. There are ~1300 wells represented in the table, each with daily records covering several years.
fields = ['PROPNUM','D_DATE','WATER'] # PROPNUM is the unique identifier for each well in acDaily, D_DATE is the date of the daily volume, and WATER is the volume of produced water.
print strftime("%Y-%m-%d %H:%M:%S") # This is used to time the duration of the loop portion of the script.
#Build an SQL expression to limit D_DATE to within the past 92 days
SQL = "D_DATE > '{}'".format(tMinus92.strftime('%Y-%m-%d %H:%M:%S'))
# Use a search cursor to go through the records that are from the past 92 days in acDaily and if the PROPNUM matches the key in propNumDict, add the water volume value to the dictionary.
with arcpy.da.SearchCursor(table, fields, SQL) as cursor:
for row in cursor:
keyValue = row[0]
if keyValue in propNumDict:
# propNumDict was generated previously and start as an empty list prior to running the SearchCursor
propNumDict[keyValue].append(row[2])
print propNumDict
print strftime("%Y-%m-%d %H:%M:%S")
... View more
02-08-2019
02:52 PM
|
1
|
3
|
6856
|
| Title | Kudos | Posted |
|---|---|---|
| 1 | 03-24-2026 11:37 PM | |
| 1 | 03-24-2026 08:01 PM | |
| 6 | 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 |
a week ago
|