Backport binary XYZV format implementation from 1.7

pull/716/head
Hleb Valoshka 2019-01-12 21:57:18 +03:00
parent cd8426ebc9
commit 0ac3e61fef
4 changed files with 182 additions and 0 deletions

View File

@ -21,6 +21,7 @@
#include <celengine/astro.h>
#include <celengine/orbit.h>
#include <celengine/samporbit.h>
#include <celengine/xyzvbinary.h>
using namespace std;
@ -870,6 +871,77 @@ template <typename T> SampledOrbitXYZV<T>* LoadSampledOrbitXYZV(const string& fi
return orbit;
}
/* Load a binary xyzv sampled trajectory file.
*/
template <typename T> SampledOrbitXYZV<T>*
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<char*>(&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<double>::digits)
{
cerr << "Unsupported digits number " << header.digits
<< ", expected " << std::numeric_limits<double>::digits << ".\n";
return NULL;
}
if (header.count == 0)
return NULL;
SampledOrbitXYZV<T>* orbit = new SampledOrbitXYZV<T>(interpolation);
double lastSampleTime = -numeric_limits<T>::infinity();
while (in.good())
{
XYZVBinaryData data;
if (!in.read(reinterpret_cast<char*>(&data), sizeof(data)))
break;
double tdb = data.tdb;
Vec3d* position = reinterpret_cast<Vec3d*>(data.position);
Vec3d* velocity = reinterpret_cast<Vec3d*>(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);
}

View File

@ -0,0 +1,19 @@
#pragma once
#include <stdint.h>
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];
};

View File

@ -18,6 +18,15 @@
#include <celutil/util.h>
#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 <byteswap.h>

View File

@ -0,0 +1,74 @@
#!/usr/bin/perl
use warnings;
use strict;
use Config;
use Scalar::Util qw(looks_like_number);
die "Syntax: xyzv2bin.pl <infile> <outfile>\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 = <INFILE>)
{
# 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;