Skip to main content
Question

Remove specific vertex from feature


jdh
Contributor
Forum|alt.badge.img+28
  • Contributor

Hi,

I was just presented with a scenario where there are bunch of polygons, and some points, and requested to remove any polygon vertex that coincides with a point.

 

 

I initially thought about using the VertexCreator's Replace point at Index, but it turns out that the index can't be set to an attribute.

 

 

Is there a better alternative than chopping everything into points, filtering out the bad ones and then reconstructing the perimeter and rebuilding the area?

8 replies

itay
Supporter
Forum|alt.badge.img+17
  • Supporter
  • October 14, 2016

Hi @jdh, if you eventually need to remove the vertex, how will you go about it without breaking up the polygon?


jdh
Contributor
Forum|alt.badge.img+28
  • Author
  • Contributor
  • October 14, 2016
itay wrote:

Hi @jdh, if you eventually need to remove the vertex, how will you go about it without breaking up the polygon?

Since there are several thousand polygons, some of which are quite complex, I'm looking for a solution that works on the polygons individually, rather than the blocking explode/reconstruct option.

 

What I had hoped to do, was identify the index of the vertex to remove, use the VertexCreator Replace Point at Index to set it to NaN and then the GeometryValidator to remove the NaN.

 

 


itay
Supporter
Forum|alt.badge.img+17
  • Supporter
  • October 14, 2016
jdh wrote:
Since there are several thousand polygons, some of which are quite complex, I'm looking for a solution that works on the polygons individually, rather than the blocking explode/reconstruct option.

 

What I had hoped to do, was identify the index of the vertex to remove, use the VertexCreator Replace Point at Index to set it to NaN and then the GeometryValidator to remove the NaN.

 

 

very nifty, but if you do match the index how are you going to use it in the VertexCreator? it only accepts parameter values or direct input, so an attribute value wont help....

 

 


jdh
Contributor
Forum|alt.badge.img+28
  • Author
  • Contributor
  • October 14, 2016
itay wrote:
very nifty, but if you do match the index how are you going to use it in the VertexCreator? it only accepts parameter values or direct input, so an attribute value wont help....

 

 

The was my road block, and why I posted the question, hoping someone else has a brilliant solution.

 

 


takashi
Influencer
  • October 15, 2016

Hi @jdh, I have no ideas except PythonCaller scripting.

import fme
import fmeobjects

class FeatureProcessor(object):
    def __init__(self):
        self.points = []
        self.polygons = []
        
    def input(self, feature):
        geomType = feature.getGeometryType()
        if geomType == fmeobjects.FME_GEOM_POINT:
            self.points.append(feature)
        elif geomType == fmeobjects.FME_GEOM_POLYGON:
            self.polygons.append(feature)
            
    def close(self):
        points = set([p.getCoordinate(0for p in self.points])
        for polygon in self.polygons:
            vertices = polygon.getAllCoordinates()
            vertices = [p for p in vertices if p not in points]
            if vertices[0] != vertices[-1]:
                vertices.append(vertices[0])
            boundary = fmeobjects.FMELine(vertices)
            polygon.setGeometry(fmeobjects.FMEPolygon(boundary))
            self.pyoutput(polygon)
If it's guaranteed that all the points are input before the first polygon, you can modify the script so that the "input" method processes one by one whenever it receives a polygon feature.Depending on the data condition, it might be necessary to snap each point to the closest polygon vertex beforehand, in order to absorb a tolerance between them, like this.

0684Q00000ArLI4QAN.png


jdh
Contributor
Forum|alt.badge.img+28
  • Author
  • Contributor
  • October 17, 2016
takashi wrote:

Hi @jdh, I have no ideas except PythonCaller scripting.

import fme
import fmeobjects

class FeatureProcessor(object):
    def __init__(self):
        self.points = []
        self.polygons = []
        
    def input(self, feature):
        geomType = feature.getGeometryType()
        if geomType == fmeobjects.FME_GEOM_POINT:
            self.points.append(feature)
        elif geomType == fmeobjects.FME_GEOM_POLYGON:
            self.polygons.append(feature)
            
    def close(self):
        points = set([p.getCoordinate(0for p in self.points])
        for polygon in self.polygons:
            vertices = polygon.getAllCoordinates()
            vertices = [p for p in vertices if p not in points]
            if vertices[0] != vertices[-1]:
                vertices.append(vertices[0])
            boundary = fmeobjects.FMELine(vertices)
            polygon.setGeometry(fmeobjects.FMEPolygon(boundary))
            self.pyoutput(polygon)
If it's guaranteed that all the points are input before the first polygon, you can modify the script so that the "input" method processes one by one whenever it receives a polygon feature.Depending on the data condition, it might be necessary to snap each point to the closest polygon vertex beforehand, in order to absorb a tolerance between them, like this.

0684Q00000ArLI4QAN.png

Thanks takashi.  I've passed this on to my team.

Forum|alt.badge.img
  • October 17, 2016

You ca also use python factory in a python caller and be able to use the VertexCreatorFactory.

Please refer to the answer to this question to see how to do it.

Your factory string will look like this:

FACTORY_DEF * VertexCreatorFactory                                     \
   FACTORY_NAME VertexCreator                                          \
   INPUT  FEATURE_TYPE Input_Port                                      \
   MODE REPLACE_AT_INDEX                                               \
   INDEX <index>                                                       \
   CONTINUE_ON_ERROR YES                                               \
   XVAL "<x>"                                                          \
   YVAL "<y>"                                                          \
   ZVAL "<z>"                                                          \
   OUTPUT OUTPUT FEATURE_TYPE VertexCreator_OUTPUT

You'll have to dynamically replace the <index> by the value of the attribute value holding your point index to replace and <x>, <y> and <z> by the coordinates values.

Regards,

Larry


jdh
Contributor
Forum|alt.badge.img+28
  • Author
  • Contributor
  • October 17, 2016
larry wrote:

You ca also use python factory in a python caller and be able to use the VertexCreatorFactory.

Please refer to the answer to this question to see how to do it.

Your factory string will look like this:

FACTORY_DEF * VertexCreatorFactory                                     \
   FACTORY_NAME VertexCreator                                          \
   INPUT  FEATURE_TYPE Input_Port                                      \
   MODE REPLACE_AT_INDEX                                               \
   INDEX <index>                                                       \
   CONTINUE_ON_ERROR YES                                               \
   XVAL "<x>"                                                          \
   YVAL "<y>"                                                          \
   ZVAL "<z>"                                                          \
   OUTPUT OUTPUT FEATURE_TYPE VertexCreator_OUTPUT

You'll have to dynamically replace the <index> by the value of the attribute value holding your point index to replace and <x>, <y> and <z> by the coordinates values.

Regards,

Larry

Hi @larry,

 

 

That's a good workaround to the initial problem of the VertexCreator not accepting attributes.   I was able to get it functioning with a little help from @DaveAtSafe.   We'll have to run some tests to see if this solution is more or less efficient than @takashi's.

Cookie policy

We use cookies to enhance and personalize your experience. If you accept you agree to our full cookie policy. Learn more about our cookies.

 
Cookie settings