Split polygon and modify its attributes

878
3
Jump to solution
08-20-2019 12:44 AM
CarstenSchumann
Occasional Contributor

I´ve edited the CutTool-example from GitHub to also modify the created/changed features. 

his is my modified code:

var rowCursor = layer.Search(myGeometry, SpatialRelationship.Crosses);
var fc = layer.GetFeatureClass();
var fkzFieldIndex = fc.GetDefinition().FindField("FSK");
if (fkzFieldIndex == -1)
	return Task.FromResult(false);

int index = 0;

// add the feature IDs into our prepared list
while (rowCursor.MoveNext())
{
	var feature = (Feature) rowCursor.Current;
	var geomTest = feature.GetShape();
	if (geomTest != null)
	{
		// make sure we have the same projection for geomProjected and geomTest
		var geomProjected = GeometryEngine.Instance.Project(geometry, geomTest.SpatialReference);
		// we are looking for polygons are completely intersected by the cut line
		if (GeometryEngine.Instance.Relate(geomProjected, geomTest, "TT*F*****"))
		{
			// add the current feature to the overall list of features to cut
			oids.Add(rowCursor.Current.GetObjectID());
			cutOperation.Modify(rowCursor.Current, fkzFieldIndex, "MyNewFKZ");
		}
	}
}

// add the elements to cut into the edit operation
cutOperation.Split(layer, oids, geometry);
//execute the operation
var operationResult = cutOperation.Execute();

return Task.FromResult(operationResult);‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

So I have a list of oids of features that I want to assign new attributes and that I want to split afterwards. My feature is split, but it does not get the value "MyNewFKZ" assigned to the FKZ-field. Did I miss anything here? I can´t see how may code differs from the example.

Just an asside: I also subscribed to the RowCreatedEvent in order to set the FKZ for the newly created feature as well. The handler is appropriately called and the new feature gets the FKZ-field assigned. Uncommenting that handler however has no effect on the modified feature. 

0 Kudos
1 Solution

Accepted Solutions
CarstenSchumann
Occasional Contributor

I got it working by not using the Modify-operation, but just registering an OnChange-eventhandler when a row is modified:

RowChangedEvent.Subscribe(this.RowChanged, fc);

				
while (rowCursor.MoveNext())
{
	var feature = (Feature)rowCursor.Current;
	var geomTest = feature.GetShape();
	if (geomTest != null)
	{
		var geomProjected = GeometryEngine.Instance.Project(geometry, geomTest.SpatialReference);
		// we are looking for polygons that are completely intersected by the cut line
		if (GeometryEngine.Instance.Relate(geomProjected, geomTest, "TT*F*****"))
		{
			oids.Add(rowCursor.Current.GetObjectID());
		}
	}
}

cutOperation.Split(layer, oids, geometry);
var operationResult = cutOperation.Execute();

The RowChanged-method is this and is executed upon EditOperation.Execute

private void RowChanged(RowChangedEventArgs obj)
{
	if (m_CurrentRowChangedOid == obj.Row.GetObjectID())
		return;

	this.m_CurrentRowChangedOid = obj.Row.GetObjectID();
	obj.Row[obj.Row.GetTable().GetDefinition().FindField("FSK")] = "MyNewFsk";
}

However we have to unsubscribe from the event. Otherwise the handler is registered on every call to our tool.

View solution in original post

0 Kudos
3 Replies
CarstenSchumann
Occasional Contributor

I got it working by not using the Modify-operation, but just registering an OnChange-eventhandler when a row is modified:

RowChangedEvent.Subscribe(this.RowChanged, fc);

				
while (rowCursor.MoveNext())
{
	var feature = (Feature)rowCursor.Current;
	var geomTest = feature.GetShape();
	if (geomTest != null)
	{
		var geomProjected = GeometryEngine.Instance.Project(geometry, geomTest.SpatialReference);
		// we are looking for polygons that are completely intersected by the cut line
		if (GeometryEngine.Instance.Relate(geomProjected, geomTest, "TT*F*****"))
		{
			oids.Add(rowCursor.Current.GetObjectID());
		}
	}
}

cutOperation.Split(layer, oids, geometry);
var operationResult = cutOperation.Execute();

The RowChanged-method is this and is executed upon EditOperation.Execute

private void RowChanged(RowChangedEventArgs obj)
{
	if (m_CurrentRowChangedOid == obj.Row.GetObjectID())
		return;

	this.m_CurrentRowChangedOid = obj.Row.GetObjectID();
	obj.Row[obj.Row.GetTable().GetDefinition().FindField("FSK")] = "MyNewFsk";
}

However we have to unsubscribe from the event. Otherwise the handler is registered on every call to our tool.

0 Kudos
CharlesMacleod
Esri Regular Contributor

I suspect this is the root of your original problem:  

var rowCursor = layer.Search(myGeometry, SpatialRelationship.Crosses);

You are using a recycling cursor. Change to a non-recycling cursor (access this off the feature class). With a recycling cursor, repetitive calls to op.Modify with rowcursor.Current will get overwritten by the following "current" feature. (note: the last feature in your selection was probably getting successfully modified).

//This is a problem with a recycling cursor when in a loop.

cutOperation.Modify(rowCursor.Current, fkzFieldIndex, "MyNewFKZ");
0 Kudos
NarelleChedzey
Esri Contributor

Carsten, 

Thanks for posting this question.  We have found that there's a bug with using the EditOperation.Modify(Row ...) methods followed by other EditOperation methods.  We will be fixing this in the next version of the software.   

In the meantime, what you have determined is an acceptable workaround.  You could also implement the following without needing to subscribe to the RowChanged event.  There is no problem with the EditOperation.Modify(layer, oid, ... ) methods. 

while (rowCursor.MoveNext())
{
    var feature = (Feature)rowCursor.Current;
    var geomTest = feature.GetShape();
    if (geomTest != null)
    {
        var geomProjected = GeometryEngine.Instance.Project(geometry, geomTest.SpatialReference);
        // we are looking for polygons that are completely intersected by the cut line
        if (GeometryEngine.Instance.Relate(geomProjected, geomTest, "TT*F*****"))
        {
            oids.Add(rowCursor.Current.GetObjectID());
        }
    }
}

var atts = new Dictionary<string, object>();
atts.Add("FSK", "MyNewFKZ");

foreach (var oid in oids)
    cutOperation.Modify(layer, oid, atts);

cutOperation.Split(layer, oids, geometry);


var operationResult = cutOperation.Execute();

Thanks

Narelle

0 Kudos