Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OCD format enhancements #2148

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 48 additions & 2 deletions src/fileformats/ocd_file_export.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@
#include <QTransform>
#include <QVarLengthArray>
#include <QVariant>
#include <QDateTime>
#include <QTimeZone>

#include "settings.h"
#include "core/georeferencing.h"
Expand Down Expand Up @@ -2484,12 +2486,56 @@ void OcdFileExport::exportObjects(OcdFile<Format>& file)
* Object setup which depends on the type features, not on minor type variations of members.
*/
template< class OcdObject >
void OcdFileExport::handleObjectExtras(const Object* object, OcdObject& ocd_object, typename OcdObject::IndexEntryType& entry)
void OcdFileExport::fillV9ObjectExtras(const Object* object, OcdObject& ocd_object, typename OcdObject::IndexEntryType& entry)
{
// Extra entry members since V9
entry.type = ocd_object.type;
entry.status = Ocd::ObjectNormal;
entry.color = convertColor(object->getSymbol()->guessDominantColor());
entry.color = ocd_object.color = convertColor(object->getSymbol()->guessDominantColor());
}


template< class OcdObject >
void OcdFileExport::fillV12ObjectExtras(const Object* object, OcdObject& ocd_object, typename OcdObject::IndexEntryType& entry)
{
Q_UNUSED(entry)

// Extra members since V12
ocd_object.server_object_id = -1;

static auto const dawn_of_time = QDate(1899, 12, 30).startOfDay(Qt::UTC);
auto const now = dawn_of_time.msecsTo(QDateTime::currentDateTimeUtc()) / 86400000.0;
auto const ctime = QDateTime::fromString(object->getTag(QString::fromLatin1("ctime")), Qt::ISODateWithMs);
auto const mtime = QDateTime::fromString(object->getTag(QString::fromLatin1("mtime")), Qt::ISODateWithMs);

if (ctime.isValid())
{
ocd_object.creation_date = dawn_of_time.msecsTo(ctime) / 86400000.0;
if (mtime.isValid())
ocd_object.modification_date = dawn_of_time.msecsTo(mtime) / 86400000.0;
else
ocd_object.modification_date = now;
}
else
{
ocd_object.creation_date = now;
ocd_object.modification_date = now;
}
}


template< class OcdObject >
void OcdFileExport::handleObjectExtras(const Object* object, OcdObject& ocd_object, typename OcdObject::IndexEntryType& entry)
{
fillV9ObjectExtras(object, ocd_object, entry);
fillV12ObjectExtras(object, ocd_object, entry);
}


template< >
void OcdFileExport::handleObjectExtras<Ocd::ObjectV9>(const Object* object, Ocd::ObjectV9& ocd_object, typename Ocd::ObjectV9::IndexEntryType& entry)
{
fillV9ObjectExtras(object, ocd_object, entry);
}


Expand Down
6 changes: 6 additions & 0 deletions src/fileformats/ocd_file_export.h
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,12 @@ class OcdFileExport : public Exporter
template< class Format >
void exportObjects(OcdFile<Format>& file);

template< class OcdObject >
void fillV9ObjectExtras(const Object* object, OcdObject& ocd_object, typename OcdObject::IndexEntryType& entry);

template< class OcdObject >
void fillV12ObjectExtras(const Object* object, OcdObject& ocd_object, typename OcdObject::IndexEntryType& entry);

template< class OcdObject >
void handleObjectExtras(const Object* object, OcdObject& ocd_object, typename OcdObject::IndexEntryType& entry);

Expand Down
58 changes: 56 additions & 2 deletions src/fileformats/ocd_file_import.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
#include <QTextCodec>
#include <QTextDecoder>
#include <QVariant>
#include <QDateTime>

#include "settings.h"
#include "core/georeferencing.h"
Expand Down Expand Up @@ -1431,12 +1432,30 @@ void OcdFileImport::setupLineSymbolPointSymbols(OcdFileImport::OcdImportedLineSy

// Special case main_gap == 0: swapped in Mapper
auto gaps_swapped = attributes.sec_gap && !attributes.main_gap && attributes.main_length;

// Store the OCD number of gaps/symbols on the line. The Mapper notion of the
// number of symbols on line differs from the OCD interpretation but we
// retain this information for enhanced compatibility.
switch (attributes.min_sym)
{
case 0:
line_symbol->show_at_least_one_symbol = true;
break;
case -1:
line_symbol->show_at_least_one_symbol = false;
break;
default:
line_symbol->show_at_least_one_symbol = true;
addWarning(OcdFileImport::tr("Cannot represent %1 gaps/symbols on line symbol %2. Replacing with 1 gap/symbol per dash.")
.arg(attributes.min_sym)
.arg(line_symbol->getName()));
break;
}
if (attributes.primary_data_size > 0)
{
line_symbol->mid_symbol_placement = gaps_swapped ? LineSymbol::CenterOfDashGroup : LineSymbol::CenterOfGap;
line_symbol->mid_symbols_per_spot = attributes.num_prim_sym;
line_symbol->mid_symbol_distance = convertLength(attributes.prim_sym_dist);
line_symbol->show_at_least_one_symbol = true;
line_symbol->mid_symbol = new OcdImportedPointSymbol();
setupPointSymbolPattern(line_symbol->mid_symbol, attributes.primary_data_size, elements);
if (attributes.secondary_data_size > 0)
Expand All @@ -1447,7 +1466,6 @@ void OcdFileImport::setupLineSymbolPointSymbols(OcdFileImport::OcdImportedLineSy
{
line_symbol->mid_symbol_placement = gaps_swapped ? LineSymbol::CenterOfGap : LineSymbol::CenterOfDashGroup;
line_symbol->mid_symbols_per_spot = 1;
line_symbol->show_at_least_one_symbol = true;
line_symbol->mid_symbol = new OcdImportedPointSymbol();
setupPointSymbolPattern(line_symbol->mid_symbol, attributes.secondary_data_size, elements);
}
Expand Down Expand Up @@ -1845,6 +1863,38 @@ void OcdFileImport::setupPointSymbolPattern(PointSymbol* symbol, std::size_t dat
}
}


template < class O >
void setObjectDates(Object* object, const O& ocd_object)
{
// The OCD file format authors decided to store object creation and
// modification timestamps but did not specify the time zone.
// We will assign UTC time zone to the times to avoid DST and time
// zone difference headaches.
static auto const dawn_of_time = QDate(1899, 12, 30).startOfDay(Qt::UTC);
auto const ctime = dawn_of_time.addMSecs(std::round(ocd_object.creation_date * 86400000)); // will overflow in about 290 Ma
auto const mtime = dawn_of_time.addMSecs(std::round(ocd_object.modification_date * 86400000));
object->setTag(QString::fromLatin1("ctime"), ctime.toString(Qt::ISODateWithMs));
object->setTag(QString::fromLatin1("mtime"), mtime.toString(Qt::ISODateWithMs));
};


template <>
void setObjectDates(Object* object, const Ocd::ObjectV8& ocd_object)
{
Q_UNUSED(object)
Q_UNUSED(ocd_object)
}


template <>
void setObjectDates(Object* object, const Ocd::ObjectV9& ocd_object)
{
Q_UNUSED(object)
Q_UNUSED(ocd_object)
}


template< class O >
Object* OcdFileImport::importObject(const O& ocd_object, MapPart* part)
{
Expand Down Expand Up @@ -1881,6 +1931,7 @@ Object* OcdFileImport::importObject(const O& ocd_object, MapPart* part)
Object* object = importRectangleObject(ocd_object, part, rectangle_info[ocd_object.symbol]);
if (!object)
addWarning(OcdFileImport::tr("Unable to import rectangle object"));
setObjectDates(object, ocd_object);
return object;
}

Expand Down Expand Up @@ -1908,6 +1959,7 @@ Object* OcdFileImport::importObject(const O& ocd_object, MapPart* part)
p->setPosition(pos.nativeX(), pos.nativeY());

p->setMap(map);
setObjectDates(p, ocd_object);
return p;
}
else if (symbol->getType() == Symbol::Text)
Expand All @@ -1927,6 +1979,7 @@ Object* OcdFileImport::importObject(const O& ocd_object, MapPart* part)
return nullptr;
}
t->setMap(map);
setObjectDates(t, ocd_object);
return t;
}
else if (symbol->getType() == Symbol::Line || symbol->getType() == Symbol::Area || symbol->getType() == Symbol::Combined)
Expand All @@ -1938,6 +1991,7 @@ Object* OcdFileImport::importObject(const O& ocd_object, MapPart* part)
fillPathCoords(p, symbol->getContainedTypes() & Symbol::Area, ocd_object.num_items, reinterpret_cast<const Ocd::OcdPoint32 *>(ocd_object.coords));
p->recalculateParts();
p->setMap(map);
setObjectDates(p, ocd_object);
return p;
}

Expand Down
6 changes: 3 additions & 3 deletions src/fileformats/ocd_types_v12.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,11 @@ namespace Ocd
qint32 color;
quint16 line_width;
quint16 diam_flags;
quint32 server_object_id;
qint32 server_object_id;
quint32 height;
quint64 creation_date;
double creation_date;
quint32 multi_rep_id;
quint64 modification_date;
double modification_date;
quint32 num_items;
quint16 num_text;
quint16 object_string_length;
Expand Down