mirror of
https://expo.survex.com/repositories/expoweb/.git/
synced 2025-12-08 14:54:28 +00:00
[svn r7460] I've added this here so I don't lose it again
This commit is contained in:
320
noinfo/cavestats.c
Normal file
320
noinfo/cavestats.c
Normal file
@@ -0,0 +1,320 @@
|
||||
/* cavestats.c */
|
||||
/* Print statistics on a cave */
|
||||
/* Copyright (C) 2004 David Loeffler
|
||||
* Based on 3dtopos.c by Olly Betts
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "cmdline.h"
|
||||
#include "filelist.h"
|
||||
#include "filename.h"
|
||||
#include "img.h"
|
||||
#include "message.h"
|
||||
#include "osalloc.h"
|
||||
|
||||
int cmp_station(const void *a, const void *b);
|
||||
|
||||
static const struct option long_opts[] = {
|
||||
/* const char *name; int has_arg (0 no_argument, 1 required_*, 2 optional_*); int *flag; int val; */
|
||||
{"survey", required_argument, 0, 's'},
|
||||
{"help", no_argument, 0, HLP_HELP},
|
||||
{"version", no_argument, 0, HLP_VERSION},
|
||||
{"compact", no_argument, 0, 'c'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
#define short_opts "s:c"
|
||||
|
||||
static struct help_msg help[] = {
|
||||
/* <-- */
|
||||
{HLP_ENCODELONG(0), "only load the sub-survey with this prefix"},
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
img_point pt;
|
||||
} station;
|
||||
|
||||
static station basept;
|
||||
|
||||
static int separator;
|
||||
|
||||
int
|
||||
cmp_station(const void *a, const void *b)
|
||||
{
|
||||
img_point pta, ptb;
|
||||
double crossprod;
|
||||
pta = ((const station *)a)->pt;
|
||||
ptb = ((const station *)b)->pt;
|
||||
|
||||
if(pta.x == basept.pt.x && pta.y == basept.pt.y) return -1;
|
||||
if(ptb.x == basept.pt.x && ptb.y == basept.pt.y) return 1;
|
||||
/* These two lines mean that the basepoint should compare as being before everything.
|
||||
Otherwise somewhat unpredictable behaviour occurs! */
|
||||
crossprod = (pta.x - basept.pt.x)*(ptb.y - basept.pt.y) - (pta.y - basept.pt.y)*(ptb.x - basept.pt.x);
|
||||
if(crossprod > 0) return 1;
|
||||
if(crossprod < 0) return -1;
|
||||
else return 0;
|
||||
}
|
||||
|
||||
static station *stns;
|
||||
static OSSIZE_T c_stns = 0;
|
||||
static station *hull;
|
||||
static OSSIZE_T c_hull = 0;
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
char *fnm;
|
||||
img *pimg;
|
||||
int result;
|
||||
OSSIZE_T c_labels = 0;
|
||||
OSSIZE_T c_totlabel = 0;
|
||||
char *p, *p_end;
|
||||
const char *survey = NULL;
|
||||
bool compact_output = 0;
|
||||
double totlen = 0, planlen = 0;
|
||||
img_point lastpt;
|
||||
int num_legs = 0;
|
||||
|
||||
msg_init(argv);
|
||||
|
||||
cmdline_set_syntax_message("3D_FILE", NULL); /* TRANSLATE */
|
||||
cmdline_init(argc, argv, short_opts, long_opts, NULL, help, 1, 1);
|
||||
while (1) {
|
||||
int opt = cmdline_getopt();
|
||||
if (opt == EOF) break;
|
||||
if (opt == 's') survey = optarg;
|
||||
if (opt == 'c') compact_output = 1;
|
||||
}
|
||||
|
||||
fnm = argv[optind++];
|
||||
|
||||
pimg = img_open_survey(fnm, survey);
|
||||
if (!pimg) fatalerror(img_error(), fnm);
|
||||
separator = pimg->separator;
|
||||
|
||||
/* Output headings line */
|
||||
if (!compact_output) printf("Statistics for %s (prefix %s)\n", fnm, survey);
|
||||
|
||||
do {
|
||||
img_point pt;
|
||||
result = img_read_item(pimg, &pt);
|
||||
switch (result) {
|
||||
case img_LINE:
|
||||
if(!pimg->flags)
|
||||
{
|
||||
planlen += sqrt((pt.x - lastpt.x)*(pt.x - lastpt.x) + (pt.y - lastpt.y)*(pt.y - lastpt.y));
|
||||
totlen += sqrt((pt.x - lastpt.x)*(pt.x - lastpt.x) + (pt.y - lastpt.y)*(pt.y - lastpt.y) + (pt.z - lastpt.z)*(pt.z - lastpt.z));
|
||||
}
|
||||
num_legs++;
|
||||
case img_MOVE:
|
||||
lastpt = pt;
|
||||
break;
|
||||
case img_LABEL:
|
||||
if(pimg->flags & img_SFLAG_UNDERGROUND)
|
||||
{
|
||||
c_labels++;
|
||||
c_totlabel += strlen(pimg->label) + 1;
|
||||
}
|
||||
break;
|
||||
case img_BAD:
|
||||
img_close(pimg);
|
||||
fatalerror(img_error(), fnm);
|
||||
}
|
||||
} while (result != img_STOP);
|
||||
|
||||
/* + 1 to allow for reading coordinates of legs after the last label */
|
||||
stns = osmalloc(ossizeof(station) * (c_labels + 1));
|
||||
p = osmalloc(c_totlabel);
|
||||
p_end = p + c_totlabel;
|
||||
|
||||
img_rewind(pimg);
|
||||
|
||||
do {
|
||||
result = img_read_item(pimg, &(stns[c_stns].pt));
|
||||
switch (result) {
|
||||
case img_LINE:
|
||||
case img_MOVE:
|
||||
break;
|
||||
case img_LABEL:
|
||||
if (!(pimg->flags & img_SFLAG_UNDERGROUND)) break;
|
||||
if (c_stns < c_labels) {
|
||||
OSSIZE_T len = strlen(pimg->label) + 1;
|
||||
if (p + len <= p_end) {
|
||||
memcpy(p, pimg->label, len);
|
||||
stns[c_stns++].name = p;
|
||||
p += len;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* FALLTHRU */
|
||||
case img_BAD:
|
||||
img_close(pimg);
|
||||
fatalerror(/*Bad 3d image file `%s'*/106, fnm);
|
||||
}
|
||||
} while (result != img_STOP);
|
||||
|
||||
if (c_stns != c_labels || p != p_end) {
|
||||
img_close(pimg);
|
||||
fatalerror(/*Bad 3d image file `%s'*/106, fnm);
|
||||
}
|
||||
|
||||
img_close(pimg);
|
||||
if (c_stns == 0)
|
||||
{
|
||||
printf("No survey data!\n");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
station wmost, nmost, emost, smost, umost, lmost;
|
||||
wmost = emost = nmost = smost = umost = lmost = stns[0];
|
||||
{
|
||||
OSSIZE_T i;
|
||||
for(i = 0; i < c_stns; i++)
|
||||
{
|
||||
if(stns[i].pt.x < wmost.pt.x) wmost = stns[i];
|
||||
if(stns[i].pt.x > emost.pt.x) emost = stns[i];
|
||||
if(stns[i].pt.y > nmost.pt.y) nmost = stns[i];
|
||||
if(stns[i].pt.y < smost.pt.y) smost = stns[i];
|
||||
if(stns[i].pt.z > umost.pt.z) umost = stns[i];
|
||||
if(stns[i].pt.z < lmost.pt.z) lmost = stns[i];
|
||||
}
|
||||
}
|
||||
|
||||
basept = wmost; /* any extreme point will do */
|
||||
|
||||
qsort(stns, c_stns, sizeof(station), cmp_station);
|
||||
|
||||
/* Now, having sorted the stations, any duplicate stations caused by *equates will appear consecutive. */
|
||||
|
||||
{
|
||||
OSSIZE_T i;
|
||||
int real_stn_count = 1;
|
||||
for(i = 1; i < c_stns; i++)
|
||||
if(stns[i].pt.x != stns[i-1].pt.x || stns[i].pt.y != stns[i-1].pt.y || stns[i].pt.z != stns[i-1].pt.z)
|
||||
real_stn_count++;
|
||||
if (!compact_output)
|
||||
{
|
||||
printf((real_stn_count == 1 ? msg(172) : msg(173)), real_stn_count);
|
||||
printf((num_legs == 1 ? msg(174) : msg(175)), num_legs);
|
||||
putnl();
|
||||
//printf((num_legs - real_stn_count == 0 ? msg(138) : msg(139)), num_legs - real_stn_count + 1);
|
||||
// Can't do this, as we don't know the number of connected components
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!compact_output)
|
||||
{
|
||||
printf("Total length of survey legs = %.2fm\n", totlen);
|
||||
|
||||
printf(msg(133), planlen);
|
||||
putnl();
|
||||
|
||||
printf(msg(135), (umost.pt.z - lmost.pt.z));
|
||||
printf(umost.name);
|
||||
printf(msg(136), umost.pt.z);
|
||||
printf(lmost.name);
|
||||
printf(msg(137), lmost.pt.z);
|
||||
putnl();
|
||||
|
||||
printf(msg(148), (nmost.pt.y - smost.pt.y));
|
||||
printf(nmost.name);
|
||||
printf(msg(136), nmost.pt.y);
|
||||
printf(smost.name);
|
||||
printf(msg(137), smost.pt.y);
|
||||
putnl();
|
||||
|
||||
printf(msg(149), (emost.pt.x - wmost.pt.x));
|
||||
printf(emost.name);
|
||||
printf(msg(136), emost.pt.x);
|
||||
printf(wmost.name);
|
||||
printf(msg(137), wmost.pt.x);
|
||||
putnl();
|
||||
}
|
||||
if(c_stns == 1)
|
||||
{
|
||||
if (!compact_output) printf("Horizontal extent = 0.00m (from %s to %s)\n", stns[0].name, stns[0].name);
|
||||
else printf("0.00\t0.00\t0.00\n");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
if(c_stns == 2)
|
||||
{
|
||||
if (!compact_output) printf("Horizontal extent = %.2fm (from %s to %s)\n", planlen, stns[0].name, stns[1].name);
|
||||
else printf("%.2f\t%.2f\t%.2f", planlen, umost.pt.z-lmost.pt.z, planlen);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
// Noddy equivalent of a stack...
|
||||
c_hull = 3;
|
||||
hull = osmalloc(ossizeof(station) * c_stns);
|
||||
hull[0] = stns[0];
|
||||
hull[1] = stns[1];
|
||||
hull[2] = stns[2];
|
||||
OSSIZE_T i = 3;
|
||||
while(i < c_stns)
|
||||
{
|
||||
double sa;
|
||||
sa = (hull[c_hull - 1].pt.x - stns[i].pt.x)*(hull[c_hull - 2].pt.y - stns[i].pt.y)
|
||||
- (hull[c_hull - 2].pt.x - stns[i].pt.x)*(hull[c_hull - 1].pt.y - stns[i].pt.y);
|
||||
if(sa > 0)
|
||||
{
|
||||
hull[c_hull++] = stns[i++];
|
||||
}
|
||||
else
|
||||
{
|
||||
c_hull--;
|
||||
}
|
||||
}
|
||||
{
|
||||
OSSIZE_T j;
|
||||
station s1, s2;
|
||||
double d, e, r;
|
||||
s1 = s2 = hull[0];
|
||||
r = 0;
|
||||
j = 0;
|
||||
d = 0;
|
||||
for(i = 0; i < c_hull; i++)
|
||||
{
|
||||
d = sqrt((hull[j % c_hull].pt.x - hull[i].pt.x)*(hull[j % c_hull].pt.x - hull[i].pt.x) + (hull[j % c_hull].pt.y - hull[i].pt.y)*(hull[j % c_hull].pt.y - hull[i].pt.y));
|
||||
while((e = sqrt((hull[(j+1) % c_hull].pt.x - hull[i].pt.x)*(hull[(j+1) % c_hull].pt.x - hull[i].pt.x) + (hull[(j+1) % c_hull].pt.y - hull[i].pt.y)*(hull[(j+1) % c_hull].pt.y - hull[i].pt.y))) >= d)
|
||||
{
|
||||
j++; d = e;
|
||||
}
|
||||
if(d > r)
|
||||
{
|
||||
r = d;
|
||||
s1 = hull[i];
|
||||
s2 = hull[j % c_hull];
|
||||
}
|
||||
}
|
||||
if (!compact_output) printf("Horizontal extent = %.2fm (from %s to %s)\n", r, s1.name, s2.name);
|
||||
else printf("%.2f\t%.2f\t%.2f\n", totlen, umost.pt.z - lmost.pt.z, r);
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
Reference in New Issue
Block a user