Please read the CODE POSTING GUIDELINES and edit your post to include CODE TAGS.
Registered forum members do not see this ad.
Hi,
I have tried to write a lisp to draw a line between 2 GPs points, the distance between them is calculated using havesine formula, but I get an error [; error: bad argument type: consp "56.06613,3.4514"], I believe that it doesn't recognise the coordinates for some reason, can someone help me with this.
I have started to write this lisp for myself for fun, since I have a smartphone from where I can extract the GPS coordinates, and I wanted to see if I can mesure more accurate the size of my garden![]()
I have to admit that I am an begginer in lisp writing.
Best regards,
Cristian
;***********csv file***********Code:;draw real distances from GPS coordinates ;load points from csv files (Defun C:gpsd ( / dataL csv_name ofil rd-pos n Pi1 P1 cntr P2n ang ED lat1 lat2 Dlat Dlong a c RD ent entdata) ;*******************load files*************** (setq dataL '());define an empty list (setq csv_name "");define an empty name for file (setq csv_name (getfiled "Select Point List .csv file" "" "csv" 2));get the file name (setq ofil (open CSV_name "r")); define "ofile" as open the file (while (setq rd-pos (read-line ofil));read each line from file (setq dataL (cons rd-pos dataL));add each row to list );close while (close ofil);close file (setq dataL (reverse dataL));put list in right order (setq n (length dataL));get the number of points (setq Pi1 (nth 0 dataL));get initial GPS point (setq P1 '(0 0));set initial Real point to "0,0" (setq xi1 (car Pi1));get initial x from first point (setq yi1 (cadr Pi1));get initial y from first point (setq cntr 1) (while (<= cntr n) (setq P2n (nth cntr dataL));choose second GPS point by cntr (setq Pxn (car P2n));get x from second point (setq Pyn (cadr P2n));get y from second point (setq ang (angle Pi1 P2n));get angle between points (setq ang (* 180.0 (/ ang pi)));convert angles from radians to degrees ;calculate real distance (setq ED 6371000);earth diameter in metres (setq lat1 (* pi (/ xi1 180.0)));lat in rad (setq lat2 (* pi (/ Pxn 180.0))) (setq Dlat (* pi(/ (- Pxn xi1) 180.0))) (setq Dlong (* pi(/ (- Pyn yi1) 180.0))) (setq a (+ (sin(/ 2 Dlat)^2) (* (* (cos lat1) (cos lat2)) (sin (/ 2 Dlong)^2)))) (setq c (* 2 (atan (sqrt a) (sqrt (- 1 a)))));calculate earth angle (setq RD (* ED c));calculate real distance between GPs Points (setq RD (* RD 1000));convert distance from metres to mm (setq P2 (polar P1 ang RD));calculate Real P2 by distance and angle (command ".line" P1 P2 "");draw a line as real distance between GPS points (setq ent (entlast));select last entoty created (setq entdata (entget ent));extract info from it (setq P1 (cdr (assoc 11 entdata)));reset Real P1 as (X2,Y2) from last line (setq Pi1 P2n);reset GPS Pi1 as next point (setq xi1 (car Pi1));recalculate x from new point (setq yi1 (cadr Pi1));recalculate y from new point ;reset counter (setq cntr (+ 1 cntr)) );close while loop );close lisp
56.045809 -3.467674
56.046754 -3.467043
56.047555 -3.466557
56.049877 -3.465697
56.050516 -3.465509
56.051126 -3.465203
56.051486 -3.464872
56.052003 -3.464229
56.052626 -3.463154
56.052887 -3.462645
;***********end csv***********
Last edited by Cristi_an_24; 18th Jul 2012 at 04:53 pm.
Please read the CODE POSTING GUIDELINES and edit your post to include CODE TAGS.
“A narrow mind and a fat head invariably come on the same person” Zig Zigler
![]()
When you open CSV file in notepad - not excel, you'll notice that every cell in a row of CSV is separated by "," character, so you must find Xcoord and Ycoord separately and put them in list of points as these coordinates are later retrieved with car or cadr functions... Also ^ operand in lisp is unknown - check (expt) function for exponentiation...
Not checked but these are my remarks... (highlighted) - you must test it and later improve...
M.R.Code:;draw real distances from GPS coordinates ;load points from csv files (Defun C:gpsd ( / Xcoord Ycoord dataL csv_name ofil rd-pos n Pi1 P1 cntr P2n ang ED lat1 lat2 Dlat Dlong a c RD ent entdata) ;*******************load files*************** (setq dataL '());define an empty list (setq csv_name "");define an empty name for file (setq csv_name (getfiled "Select Point List .csv file" "" "csv" 2));get the file name (setq ofil (open CSV_name "r")); define "ofile" as open the file (while (setq rd-pos (read-line ofil));read each line from file (setq Xcoord (substr rd-pos 1 (vl-string-position (ascii ",") rd-pos))) (setq Ycoord (substr rd-pos (+ (vl-string-position (ascii ",") rd-pos) 2) (- (strlen rd-pos) (vl-string-position (ascii ",") rd-pos) 1))) (setq dataL (cons (list (read Xcoord) (read Ycoord)) dataL));add each row to list );close while (close ofil);close file (setq dataL (reverse dataL));put list in right order (setq n (length dataL));get the number of points (setq Pi1 (nth 0 dataL));get initial GPS point (setq P1 '(0 0));set initial Real point to "0,0" (setq xi1 (car Pi1));get initial x from first point (setq yi1 (cadr Pi1));get initial y from first point (setq cntr 1) (while (<= cntr n) (setq P2n (nth cntr dataL));choose second GPS point by cntr (setq Pxn (car P2n));get x from second point (setq Pyn (cadr P2n));get y from second point (setq ang (angle Pi1 P2n));get angle between points (setq ang (* 180.0 (/ ang pi)));convert angles from radians to degrees ;calculate real distance (setq ED 6371000);earth diameter in metres (setq lat1 (* pi (/ xi1 180.0)));lat in rad (setq lat2 (* pi (/ Pxn 180.0))) (setq Dlat (* pi(/ (- Pxn xi1) 180.0))) (setq Dlong (* pi(/ (- Pyn yi1) 180.0))) (setq a (+ (expt (sin (/ 2 Dlat)) 2) (* (* (cos lat1) (cos lat2)) (expt (sin (/ 2 Dlong)) 2)))) (setq c (* 2 (atan (sqrt a) (sqrt (- 1 a)))));calculate earth angle (setq RD (* ED c));calculate real distance between GPs Points (setq RD (* RD 1000));convert distance from metres to mm (setq P2 (polar P1 ang RD));calculate Real P2 by distance and angle (command ".line" P1 P2 "");draw a line as real distance between GPS points (setq ent (entlast));select last entoty created (setq entdata (entget ent));extract info from it (setq P1 (cdr (assoc 11 entdata)));reset Real P1 as (X2,Y2) from last line (setq Pi1 P2n);reset GPS Pi1 as next point (setq xi1 (car Pi1));recalculate x from new point (setq yi1 (cadr Pi1));recalculate y from new point ;reset counter (setq cntr (+ 1 cntr)) );close while loop );close lisp
I have marked in red the trouble maker code - the lines you got from data file are strings, while you attempt to treat them as list:
Code:... (setq Pi1 (nth 0 dataL));get initial GPS point (setq P1 '(0 0));set initial Real point to "0,0" (setq xi1 (car Pi1));get initial x from first point (setq yi1 (cadr Pi1));get initial y from first point ...
Regards,
Mircea
AutoCAD's happy user equation: FILEDIA + PICKADD² + PICKFIRST = 3
Thanks, I will try tomorrow Marko's version, I was thinking that I am reading the each row from csv as a list of coordinates for each point, obviously I am wrong.
Regards,
Cristian
I need your help again, this time I believe the angle gets a negative value and my program stops, I tried to force my calculation to bring me positive values using "abs", but still nothing
I have also change my code a bit, I am now calculating the distances relative to the first poing, get the real x&y, I store them into a list and at the end I want to draw a line to connect all the dots.
"; error: function undefined for argument: -0.0577494"Code:;draw real distances from GPS coordinates ;load points from csv files (Defun C:gpx ( / Xcoord Ycoord dataL Rpt csv_name ofil rd-pos n Pi1 P1 cntr P2n ang ED lat1 lat2 Dlat Dlong a c RD ent entdata) ;*******************load files*************** (setq dataL '());define an empty list (setq Rpt '());define an empty list for points (setq csv_name "");define an empty name for file (setq csv_name (getfiled "Select Point List .csv file" "" "csv" 2));get the file name (setq ofil (open CSV_name "r")); define "ofile" as open the file (while (setq rd-pos (read-line ofil));read each line from file (setq Xcoord (substr rd-pos 1 (vl-string-position (ascii ",") rd-pos))) (setq Ycoord (substr rd-pos (+ (vl-string-position (ascii ",") rd-pos) 2) (- (strlen rd-pos) (vl-string-position (ascii ",") rd-pos) 1))) (setq dataL (cons (list (read Xcoord) (read Ycoord)) dataL));add each row to list );close while (close ofil);close file (setq dataL (reverse dataL));put list in right order (setq n (length dataL));get the number of points (setq Pi1 (nth 0 dataL));get initial GPS point (setq P1 '(0 0));set initial Real point to "0,0" (setq xi1 (car Pi1));get initial x from first point (setq yi1 (cadr Pi1));get initial y from first point (setq Rpt (cons P1 Rpt));add P1 on list as 0,0 (setq cntr 1) (while (<= cntr n) (setq P2n (nth cntr dataL));choose second GPS point by cntr (setq Pxn (car P2n));get x from second point (setq Pyn (cadr P2n));get y from second point (setq ang (angle Pi1 P2n));get angle between points (setq ang (* 180.0 (/ ang pi)));convert angles from radians to degrees ;calculate real distance (setq ED 6371000);earth diameter in metres (setq lat1 (abs(* pi (/ xi1 180.0))));lat in rad (setq lat2 (abs(* pi (/ Pxn 180.0)))) (setq Dlat (abs (* pi(/ (- Pxn xi1) 180.0))));abs added (setq Dlong (abs (* pi(/ (- Pyn yi1) 180.0))));abs added (setq a (+ (expt (sin (/ 2 Dlat)) 2) (* (* (cos lat1) (cos lat2)) (expt (sin (/ 2 Dlong)) 2)))) (setq c (* 2 (atan (sqrt a) (sqrt (- 1 a)))));calculate earth angle (setq RD (* ED c));calculate real distance between GPs Points (setq RD (* RD 1000));convert distance from metres to mm (setq P2 (polar P1 ang RD));calculate Real P2 by distance and angle (setq Rpt (cons P2 Rpt));add next point to the list ;reset counter (setq cntr (+ 1 cntr)) );close while loop (setq Rpt (reverse RPT));put the list in the right order (command ".line" Rpt "");draw a line as real distance between GPS points );close lisp
for points:
56.06613 3.4514
56.06671 3.45163
56.06694 3.44979
56.0663 3.44959
and
; error: bad argument type: 2D/3D point: nil
for this list of points:
56.045809 -3.467674
56.046754 -3.467043
56.047555 -3.466557
56.049877 -3.465697
what is wrong in my code?
Thanks,
Cristian
First, please pay attention to the number of items you try to walk on the list:
Second, the line cannot be drawn by using the list of points as argument:Code:(while (<= cntr n)(while (< cntr n)
Code:(command ".line" Rpt "")(command "_.LINE") (foreach point Rpt (command "_non" point) ) (command "")
Regards,
Mircea
AutoCAD's happy user equation: FILEDIA + PICKADD² + PICKFIRST = 3
Thanks Mircea,
I have changed my code with your recomandations but i still get this error: "; error: function undefined for argument: -0.00160928", I have attached my list of points as well as text file.
Thanks again,
Cristian
There is an inconsistency between the code and example file – the separator used in the file is <Tab> instead of comma considered in code; so you should use;
instead of:Code:(ascii "\t")
Code:(ascii "\,")
Regards,
Mircea
AutoCAD's happy user equation: FILEDIA + PICKADD² + PICKFIRST = 3
Registered forum members do not see this ad.
The problem is from the fact that square root have meaning only for positive numbers; in at least one case the argument become negative.
You should validate again your formulas - I cannot check them since don't know from where come from.Code:(setq c (* 2 (atan (sqrt a) (sqrt (- 1 a)))))
The (at least first) trouble-maker pair of data is:
56.0534 -3.46219
Regards,
Mircea
AutoCAD's happy user equation: FILEDIA + PICKADD² + PICKFIRST = 3
Bookmarks