diff --git a/src/celengine/samporbit.cpp b/src/celengine/samporbit.cpp index 2105fa21d..c027cac8f 100644 --- a/src/celengine/samporbit.cpp +++ b/src/celengine/samporbit.cpp @@ -21,6 +21,7 @@ #include #include #include +#include using namespace std; @@ -870,6 +871,77 @@ template SampledOrbitXYZV* LoadSampledOrbitXYZV(const string& fi return orbit; } +/* Load a binary xyzv sampled trajectory file. + */ +template SampledOrbitXYZV* +LoadSampledOrbitXYZVBinary(const string& filename, TrajectoryInterpolation interpolation, T /*unused*/) +{ + ifstream in(filename.c_str(), ios::binary); + if (!in.good()) + { + //cerr << "Error openning " << filename << ".\n"; + return NULL; + } + + XYZVBinaryHeader header; + if (!in.read(reinterpret_cast(&header), sizeof(header))) + { + cerr << "Error reading header of " << filename << ".\n"; + return NULL; + } + + if (string(header.magic) != "CELXYZV") + { + cerr << "Bad binary xyzv file " << filename << ".\n"; + return NULL; + } + + if (header.byteOrder != __BYTE_ORDER__) + { + cerr << "Unsupported byte order " << header.byteOrder + << ", expected " << __BYTE_ORDER__ << ".\n"; + return NULL; + } + + + if (header.digits != std::numeric_limits::digits) + { + cerr << "Unsupported digits number " << header.digits + << ", expected " << std::numeric_limits::digits << ".\n"; + return NULL; + } + + if (header.count == 0) + return NULL; + + SampledOrbitXYZV* orbit = new SampledOrbitXYZV(interpolation); + + double lastSampleTime = -numeric_limits::infinity(); + + while (in.good()) + { + XYZVBinaryData data; + + if (!in.read(reinterpret_cast(&data), sizeof(data))) + break; + + double tdb = data.tdb; + Vec3d* position = reinterpret_cast(data.position); + Vec3d* velocity = reinterpret_cast(data.velocity); + + // Convert velocities from km/sec to km/Julian day + *velocity *= astro::daysToSecs(1.0); + + if (tdb != lastSampleTime) + { + orbit->addSample(tdb, *position, *velocity); + lastSampleTime = tdb; + } + } + + return orbit; +} + /*! Load a trajectory file containing single precision positions. */ @@ -891,6 +963,10 @@ Orbit* LoadSampledTrajectoryDoublePrec(const string& filename, TrajectoryInterpo */ Orbit* LoadXYZVTrajectorySinglePrec(const string& filename, TrajectoryInterpolation interpolation) { + Orbit* ret = LoadSampledOrbitXYZVBinary(filename + "bin", interpolation, 0.0f); + if (ret != NULL) + return ret; + return LoadSampledOrbitXYZV(filename, interpolation, 0.0f); } @@ -899,5 +975,9 @@ Orbit* LoadXYZVTrajectorySinglePrec(const string& filename, TrajectoryInterpolat */ Orbit* LoadXYZVTrajectoryDoublePrec(const string& filename, TrajectoryInterpolation interpolation) { + Orbit* ret = LoadSampledOrbitXYZVBinary(filename + "bin", interpolation, 0.0); + if (ret != NULL) + return ret; + return LoadSampledOrbitXYZV(filename, interpolation, 0.0); } diff --git a/src/celengine/xyzvbinary.h b/src/celengine/xyzvbinary.h new file mode 100644 index 000000000..69074c0b4 --- /dev/null +++ b/src/celengine/xyzvbinary.h @@ -0,0 +1,19 @@ +#pragma once + +#include + +struct XYZVBinaryHeader +{ + char magic[8]; + uint16_t byteOrder; + uint16_t digits; + uint32_t reserved; + uint64_t count; +}; + +struct XYZVBinaryData +{ + double tdb; + double position[3]; + double velocity[3]; +}; diff --git a/src/celutil/bytes.h b/src/celutil/bytes.h index eff369dd9..4380d2e0f 100644 --- a/src/celutil/bytes.h +++ b/src/celutil/bytes.h @@ -18,6 +18,15 @@ #include +#ifndef __BYTE_ORDER__ +# ifdef _WIN32 +// FIXME: we assume that windows runs on LE hw only +# define __BYTE_ORDER__ 1234 +# else +# error "Unknown system or compiler" +# endif +#endif + /* Use the system byteswap.h definitions if we have them */ #ifdef HAVE_BYTESWAP_H #include diff --git a/src/tools/xyzv2bin/xyzv2bin.pl b/src/tools/xyzv2bin/xyzv2bin.pl new file mode 100644 index 000000000..32a7ba4b4 --- /dev/null +++ b/src/tools/xyzv2bin/xyzv2bin.pl @@ -0,0 +1,74 @@ +#!/usr/bin/perl + +use warnings; +use strict; +use Config; +use Scalar::Util qw(looks_like_number); + +die "Syntax: xyzv2bin.pl \n" if($#ARGV != 1); + +my $MAGIC = "CELXYZV"; +my $byte_order = $Config{byteorder} == 12345678 ? 1234 : $Config{byteorder}; +my $digits = $Config{doublemantbits} + 1; +my $reserved = 0; +my $count = -1; # unknown + +open(INFILE, '<', $ARGV[0]) || die "Unable to open $ARGV[0] for reading\n"; +open(OUTFILE, '>', $ARGV[1]) || die "Unable to open $ARGV[1] for writing\n"; +binmode OUTFILE; + +# only byte_order is in LE order, other values are in native order +my $header = pack "Z8vslq", ($MAGIC, $byte_order, $digits, $reserved, $count); +print OUTFILE $header; + +my @values; +my $chunk; +my $line; +$count = 0; + +outer: +while($line = ) +{ + # remove leading and terminating spaces + $line =~ s/^\s+|\s+$//g; + + # skip empty lines + next if length $line == 0; + + # remove comments + my $pos = index $line, '#'; + if ($pos > -1) + { + next if $pos == 0; + $line = substr $line, 0, $pos; + } + + @values = split /\s+/, $line; + if ($#values != 6) + { + print "Skipping bad line: $line\n"; + next; + } + + while (my $v = each @values) + { + unless (looks_like_number($v)) + { + print "Skipping bad line: $_\n"; + next outer; + } + } + + $chunk = pack "d7", @values; + print OUTFILE $chunk; + ++$count; +} + +seek OUTFILE, 0, 0; + +# print the header once again to save actual number or records +$header = pack "Z8vslq", ($MAGIC, $byte_order, $digits, $reserved, $count); +print OUTFILE $header; + +close OUTFILE; +close INFILE;