Solved

lines to arcs


Badge +6

Hi Guys,

 

another question....i want to do that for myself but i didnt find out which transformer i should use.

I want to create arcs (thick line) where to lines come together (thin lines ) by radius params which are in a excel sheet..

 

 

Thanks
icon

Best answer by takashi 19 June 2015, 15:20

View original

24 replies

Badge +6
Hi Guys,

 

means i want place an inside arc everywhere with a fixed radius
Userlevel 5
Hi

 

 

I'm not quite sure I understand your question, but if you need to create arcs based on radius etc, then look at the 2DArcReplacer.

 

 

David
Badge +6
i have a route with vertices...in microstation there is a function which is called Circular fillet....means where two lines come together in an anglepoint both lines where curved by a certain radius...

 

Also complicate explanation or?
Badge +6

here a screenshot ....

 

 

red line with vertices and angles.......blue line the arc with a certain radius!
Badge +3
You want to create continous radius fillets (a piece of a circle..) and be in control of the radius.

 

 

There are a number of ways of doing that.

 

 

Make a network of lines to acquire id and relationships between lines (wich lines do touch/intersect at an angle) . (or use spatialrelator to do that)

 

 

With 2 lines you can create the centerline (line with equal distance to both). On this the circle must reside.

 

This is basic math, so relatively easy to accomplish. These parametric values  u can enter in a 2dArcCreator with radius as  a manual inputparameter.

 

 

Or you can just go and set up the calculation for equal distance to both the lines, after you have extracted their parametric descirption. And create the fillet circle and cut it with the lines.

 

 

 

 

 
Badge +6

Hi Gio,

 

thats seems clear for me:

But i want to do it on the complete route and i have always the same radius....so it is another way or...or what transformers i have to use in which order?

How i can calculate something as start or end of the angle which i need to put in the 2DARCReplacer?

Thx

Franco

Userlevel 3
Badge +17
Hi Franco,

 

 

IHi Franco,

 

 

It's possible to calculate parameter values for the 2DArcReplacer, but it would be a little bit complex. I think it's easier to create an arc from 3 points using a script.

 

I wrote a script example. Assuming that the input feature has attributes storing:

 

- the radius of required arc: "_radius"

 

- the coordinates of 3 vertices of the bended line. start: (_x0, _y0), middle: (_x1, _y1), end: (_x2, _y2).

 

-----

 

# Script Example for PythonCaller

 

import fme, fmeobjects, math

 

 

class ArcReplacer(object):

 

    def __init__(self):

 

        self.logger = fmeobjects.FMELogFile()

 

        

 

    def input(self,feature):

 

        radius = float(feature.getAttribute('_radius'))

 

        x0, y0 = float(feature.getAttribute('_x0')), float(feature.getAttribute('_y0'))

 

        x1, y1 = float(feature.getAttribute('_x1')), float(feature.getAttribute('_y1'))

 

        x2, y2 = float(feature.getAttribute('_x2')), float(feature.getAttribute('_y2'))

 

        

 

        # Calculate vectors of the 2 line segments (start node -> end node).

 

        ax, ay = x1 - x0, y1 - y0

 

        bx, by = x2 - x1, y2 - y1

 

        len0, len1 = math.hypot(ax, ay), math.hypot(bx, by) # lengths of them

 

        

 

        # If a length is nearly equal to zero, arc cannot be created.

 

        if len0 < 1.0e-8 or len1 < 1.0e-8:

 

            self.logger.logMessageString('Warning: Arc cannot be created', fmeobjects.FME_WARN)

 

            return

 

        

 

        # Convert the vectors to unit vectors and calculate cross product of them.

 

        ax, ay = ax / len0, ay / len0

 

        bx, by = bx / len1, by / len1

 

        cross = ax * by - ay * bx # cross product

 

        

 

        # If the two lines on the same straight line, arc cannot be created.

 

        if abs(cross) < 1.0e-8:

 

           self.logger.logMessageString('Warning: Arc cannot be created', fmeobjects.FME_WARN)

 

           return

 

        

 

        # Calculate distance between the middle vertex and start/end point of the arc.

 

        angle = math.radians(180) - abs(math.asin(cross))

 

        d = radius / math.tan(angle * 0.5)

 

        

 

        # Create FMEPoint objects for start and end points of the arc.

 

        xs, ys = x1 - ax * d, y1 - ay * d

 

        xe, ye = x1 + bx * d, y1 + by * d

 

        start = fmeobjects.FMEPoint(xs, ys)

 

        end = fmeobjects.FMEPoint(xe, ye)

 

        

 

        # Create FMEPoint object for middle point on the arc.

 

        nx, ny = (-ay, ax) if 0 < cross else (ay, -ax) # normal vector: start -> center of the arc

 

        xc, yc = xs + nx * radius, ys + ny * radius # center of the arc

 

        distance = math.hypot(x1 - xc, y1 - yc) # distance between center and middle vertex

 

        ux, uy = (x1 - xc) / distance, (y1 - yc) / distance # unit vector: center -> middle vertex

 

        middle = fmeobjects.FMEPoint(xc + ux * radius, yc + uy * radius)

 

        

 

        # Create FMEArc object from the 3 points, set the arc to the feature and output it.

 

        arc = fmeobjects.FMEArc((start, middle, end))

 

        feature.setGeometry(arc)

 

        self.pyoutput(feature)

 

-----

 

 

Result

 

 

 

Takashi
Userlevel 3
Badge +17
Sorry, the script did not support the case that the angle of the bending is acute.

 

This is the upgraded version.

 

-----

 

# Script Example for PythonCaller ver.2

 

import fme, fmeobjects, math

 

 

class ArcReplacer(object):

 

    def __init__(self):

 

        self.logger = fmeobjects.FMELogFile()

 

        

 

    def input(self,feature):

 

        radius = float(feature.getAttribute('_radius'))

 

        x0, y0 = float(feature.getAttribute('_x0')), float(feature.getAttribute('_y0'))

 

        x1, y1 = float(feature.getAttribute('_x1')), float(feature.getAttribute('_y1'))

 

        x2, y2 = float(feature.getAttribute('_x2')), float(feature.getAttribute('_y2'))

 

        

 

        # Calculate vectors of the 2 line segments (start node -> end node).

 

        ax, ay = x1 - x0, y1 - y0

 

        bx, by = x2 - x1, y2 - y1

 

        len0, len1 = math.hypot(ax, ay), math.hypot(bx, by) # lengths of them

 

        

 

        # If a length is nearly equal to zero, arc cannot be created.

 

        if len0 < 1.0e-8 or len1 < 1.0e-8:

 

            self.logger.logMessageString('Warning: Arc cannot be created', fmeobjects.FME_WARN)

 

            return

 

        

 

        # Convert the vectors to unit vectors and calculate cross/dot product of them.

 

        ax, ay = ax / len0, ay / len0

 

        bx, by = bx / len1, by / len1

 

        cross = ax * by - ay * bx # cross product

 

        dot = ax * bx + ay * by # ver.2: dot product

 

        

 

        # If the two lines on the same straight line, arc cannot be created.

 

        if abs(cross) < 1.0e-8:

 

           self.logger.logMessageString('Warning: Arc cannot be created', fmeobjects.FME_WARN)

 

           return

 

        

 

        # Calculate distance between the middle vertex and start/end point of the arc.

 

        # ver.2: updated to support acute angle.

 

        angle = math.radians(180) - abs(math.asin(cross)) if 0 < dot else abs(math.asin(cross))

 

        d = radius / math.tan(angle * 0.5)

 

        

 

        # Create FMEPoint objects for start and end points of the arc.

 

        xs, ys = x1 - ax * d, y1 - ay * d

 

        xe, ye = x1 + bx * d, y1 + by * d

 

        start = fmeobjects.FMEPoint(xs, ys)

 

        end = fmeobjects.FMEPoint(xe, ye)

 

        

 

        # Create FMEPoint object for middle point on the arc.

 

        nx, ny = (-ay, ax) if 0 < cross else (ay, -ax) # normal vector: start -> center of the arc

 

        xc, yc = xs + nx * radius, ys + ny * radius # center of the arc

 

        distance = math.hypot(x1 - xc, y1 - yc) # distance between center and middle vertex

 

        ux, uy = (x1 - xc) / distance, (y1 - yc) / distance # unit vector: center -> middle vertex

 

        middle = fmeobjects.FMEPoint(xc + ux * radius, yc + uy * radius)

 

        

 

        # Create FMEArc object from the 3 points, set the arc to the feature and output it.

 

        arc = fmeobjects.FMEArc((start, middle, end))

 

        feature.setGeometry(arc)

 

        self.pyoutput(feature)

 

-----
Badge +6

Hi Takashi,

yeah it looks very complex....i will try it but befor ethat one question....from which line the attributes should be stored in an attribute? from the lines between the vertices? e.g. i have a route with 125 segments.....the script need coordinates (start, middle, end) from each segment?

Thx

Franco

Userlevel 3
Badge +17
This is a workspace for testing the script. If you send polyline(s) to this workflow, the PythonCaller with the script creates arcs for each bending location.

 

 

 

Counter: Add temporary ID attribute ("_count") to the input polyline.

 

Chopper: Decompose the polyline into individual line segments.

 

CoordinateExtractor: Extract the coordinates of start and end nodes. (x0, y0), (x1, y1)

 

AttributeCreator: Extract the coordinate of end node of the next segment (x2, y2), and also save its ID.

 

Tester: Discard the last segment in a original polyline.
Userlevel 3
Badge +17
oops, forgot. Add another attribute storing the radius.
Badge +6

 

Tester(TestFactory): Tested 107 input feature(s) -- 0 feature(s) passed and 107 feature(s) failedTester_PASSED Feature Counter -1 19(TeeFactory): Cloned 0 input feature(s) into 0 output feature(s)

 

 

PythonFactory failed to load python symbol `FeatureProcessor'

 

 

PythonFactory failed to close properly

 

 

f_365(PythonFactory): A fatal error has occurred. Check the logfile above for details
Userlevel 3
Badge +17
Specify the class name ("AreaReplacer") to the "Class or Function to Process Features" parameter of the PythonCaller...
Badge +6

you mean 2DArcReplacer or? even then the error mesage is like

 

FME API version of module 'LogCount_func' matches current internal version (3.7 20150407)Creating writer for format: FME Feature Store (FFS)

 

 

FME Configuration: No destination coordinate system set

 

 

FME API version of module 'NULL' matches current internal version (3.7 20150407)

 

 

FME API version of module 'NULL' matches current internal version (3.7 20150407)

 

 

Loaded module 'PythonFactory' from file 'C:\\Program Files (x86)\\FME\\plugins/PythonFactory.dll'

 

 

FME API version of module 'PythonFactory' matches current internal version (3.7 20150407)

 

 

Using FME's provided Python interpreter from C:\\Program Files (x86)\\FME\\fmepython27\\python27.dll

 

 

Python version 2.7 successfully loaded

 

 

Adding folder `C:\\Private\\FME_PRÄS\\fme\\' to the python path

 

 

Shape Reader: Bounding box of shapefile `I:\\ATVIN\\GIS\\H258\\6_CAE\\60_GIS\\602_gis\\6023_vector\\ATRUSH_FEEDER_LINE_140610' is: (349704.1614,4055164.2696),(367406.5278,4081335.4541)

 

 

Shape Reader: Bounding box of shapefile(s) selected from folder `I:\\ATVIN\\GIS\\H258\\6_CAE\\60_GIS\\602_gis\\6023_vector/' is: (349704.1614,4055164.2696),(367406.5278,4081335.4541)

 

 

PythonFactory failed to load python symbol `2DArcReplacer'

 

 

Factory proxy not initialized

 

 

PythonFactory failed to process feature

 

 

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

 

 

Feature output statistics for `FFS' writer using keyword `W_1':

 

 

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

 

 

Features Written

 

 

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

 

 

==============================================================================

 

 

Total Features Written 0

 

 

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

 

 

A fatal error has occurred. Check the logfile above for details
Userlevel 3
Badge +17
No. "ArcReplacer" is the class name that I defined in the script.

 

---

 

# Script Example for PythonCaller ver.2

 

import fme, fmeobjects, math

 

 

class ArcReplacer(object):  <== This is it!
Badge +6

Ok...I'm not so familiar with Python..so another shot

 

Python Exception <TypeError>: float() argument must be a string or a numberTraceback (most recent call last):

 

 

File "<string>", line 10, in input

 

 

TypeError: float() argument must be a string or a number

 

 

Error encountered while calling method `input'

 

 

PythonFactory failed to process feature

 

 

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

 

 

Feature output statistics for `FFS' writer using keyword `W_1':

 

 

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

 

 

Features Written

 

 

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

 

 

==============================================================================

 

 

Total Features Written 0

 

Userlevel 3
Badge +17
Check if all the attribute names (_radius, _x0, _y0, _x1, _y1, _x2, _y2) are correct.
Userlevel 3
Badge +17
I saved the test workspace here. (https://drive.google.com/file/d/0B0ufVP2t0eApQVFWQnJET3lweGs/view?usp=sharing)

 

FYI.
Badge +2
Hi Takashi,

 

 

Even I was also trying for fillet.

 

Is it possible to provide the workbench in lower version? else please provide the screenshot of the workbech.

 

 

Thank you

 

 

 
Badge +2
Will this script will do fillet (to given radius) with 2 differnet lines?
Userlevel 3
Badge +17
Hi Pratap,

 

 

This is FME 2013 SP4+ version. (https://drive.google.com/file/d/0B0ufVP2t0eApQ3JEQlhGUHJNTzA/view?usp=sharing)

 

The script creates arcs based on a given radius and a polyline, like this image.

 

 

 

Takashi
Badge +2
Thank you Takashi.
Userlevel 3
Badge +17
I'm not sure what the "fillet" function is. If the function means inserting an arc between the two adjoining line segments to smooth the bending point, I think that the script which performs that can be developed by improving my script.
Userlevel 3
Badge +17
Is this your required result?

 

 

 

The demo workspace is here. (https://drive.google.com/file/d/0B0ufVP2t0eApSWZWdENXNkRWSTQ/view?usp=sharing)

Reply