//
// model.h
//
// Cave survey model.
//
// Copyright (C) 2000-2003,2005 Mark R. Shinwell
// Copyright (C) 2001-2003,2004,2005,2006,2010,2011,2012,2013,2014,2015,2016,2018 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, see
// .
//
#ifndef model_h
#define model_h
#include
#include "labelinfo.h"
#include "vector3.h"
#include
#include
#include
#include
using namespace std;
class MainFrm;
class PointInfo : public Point {
int date = -1;
public:
PointInfo() : Point() { }
explicit PointInfo(const img_point & pt) : Point(pt) { }
PointInfo(const img_point & pt, int date_) : Point(pt), date(date_) { }
PointInfo(const Point & p, int date_) : Point(p), date(date_) { }
int GetDate() const { return date; }
};
class XSect {
friend class MainFrm;
const LabelInfo* stn;
int date;
double l, r, u, d;
double right_bearing = 0.0;
public:
XSect(const LabelInfo* stn_, int date_,
double l_, double r_, double u_, double d_)
: stn(stn_), date(date_), l(l_), r(r_), u(u_), d(d_) { }
double GetL() const { return l; }
double GetR() const { return r; }
double GetU() const { return u; }
double GetD() const { return d; }
double get_right_bearing() const { return right_bearing; }
void set_right_bearing(double right_bearing_) {
right_bearing = right_bearing_;
}
int GetDate() const { return date; }
const wxString& GetLabel() const { return stn->GetText(); }
const Point& GetPoint() const { return *stn; }
double GetX() const { return stn->GetX(); }
double GetY() const { return stn->GetY(); }
double GetZ() const { return stn->GetZ(); }
friend Vector3 operator-(const XSect& a, const XSect& b);
};
inline Vector3 operator-(const XSect& a, const XSect& b) {
return *(a.stn) - *(b.stn);
}
class traverse : public vector {
public:
int n_legs = 0;
// Bitmask of img_FLAG_SURFACE, img_FLAG_SPLAY and img_FLAG_DUPLICATE.
int flags = 0;
// An img_STYLE_* value.
int style = 0;
double length = 0.0;
enum { ERROR_3D = 0, ERROR_H = 1, ERROR_V = 2 };
double errors[3] = {-1, -1, -1};
wxString name;
explicit
traverse(const char* name_) : name(name_, wxConvUTF8) {
if (name.empty() && !name_[0]) {
// If name isn't valid UTF-8 then this conversion will
// give an empty string. In this case, assume that the
// label is CP1252 (the Microsoft superset of ISO8859-1).
static wxCSConv ConvCP1252(wxFONTENCODING_CP1252);
name = wxString(name_, ConvCP1252);
if (name.empty()) {
// Or if that doesn't work (ConvCP1252 doesn't like
// strings with some bytes in) let's just go for
// ISO8859-1.
name = wxString(name_, wxConvISO8859_1);
}
}
}
};
class SurveyFilter {
std::set> filters;
std::set> redundant_filters;
// Default to the Survex standard separator - then a filter created before
// the survey separator is known is likely to not need rebuilding.
wxChar separator = '.';
public:
SurveyFilter() {}
void add(const wxString& survey);
void remove(const wxString& survey);
void clear() { filters.clear(); redundant_filters.clear(); }
bool empty() const { return filters.empty(); }
void SetSeparator(wxChar separator_);
bool CheckVisible(const wxString& name) const;
};
/// Cave model.
class Model {
list traverses[8];
mutable list> tubes;
private:
list m_Labels;
Vector3 m_Ext;
double m_DepthMin, m_DepthExt;
int m_DateMin, m_DateExt;
bool complete_dateinfo;
int m_NumEntrances = 0;
int m_NumFixedPts = 0;
int m_NumExportedPts = 0;
bool m_HasUndergroundLegs = false;
bool m_HasSplays = false;
bool m_HasDupes = false;
bool m_HasSurfaceLegs = false;
bool m_HasErrorInformation = false;
bool m_IsExtendedElevation = false;
mutable bool m_TubesPrepared = false;
// Character separating survey levels (often '.')
wxChar m_separator;
wxString m_Title, m_cs_proj, m_DateStamp;
time_t m_DateStamp_numeric;
Vector3 m_Offset;
// We lazily set the higher bits of LabelInfo::flags to a value to give us
// the sort order we want via integer subtraction. This is done the first
// time this sort happens after loading a file.
bool added_plot_order_keys = false;
void do_prepare_tubes() const;
void CentreDataset(const Vector3& vmin);
public:
int Load(const wxString& file, const wxString& prefix);
const Vector3& GetExtent() const { return m_Ext; }
const wxString& GetSurveyTitle() const { return m_Title; }
const wxString& GetDateString() const { return m_DateStamp; }
time_t GetDateStamp() const { return m_DateStamp_numeric; }
double GetDepthExtent() const { return m_DepthExt; }
double GetDepthMin() const { return m_DepthMin; }
bool HasCompleteDateInfo() const { return complete_dateinfo; }
int GetDateExtent() const { return m_DateExt; }
int GetDateMin() const { return m_DateMin; }
int GetNumFixedPts() const { return m_NumFixedPts; }
int GetNumExportedPts() const { return m_NumExportedPts; }
int GetNumEntrances() const { return m_NumEntrances; }
bool HasUndergroundLegs() const { return m_HasUndergroundLegs; }
bool HasSplays() const { return m_HasSplays; }
bool HasDupes() const { return m_HasDupes; }
bool HasSurfaceLegs() const { return m_HasSurfaceLegs; }
bool HasTubes() const { return !tubes.empty(); }
bool HasErrorInformation() const { return m_HasErrorInformation; }
bool IsExtendedElevation() const { return m_IsExtendedElevation; }
wxChar GetSeparator() const { return m_separator; }
const wxString& GetCSProj() const { return m_cs_proj; }
const Vector3& GetOffset() const { return m_Offset; }
list::const_iterator
traverses_begin(unsigned flags, const SurveyFilter* filter) const {
if (flags >= sizeof(traverses)) return traverses[0].end();
auto it = traverses[flags].begin();
if (filter) {
while (it != traverses[flags].end() &&
!filter->CheckVisible(it->name)) {
++it;
}
}
return it;
}
list::const_iterator
traverses_next(unsigned flags, const SurveyFilter* filter,
list::const_iterator it) const {
++it;
if (filter) {
while (it != traverses[flags].end() &&
!filter->CheckVisible(it->name)) {
++it;
}
}
return it;
}
list::const_iterator traverses_end(unsigned flags) const {
if (flags >= sizeof(traverses)) flags = 0;
return traverses[flags].end();
}
list>::const_iterator tubes_begin() const {
prepare_tubes();
return tubes.begin();
}
list>::const_iterator tubes_end() const {
return tubes.end();
}
list>::iterator tubes_begin() {
prepare_tubes();
return tubes.begin();
}
list>::iterator tubes_end() {
return tubes.end();
}
list::const_iterator GetLabels() const {
return m_Labels.begin();
}
list::const_iterator GetLabelsEnd() const {
return m_Labels.end();
}
list::const_reverse_iterator GetRevLabels() const {
return m_Labels.rbegin();
}
list::const_reverse_iterator GetRevLabelsEnd() const {
return m_Labels.rend();
}
list::iterator GetLabelsNC() {
return m_Labels.begin();
}
list::iterator GetLabelsNCEnd() {
return m_Labels.end();
}
void SortLabelsByName();
void SortLabelsByPlotOrder();
void prepare_tubes() const {
if (!m_TubesPrepared) {
do_prepare_tubes();
m_TubesPrepared = true;
}
}
};
#endif