Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

I need some help to create a script.

Imagine that I'm using 3 shapes: 1 point and 2 polygons. When I create a new point I want it to assume some attributes of the polygons in which that point is inserted.

Any idea?

share|improve this question
add comment

5 Answers 5

Loop through your points (search cursor), then loop though you polygons (search cursor). Once you find the point is in the polygon (polygon.contains(point), then as you are already in the record of the polygon and point, just update by setting the attribute in the point, equal to the attribute you require from the polygon. simply then update the row in the point table, exit the polygon loop, then load the next point, etc.

If you can wait until monday, I can write some arcpy for you; it's very, very easy and I think I did the very same thing last week.

fcPnt = "C:\\Path\\to\\Point\\Data.sde\\PointDS"
fcPoly = "C:\\Path\\To\\Polygon\\Data.sde\\PolygonDS"
sSQL "Sql to sub select data for your points if you need to

pntcur = arcpy.UpdateCursor(fcPnt, sSQL)
# can also be pntcur = arcpy.SearchCursor(fcPnt) to select all points
for row in pntcur:
    #if you have access to the point x and y through column data, then use:
    geom = arcpy.Point(row.X,row.Y)
    #otherwise cast the shape to an arcpy point
    #geom = arcpy.Point(row.shape.extent.XMax,row.shape.extent.YMax)
    # or geom = arcpy.Point(row.GetPart()) as we know it is a point object, we dont need to reference the part number
    polycurs = arcpy.SearchCursor(fcPoly)
    for polyRow in polycurs:
        poly = polyRow.Shape
        if poly.contains(geom):
            row.SomeRow = polyRow.SomePolyRowData
            row.SomeOtherRow = polyRow.SomeOtherPolyRowData
            ...
            ...
        del polyRow
        del poly

    del polycurs
    pntcur.updateRow(row)
    del row

del pntcur

Or there, or there abouts!

share|improve this answer
    
Thank you.. it would be great –  Luis Almeida Apr 16 '12 at 10:24
    
There you go Luis Almeida –  Hairy Apr 17 '12 at 6:26
1  
@Hairy: Your script updates a polygon layer not points. The geom variable wont be created as you don't have access to X,Y directly. Use geom = row.Shape.getPart() instead. Moreover, the script may not be effective while many polygon as it loops through all polygons for each point. –  Marcin Apr 17 '12 at 10:05
    
@Marcin - Edited. There are 2 polygons, so, imo, performance is moot. Do you know you don't have access to the point? You should do, as you can cast the shape as a point, and access the x and y that way. The script wasn't meant as a fix, merely a pointer, I am sure the OP has enough nous to be able to edit it as he sees fit... –  Hairy Apr 17 '12 at 11:34
    
@Luis Almeida - There are some solutions here for you to try. Good luck –  Hairy Apr 18 '12 at 7:06
add comment

What you're trying to do is called a "point in polygon" search.

Python

I'm guessing you're trying to script it using python given your tag. A google search for python "point in polygon" should give you a good start. A top result I get is this page which looks like it may be adaptable to do what you want: http://www.heikkitoivonen.net/blog/2009/01/26/point-in-polygon-in-python/

Spatial Database

Alternately you can offload the processing to a spatial database, i.e. spatialLite. You store your polygons in there and then when a new point is created you use some SQL to get the attributes for whichever polygons its within. https://code.google.com/p/xenia/wiki/SpatialLite - has a little more information

Python Libaries There are also some python GIS libraries out there which could allow you to offload it to them rather than roll your own. Unfortunately I don't know any of their names. :-S

share|improve this answer
add comment

I'm not sure that that is possible, or the best way to approach the problem. I would imagine a better way is to create all the points first, or load them into your GIS somehow, and then update the desired fields in the points shape based on which polygon they are in, which is very possible in most GIS software, including open-source.

State the software you intend to you use if you need more pointers.

share|improve this answer
add comment

How about:

  1. Select by location -> point(s) contained by polygon.
  2. SearchCursor(polygonFeatureClass) -> store values of attributes in
  3. variables Insert/UpdateCursor(pointFeatureClass) -> update attribute with stored values
share|improve this answer
add comment

In ArcGIS you can simply use Spatial Join or Identity (ArcInfo only) to join attributes from one layer to another. Both tools will create new point layer.


If you don't want create new layer and have greater control on selection method, here's the script similar to @Hairy's script but uses Feature Layers and Select By Location:

import arcpy
arcpy.env.overwriteOutput = True

#adapt the following variabled to your data:
polygonLayer = r"C:\tmp\Test.gdb\Polygons"
pointLayer = r"C:\tmp\Test.gdb\Points"
copyField = "FieldNameToCopy"


#add new field to target feature class if it don't exists (you can delete it if you plan to create field manually)
fieldList = arcpy.ListFields(pointLayer)
fieldNameList = []
for field in fieldList:
    fieldNameList.append(field.name)
fieldType = arcpy.ListFields(polygonLayer,copyField)[0].type
if not copyField in fieldNameList:
    arcpy.AddField_management(pointLayer, copyField, fieldType)

arcpy.MakeFeatureLayer_management(polygonLayer, "PolygonLayer")

pntCursor = arcpy.UpdateCursor(pointLayer)
for pnt in pntCursor:
    rowID = pnt.OBJECTID
    arcpy.MakeFeatureLayer_management(pointLayer, "PointLayer", '"OBJECTID" = ' + str(rowID))

    #polygon selection based on CONTAINS selection method
    arcpy.SelectLayerByLocation_management("PolygonLayer", "CONTAINS", "PointLayer")

    #copy field values from polygon to point layer    
    polyCursor = arcpy.SearchCursor("PolygonLayer")        
    for poly in polyCursor:
        pnt.setValue(copyField, poly.getValue(copyField))
        pntCursor.updateRow(pnt)

    arcpy.Delete_management("PointLayer")        

del pntCursor, polyCursor, pnt, poly
share|improve this answer
    
Seems a bit convoluted to be creating layers and having to delete them and is a longer way to do what I have suggested. This would take a lot longer than the solution I have proposed too. –  Hairy Apr 18 '12 at 7:05
    
The solution is basen on exercise from PennState: e-education.psu.edu/geog485/node/159. Moreover, On the first place I proposed two ArcGIS tools which do not require any scripting! –  Marcin Apr 18 '12 at 7:25
    
@Hairy: I think your criticism is unmerited. I've made some tests: 17 random points, 170k polygons in FGDB. Your code ~13min, my ~0.5min. I suppose that avoid looping through polygon layer several times makes the difference. –  Marcin Apr 18 '12 at 8:47
    
there are two polygons, not 170,000. @Marcin If you are running the test properly, you would reverse the numbers, it is why I built the code this way. Yours is too complex for what is a very simple job. I may also add the reference to using ArcInfo tools, which people may not have. I guess it is you who has marked me down too. Hey ho. –  Hairy Apr 18 '12 at 9:41
    
@Hairy: I understood that there're 2 polygon layers, each with more than 2 polygons - for 2 polygon features ther's no sense to use any tool beyond Idetify:) But I agree that for simpler geometries your code is more clear. –  Marcin Apr 18 '12 at 10:13
show 1 more comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.