The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.


Kite::Profile - represent and manipulate a 2d profile


    use Kite::Profile;

    # create new profile 
    my $profile = Kite::Profile->new({
        NAME => "Profile Name",
        X    => [ $x1, $x2, $x3 ... $xn ],
        Y    => [ $y1, $y2, $y3 ... $yn ]

    # load profile from file (plotfoil format)
    my $profile = Kite::Profile->new({
        FILE => 'profiles/S2091'
    }) || die Kite::Profile->error(), "\n";

    # create profile from text string (plotfoil format)
    my $profile = Kite::Profile->new({
        TEXT => "Profile Name\n x1 y1\n x2 y2\n ...\n"
    }) || die Kite::Profile->error(), "\n";

    # get/set the profile name
    print $profile->name();
    $profile->name("New name for this profile");

    # methods for general information and data output
    print $profile->about();
    print $profile->output();

    # methods to return specific profile characteristics
    print $profile->height();
    print $profile->length();
    print $profile->max_x();
    print $profile->min_x();
    print $profile->max_y();
    print $profile->min_y();

    # move (translate) the x or y values by a given amount

    # move the profile to zero it at the origin (minx = miny = 0)

    # scale the profile by a given factor

    # scale the profile to a length (x) or height (y) of 1

    # insert a node $n with values $x and $y
    $profile->insert($n, $x, $y)
        || warn $profile->error(), "\n";

    # delete node $n
        || warn $profile->error(), "\n";

    # discard all but a sub-section of nodes
    $profile->keep($from, $to)
        || warn $profile->error(), "\n";

    # test if profile is closed (first node == last node)
    print "profile is closed\n"
        if $profile->closed();
    # add final node if necessary to ensure a closed profile

    # find set of X/Y values where profile crosses point on Y/X axis
    my $xpoints = $profile->x_at_y($y);
    print "profile crosses X at Y=$y at [ @$xpoints ]\n";

    my $ypoints = $profile->y_at_x($x);
    print "profile crosses Y at X=$x at [ @$ypoints ]\n";

    # retrieve number of nodes and lists of node values
    my $no_of_nodes = $profile->n_nodes();
    my ($x, $y) = $profile->nodes();
    for (my $i = 0; $i < $no_of_nodes; $i++) {
        print "$i  x: $x->[$i]  y: $y->[$i]\n";


This module defines an object class which can be used to represent and manipulate 2D profiles. In this context, a profile is a set of X,Y co-ordinates (nodes) that define the outline of a shape.

For the original intended use in kite construction, these profiles ultimately represent cutting patterns for pieces of fabric which are sewn together to form the kite. However, this module is not specific to kite design and can be applied to any situation where you wish to represent a 2-dimensional shapes by a set of co-ordinates and perform simple manipulations on it (e.g. scale, translate, sub-section, etc.)

The profile data can be output in a simple format which can be subsequently processed (e.g. convert to Postscript) by other tools (e.g. plotfoil).



Class constructor method to create a new profile object based on data provided as configuration items, read from a file or provided as a text string. The method should be passed a reference to a hash array containing one of the following items or sets of items.


Specify the profile name, and X and Y values for each of the points that constitute the profile. The X and Y values should be specified as references to lists.

    my $profile = Kite::Profile->new({
        NAME => 'Peter Lynn "Pilot" 4m^2 - Flare'
        X    => [ 2250, 985, 110, 0, 2250 ],
        Y    => [ 0, 480, 280, 0, 0 ],

Specify a filename from which the profile data should be read.

    my $profile = Kite::Profile->new({ 
        FILE => '/home/abw/kites/pilot/rib'

The constructor returns undef if the file cannot be opened. The error() class method can be called to retrieve the specific error message.

    my $profile = Kite::Profile->new({ 
        FILE => '/home/abw/kites/pilot/rib'
    }) || die Kite::Profile->error();

The expected file format is as per Plotfoil:

     Name of the profile
     x1  y1
     x2  y2
     .   .
     .   .
     xn  yn

Comments (lines starting with # or %) are ignored, as are blank lines.


     Peter Lynn "Pilot" 4m^2 - Rib 
     # either:
     #   cut 5 of these
     # or:
     #   cut 2 of these and cut the other 3 with the flares (30mm overlap)
     2330    0
     2330   20
      350  270
      300  277
        .    .
        .    .
     2330    0

This option allows you to specify the profile data as a text string. The format should be as above.

    my $text = 

    my $profile = Kite::Profile->new({ 
        TEXT => "Peter Lynn \"Pilot\" 4m^2 - Rib\n2330 0\n2330 20\n..."; 


Returns the profile name. Can also be called with an argument to set a new name.

    $profile->name("New name for the profile");


Returns the profile length (max_x - min_x).


Returns the profile height (max_y - min_y).


Returns the smallest X value.


Returns the largest X value.


Returns the smallest Y value.


Returns the largest Y value.


Add a given amount to all the X values, effectively moving the profile in the X direction.


Add a given amount to all the Y values, effectively moving the profile in the Y direction.


Translates the profile to the origin so that both minx and max are 0.


Translates the profile X values so that minx is 0.


Translates the profile Y values so that miny is 0.


Multiply all the X values by a given amount, effectively scaling the profile in the X direction.


Multiply all the Y values by a given amount, effectively scaling the profile in the Y direction.


Multiply all the X and Y values by a given amount, effectively scaling the profile in both X and Y directions.


Scales the X values (by 1/length) to achieve a profile length of 1. The profile is moved along the X axis to ensure that min_x is 0. The max_x value is then 1 and all other values lie proportionately between 0 and 1.


Scales the Y values (by 1/height) to acheive a profile height of 1. The profile is *NOT* translated to min_x = 0 to ensure that the original centre line position of the profile is preserved. range 0 - 1.


Normalises the profile to a length of 1 (see normalise_x()) and then scales the Y values by the same factor (1/length). The end result is a proportionately scaled profile of length 1.

insert($node, $x, $y)

Inserts a new node at the position specified by $node with the $x and $y values. The value for $node should be in the range 0 - $nnodes. The existing node $n and any elements following will be shifted futher down the list by one to make room for the new element. An element inserted at $node position 0 is added to the front of the list. An element inserted at a $node position one greater than the last current node will be added to the end of the list.

Returns 1 if the new node was successfully inserted or undef on error.


Deletes the node at the position specified by $node and moves the remaining items in the list up by one to close the gap.

Returns 1 if the node was sucessfully inserted or undef on error.

keep($from, $to)

Reduces the profile to a sub-section of nodes identified by $from and $to. These should be specified as node numbers from 0 to n_nodes-1. The nodes in this range (inclusively) are kept to form the new profile and the others are discarded.


Returns a true/false value to indicate if the profile is closed. That is, if the first and last nodes contain identical X and Y values.


Duplicates the first node at the end of the list to ensure that the profile is closed. Has no effect if the profile is already closed.


Returns a reference to a list of X values where the profile crosses point $y on the Y axis. The profile must be closed. The list returned will be empty if the profile does not cross the specified point or will contain an even number of items if it does. Each pair of items thus represents an entry/exit transition into/out of the enclosed profile area for increasing values of X at a fixed Y.

Returns undef on error (e.g. profile not closed).


Returns a reference to a list of Y values where the profile crosses point $y on the X axis. Otherwise similar to x_at_y() above.


Andy Wardley <>


$Revision: 1.3 $


Copyright (C) 2000 Andy Wardley. All Rights Reserved.

This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself.


okprof, Kite, Kite::Base