Perl Array help

okay so my job is requiring me to learn perl and i have never had any type of programming language... ever.

So i need to take a file that has data (nodes/points) with x, y, and z components.

Example of what the file contains is below:

RANDOM TEXT
RANDOM TEXT
Node #          x pos              ypos          zpos
5948             50.24              125.35          5.79
(there are over 200 lines of this data)
RANDOM TEXT
RANDOM TEXT

i need to somehow open this file, grab the data for Node, x position, y pos, and z pos and from this data be able to calculate which node is closest to a given position by a user defined input.

so if the user enters a position of lets say 10 for the x pos, 10 for the y pos, and 10 for the z pos. (just keeping it simple) the code needs to be able to loop through the data and find the node with the closest corresponding positions.

ANY help is much appreciated!!

Few questions:

  1. Please post few lines from the input file spanning few lines from random text, few lines of node data, and few more lines of random text. The simplest way to loop through the nodes and positions is by checking if the line starts with a number (unless no other random text starts with a number too)
  1. When you say grab the closest point, do you mean the point from file nearest to the user inputted data:
    dist = sqrt ((x_input - x)^2 + (y_input - y)^2 + (z_input - z)^2)

I dont have the file with me right now but yes, it contains other sets of numbers (which i don't need) along with other information that was gathered from a simulation.

and when i say grab the closest point (node), i mean that i want to find a node that is closest to a user inputted position. So if the user inputs values for x,y,z as 10,10,10 and my data set only contains 2 nodes with positions 11,11,11 and 50,50,50 i want it to tell me that the node with the 11,11,11 position is closest to the user inputted position of 10,10,10

It'd be helpful if you can post sample input data.

And, I'm sure the co-ordinates are not as simple as (11,11,11) and (12,12,12).

If user inputs (10,10,10) and the file contains (9,10,11) and (11,9,10), then which point will you choose? (If you plot these points on a graph and measure the distance between (10,10,10) from the other two points, it'd measure the same.)

What logic are you following to determine the closest point?

I will reply tomorrow with the file and code im using. it will make it a little easier to explain

---------- Post updated at 07:59 AM ---------- Previous update was at 12:52 AM ----------

open (FILENAME, "<FILEPATH")

but i guess to start off im not exactly sure how to only gather the first set of data from the file and nothing else.

That answers the first question. Second question is how would you want to find the nearest node given the input co-ordinates?

From my understanding, this looks like the Finite Element Analysis of a bar. And you might want to use the distance formula (mentioned in post #2) to determine the nearest node.

To open a file, you can use this: open FH, "< /path/to/file";
Use this filehandle 'FH' in a loop to read each line of file.

You are correct about the FEA. My current code looks as followed: (all it dose is output the entire file from above post into my command screen)

use feature ':5.10';
use warnings;
use strict;


#print "Enter File Path:\n"

#$file_path = <>;
my $LINE_VAR; 

open (COORD, "</projects/student2/Projects/FEA_AN/GM_Back_structure/Tensile_Bar_TEST.inp");

while (<COORD>) {

    my @raw_data = <COORD>;

        foreach $LINE_VAR (@raw_data)
{


            print "$LINE_VAR";

}

}
close (COORD);

And i guess the distance formula would work if it allows me to input a position, and from there it calculates the closest node.

[highlight=perl]#! /usr/bin/perl
use warnings;
use strict;

(@ARGV != 3) && die "Enter co-ordinates. Exiting ";

my ($x, $y, $z) = @ARGV;
my (@nos, @near_node);
my ($dist, $near_dist);

open (COORD, "input");
while (<COORD>) {
chomp;
if (/^\NODE/ .. /^\*\/) {
if (/^\NODE/) { next }
if (/^\*\
/) { last }

    @nos = split /\\s\+/;
    @nos = map \{ s/[.,]\+$//; $_ \} @nos;
    $dist = sqrt \(\(\($x - $nos[2]\) ** 2\) \+ \(\($y - $nos[3]\) ** 2\) \+ \(\($z - $nos[4]\) ** 2\)\);

    \#print "$dist .. @nos\\n"; \# Uncomment this line if you want to see dist of each node from input and the node itself.
    if \(!defined\($near_dist\)\) \{
        $near_dist = $dist;
        @near_node = @nos;
    \}
    elsif \($dist &lt;= $near_dist\) \{
        $near_dist = $dist;
        @near_node = @nos;
    \}
\}

}
close (COORD);
print "Nearest node: @near_node\nDistance: $near_dist\n";[/highlight]Provide input co-ordinates (x,y,z) as command line arguments.
Few runs:

[user@host ~]# ./test.pl 76 86 0
Nearest node:  29456 75.95656 86.5 0
Distance: 0.501883486080186
[user@host ~]#
[user@host ~]# ./test.pl 50 60 0
Nearest node:  29376 57.499958 77.81881 0
Distance: 19.3328570009159
[user@host ~]# ./test.pl 78 88 10
Nearest node:  29466 77.82405 87.50001 0
Distance: 10.014037567465
[user@host ~]#

wow! okay first question.

(@ARGV != 3) && die "Enter co-ordinates. Exiting ";

im not to sure what this line is doing.

If the command line arguments are not equal to 3, the program will exit. Try giving just ./test.pl and see what happens.

when you say giving

./test.pl

what do you mean exactly. I have only been using Perl for about two days now so I am VERY to this.

  1. Which OS are you working on?
  2. How did you run sample practice perl programs in your 2 days of learning?
  1. I'm running vista (figure a company like BASF could afford something better, huh?)
  2. We have a program call PuTTy.

OK... Please post the output of the following two commands:

  1. uname -a
  2. echo $SHELL

My guess is you're connecting to a server with some enterprise version of Linux and you do that using PuTTY. Try the following steps in your home directory.

  1. Paste the program in a file "test.pl"
  2. Paste the sample input in a file "input"
  3. Run it at command line using this command perl test.pl 76 86 0

uname -a

wyncc 2.6.34-12-desktop #1 SMP PREEMP 2010-06-29 02:39:08 +0200 x86_64 x86_64 x86_64 GNU/Linux

echo $SHELL

/bin/tcsh

and i got it to work.

i wast aware that the inputs where to be entered right after the test.pl

if you don't mind i would just kind of like to clarify some of the code to get a better understand of what each line is doing.

This segment is searching through the "input" file for the data between *NODE and * correct? and if it finds *NODE it wants all the data on the next line until the data just above *?

while (<COORD>) {
    chomp;
    if (/^\*NODE/ .. /^\*\*/) {
        if (/^\*NODE/) { next }
        if (/^\*\*/)   { last }

as for the next two lines i have absolutely no idea what they are doing.

@nos = split /\s+/;
        @nos = map { s/[.,]+$//; $_ } @nos;

Thanks!

Yes, you're right.

@nos = split /\s+/; => Split the line using whitespaces as delimiter and store the elements in array @nos

@nos = map { s/[.,]+$//; $_ } @nos => s/// is similar to sed's substitution. This is the general format: s/<pattern>/<replacement>/modifiers. So string matched by <pattern> is substituted by <replacement>. What we're doing here is, take each element of array @nos and delete last characters if they're a '.' or ',' (or rather substitute . or , by nothing). After this task take the elements and store them back in array @nos

Next question:

This line is checking to see if near_dist is defined and if it's defined it sets near_dist = dist

if (!defined($near_dist)) {
            $near_dist = $dist;
        }

as for this next line im not to sure whats happening

elsif ($dist <= $near_dist) {
            $near_dist = $dist;
            @near_node = @nos;

---------- Post updated at 12:48 PM ---------- Previous update was at 12:25 PM ----------

also when i enter a negative value for a node position it gives me the incorrect node that is closest. Is there away to allow negative positions???????

---------- Post updated at 01:10 PM ---------- Previous update was at 12:48 PM ----------

im also getting
Use of uninitialized value in subtraction (-) for i believe every line data

here is the data containing the negative coordinates.

The format of the file attached in post #18 has changed. Your original requirement was to loop through the data co-ordinates which are in between "*NODE" and "**". And this data in between had few white spaces at the beginning of each line.

Since the data format provided now has changed, the program is not going into the if-condition block inside the while loop.

Try with this exact data sample (this is similar to your original requirement):

Random Text
Random Text
Random Text
*NODE
    70000000,        2536.143099644908,       -228.1225513919157,                 776.3626
    70000001,        2537.780882406166,      -224.58895334736727,                 776.3626
    70000002,                 2532.735,                  -224.66,                 776.3626
    70000003,                 2532.735,                 -227.938,                 776.3626
    70000004,       2511.7897270833937,                 -224.514,                 776.3626
    70000005,                 2506.435,                 -224.514,                 776.3626
    70000006,        2506.441591494802,      -227.63505426366342,                 776.3626
    70000007,        2512.065925587347,      -227.04047758786248,                 776.3626
    70000008,       2506.7046700485685,      -231.10340020092286,                 776.3626
    70000009,       2512.6415277961746,      -229.46730220429106,                 776.3626
    70000010,        2520.966873352281,         -238.49470282806,                 776.3626
**
Random Text
Random Text
Random Text
[user@host ~]# ./test.pl 2532 -228 776
Nearest node: 70000003 2532.735 -227.938 776.3626
Distance: 0.821917124776105
[user@host ~]#

Also, I've made a small modification in the code after line #24 (added line "@near_node = @nos" as line #25. This will help to display the node data incase the match is obtained in the very first line).

im still pulling data from the *NODE to **. I had the code put the data into a .txt file just for quick reference.