Question

create spline - Python


Badge

Bonjour

je cherche a créer un spline a partir d'une série de point

suivant l'exemple ci dessous (je cherche a créer la ligne verte)

qui doit passer par les points

j'ai bien essayé avec un Generalizer mais les algorithmes génèrent des lignes qui ne passent par les points

(ou je n'ai pas les bons paramètres ?)

je voudrais essayer avec des fonction Python et un PythonCaller

avec en entrée un tableau des 6 points et en sortie en semi de points représentant ce Spline

Mais je ne connais pas suffisamment l’interpréteur Python Caller

je suis preneur d'idées et d'exemples

 

Merci a tous!


10 replies

Badge +15

Correct me if i'm wrong but in english you ask:

 

I want to create the green line in the example picture based on the points of the black line. I tried to use the Generalizer but the green line won't go through the points of the black line.

My next choice to solve the problem is the PythonCaller Transformer. But I don't know enough about this transformer, so I'm stuck.

 

To answer:

What are the options you tried? You ask if the settings of the Generalizer are correct, but you don't show the setting. Do you have a Python script that creates Splines? If so, then tell what parameters the script needs. And what is the output of this script.

Badge +22

Vous pouvez essayer le code python dans l'example ici: https://knowledge.safe.com/questions/2706/create-cubic-bezier-curves.html

Le generalizer option Nurbfit utilise un algorithm B-spline qui prend seulement les points de debut et fin comme control, mais passe pas sur tous les points interiors, n'importe le degre polynôme.

 

Badge

avec le Generalizer le plus proche que j'ai trouvé c'est avec NURBfit (smooth)

en rouge, mais ça ne me convient pas comme la courbe ne passe pas par les sommets

en cherchant des exemples python voila ce que j'ai trouve

avec le resultat que je voudrais obtenir (cubic)

par exemple la fonction spicy.interpolate

mais je ne sais pas la mettre en oeuvre dans pythoncaller

 

 

merci !!!

Badge +15

This is the code used at:

Knowledge Base Question: create-cubic-bezier-curves

import fmeobjects
class CubicBezierCurveReplacer(object):
      def __init__(self):
            self.set_coefficients(32)
            
      def set_coefficients(self, n):
            self.n = n
            r = 1.0 / float(self.n)
            s = range(0, self.n)
            self.k0 = [(1.0 - (r * m))**3 for m in s]
            self.k1 = [3.0 * (r * m) * (1.0 - r * m)**2 for m in s]
            self.k2 = [3.0 * (1.0 - (r * m)) * (r * m)**2 for m in s]
            self.k3 = [(r * m)**3 for m in s]
      def bezier_coords(self, p):
            coords = []
            x0, x1, x2, x3 = p[0][0], p[1][0], p[2][0], p[3][0]
            y0, y1, y2, y3 = p[0][1], p[1][1], p[2][1], p[3][1]

            for i in range(1, self.n):
                  x = self.k0[i] * x0 + self.k1[i] * x1 + self.k2[i] * x2 + self.k3[i] * x3
                  y = self.k0[i] * y0 + self.k1[i] * y1 + self.k2[i] * y2 + self.k3[i] * y3
                  coords.append((x, y))
            return coords
      def input(self, feature):
# If the number of coordinates is less than 2, return nothing.
            if feature.numCoords() < 2: return
# Get all coordinates of the input feature as control points.
            points = feature.getAllCoordinates()
# Append coordinates while (number of control points - 1)
# is not divisible by 3 evenly.
            while (len(points) - 1) % 3 != 0:
                  points.append(points[-1])
# Create   cubic Bezier curves.
            bezier = feature.cloneAttributes();
            bezier.setGeometryType(fmeobjects.FME_GEOM_LINE)
            bezier.setCoordSys(feature.getCoordSys())
            bezier.addCoordinate(points[0][0], points[0][1])
            for i in range(3, len(points), 3):
                  bezier.addCoordinates(self.bezier_coords(points[i - 3 : i + 1]))
                  bezier.addCoordinate(points[i][0], points[i][1])
            self.pyoutput(bezier)
      def close(self):
            pass

Settings of the PythonCaller:

PythonCaller [PythonCaller Version 4]
Parameters:
        Python Script: 
                ...
        Class or Function to Process Features: CubicBezierCurveReplacer
Advanced:
        Attributes to Expose: 
        Attributes To Hide: <not set>
        Lists to Hide: <not set>

 

Badge

This is the code used at:

Knowledge Base Question: create-cubic-bezier-curves

import fmeobjects
class CubicBezierCurveReplacer(object):
      def __init__(self):
            self.set_coefficients(32)
            
      def set_coefficients(self, n):
            self.n = n
            r = 1.0 / float(self.n)
            s = range(0, self.n)
            self.k0 = [(1.0 - (r * m))**3 for m in s]
            self.k1 = [3.0 * (r * m) * (1.0 - r * m)**2 for m in s]
            self.k2 = [3.0 * (1.0 - (r * m)) * (r * m)**2 for m in s]
            self.k3 = [(r * m)**3 for m in s]
      def bezier_coords(self, p):
            coords = []
            x0, x1, x2, x3 = p[0][0], p[1][0], p[2][0], p[3][0]
            y0, y1, y2, y3 = p[0][1], p[1][1], p[2][1], p[3][1]

            for i in range(1, self.n):
                  x = self.k0[i] * x0 + self.k1[i] * x1 + self.k2[i] * x2 + self.k3[i] * x3
                  y = self.k0[i] * y0 + self.k1[i] * y1 + self.k2[i] * y2 + self.k3[i] * y3
                  coords.append((x, y))
            return coords
      def input(self, feature):
# If the number of coordinates is less than 2, return nothing.
            if feature.numCoords() < 2: return
# Get all coordinates of the input feature as control points.
            points = feature.getAllCoordinates()
# Append coordinates while (number of control points - 1)
# is not divisible by 3 evenly.
            while (len(points) - 1) % 3 != 0:
                  points.append(points[-1])
# Create   cubic Bezier curves.
            bezier = feature.cloneAttributes();
            bezier.setGeometryType(fmeobjects.FME_GEOM_LINE)
            bezier.setCoordSys(feature.getCoordSys())
            bezier.addCoordinate(points[0][0], points[0][1])
            for i in range(3, len(points), 3):
                  bezier.addCoordinates(self.bezier_coords(points[i - 3 : i + 1]))
                  bezier.addCoordinate(points[i][0], points[i][1])
            self.pyoutput(bezier)
      def close(self):
            pass

Settings of the PythonCaller:

PythonCaller [PythonCaller Version 4]
Parameters:
        Python Script: 
                ...
        Class or Function to Process Features: CubicBezierCurveReplacer
Advanced:
        Attributes to Expose: 
        Attributes To Hide: <not set>
        Lists to Hide: <not set>

 

Merci

c'est une bonne approche

mais la courbe ne passe par les points peut on jouer sur les paramètres ?

 

0684Q00000ArMmQQAV.jpgen vert le resultat recherché, en rouge le resultat obtenu avec le script Python

il y a t'il un moyen de debugger les lignes de code avec fme pour comprendre le fonctionnement de ce script ?

 

merci beaucoup

 

 

Badge +22

Merci

c'est une bonne approche

mais la courbe ne passe par les points peut on jouer sur les paramètres ?

 

0684Q00000ArMmQQAV.jpgen vert le resultat recherché, en rouge le resultat obtenu avec le script Python

il y a t'il un moyen de debugger les lignes de code avec fme pour comprendre le fonctionnement de ce script ?

 

merci beaucoup

 

 

La scripte tel-que prends chaque troisieme point comme controle.

 

 

Il me semble qu'il y a pleusieurs modifications a faire pour utiliser tous les points comme controle, mais je ne sais pas assais l'algorithme.

 

 

Probablement:

 

 

31. while (len(points) - 1) % 3 != 0:
38.  for i in range(3, len(points), 3):
       bezier.addCoordinates(self.bezier_coords(points[i - 3 : i + 1]))                    bezier.addCoordinate(points[i][0], points[i][1])
Badge

Si quelqu'un peut m'expliquer comment utiliser la fonction scipy.interpolate

avec en entree une serie de point (X,Y)

et en sortie la courbe cubic

 

Merci!!!

Badge +22

Si quelqu'un peut m'expliquer comment utiliser la fonction scipy.interpolate

avec en entree une serie de point (X,Y)

et en sortie la courbe cubic

 

Merci!!!

scipy est un module python qu'il n'est pas inclus dans FME, pour utiliser il faut suivre les etaps dans le document https://docs.safe.com/fme/html/FME_Desktop_Documentation/FME_Workbench/Workbench/Installing-Python-Packages.htm

Badge

scipy est un module python qu'il n'est pas inclus dans FME, pour utiliser il faut suivre les etaps dans le document https://docs.safe.com/fme/html/FME_Desktop_Documentation/FME_Workbench/Workbench/Installing-Python-Packages.htm

J'ai essaye d'installer le Package mais ce n'est pas si simple

Il doit y avoir un pb de droit sous windows ??

 

Dans ce cas si j'utilise FME Cloud faut il également installer le Package sur le server ou cela se fait lorsque l'on transfert le Workbench ?

 

Merci

Badge +22

J'ai essaye d'installer le Package mais ce n'est pas si simple

Il doit y avoir un pb de droit sous windows ??

 

Dans ce cas si j'utilise FME Cloud faut il également installer le Package sur le server ou cela se fait lorsque l'on transfert le Workbench ?

 

Merci

Je ne sais pas les droits necessaires pour installer sur windows, j'essaye toujour d'eviter les packages non-inclues.

 

 

Pour FME Cloud, le liste des packages inclus sont : https://knowledge.safe.com/questions/52034/r-packages-and-python-libraries-are-available-on-f.html

 

 

Pour ajouter un nouveau package, les etapes sont:

https://docs.safe.com/fme/html/FME_Desktop_Documentation/FME_Workbench/Workbench/Importing_Custom_Python_Modules_FMEServer.htm

Reply