Path-Lofting Method

The following function in GeometricTools lofts a set of contours along a path. This method uses an Akima spline to extrapolate in between the contours and path points supplied by the user, which resembles the flexibility of NURBs but without weights in order to make the process simpler for the user.

GeometricTools.surface_pathloftFunction

surface_pathloft(sections, section_NDIVS, path_NDIVS, path; injective_coordinate=1, loop_dim=0, nperiodic=2, redisc_optargs=[], verify_spline=true, save_path=nothing, paraview=true, file_pref="pathloft")

Generation of a surface grid by lofting a set of sections along a path.

sections is an array where sections[i] = (spos, points) is the i-th contour made out of the 2xn matrix points that goes along the path in the nondimensional arc-length position spos (a number between 0 and 1, where 0 is the start of the path and 1 is the end of the path). path is an array where path[i] = (X, n, twist) is the i-th point along the path placed at X in the global coordinate system and the cross section passing through this point will be oriented according to the normal vector n and twisted by twist (in degrees). The number of points in path does not need to match the number of sections in sections

This function rediscretizes the sections as indicated by section_NDIVS, which could be an array of multidiscretization parameters to apply to each section, a single multidiscretization parameter set for all the sections, or an integer with the number of points used to discretize all sections. Similarly, path_NDIVS indicates the desired discretization of the x-position along the path.

Contours can either be closed or open, and the discretization will automatically recognize and preserve that. Contours must be concave.

sections has the format sections[i] = (spos, points) where points is the nx2 matrix of n contours points (y, z) of each section, and spos is the nondimensional position along the path of each section.

path has the format path[i] = (X, normal, twist), where X is the position of the i-th point (a vector of length 3), normal is a the normal of cross sections at that position (a vector of length 3), and twist is the twist of the cross section at that position (in degrees). injective_coordinate is the coordinate that makes the path injective.

surface_pathloft(sections::Vector{Tuple{<:Real, String}}, data_path::String, args...; header_len=1, delim=",", optargs...)

Loft a geometry where the sections are read from the files indicated by sections found in data_path.

sections has the format sections[i] = (xpos, filename) where filename is the CSV file containing the (y, z) contours of each section, and xpos is the nondimensional position along the path of each section.

Example

In this example we read two conic sections from a CSV and define a loft path to generate a lofted surface grid. This animation shows the path of the loft ( points in black, normals in green, path spline in red):

Vid here
import GeometricTools as gt

import FLOWPanel: examples_path
import CSV
import DataFrames: DataFrame


save_path       = "pathloft-example"                # Where to save grid VTK
contour_path    = joinpath(examples_path, "data")   # Where to read the conic contour from


# ------------ Define contours of loft -----------------------------------------

# Read conic contours for loft
points1 = CSV.read(joinpath(contour_path, "conicsection1.csv"), DataFrame)
points1 = Matrix(points1)

points2 = CSV.read(joinpath(contour_path, "conicsection2.csv"), DataFrame)
points2 = Matrix(points2)

# Define loft sections
sections = [ # (non-dimensional arclength position along path, contour)
                (0.000,  points1),
                (0.125, points1),
                (0.250, points1),
                (0.800,  points2),
                (0.900,  points2),
                (1.000,  points2)
            ]


# ------------ Define loft path ------------------------------------------------

# Points along path
path_Xs = [
            [1.0, 0, 0],
            [2.0, 0, 0],
            [3.0, 0, 0],
            [4.0, 0.5, 0],
            [6.0, 1, 1]
          ]

# Section normals along path
path_normals = [
                [1, 0, 0],
                [1, 0, 0],
                [1, 0, 0],
                [1, 1, 0]/sqrt(2),
                [1, 1, 1]/sqrt(3)
               ]

# Twist of section contours along path
path_twists = [0, -30, -45, 0, -45]

# Collect the path
path = collect(zip(path_Xs, path_normals, path_twists))


# ------------ Generate lofted surface grid ----------------------------------

# Define discretization
section_NDIVS   = 200                               # Discretization of section contours
path_NDIVS      = 100                               # Discretization of path

# Generate loft
grid = gt.surface_pathloft(sections, path,
                            section_NDIVS, path_NDIVS; save_path=save_path, paraview=true)

surface_pathloft(...; verify_spline=true, ...) automatically generates the following plots for the user to verify that the spline is correctly fitting the raw contours and path. Here are the contours:

Pic here Pic here Pic here
Pic here Pic here Pic here


The path is visualized showing the $x-y$ and $x-z$ coordinates of the path points and normals, as shown below:

Pic here

Also the contour twist is shown along the dimensional length of the path:

Pic here

surface_pathloft(...; paraview=true, ...) calls ParaView after generating the grid to visualize the loft:

Vid here Vid here