Files
secondo/Algebras/TIN/Tin.h
2026-01-23 17:03:45 +08:00

841 lines
21 KiB
C++

/*
----
This file is part of SECONDO.
Copyright (C) 2004-2007, University in Hagen, Department of Computer Science,
Database Systems for New Applications.
SECONDO 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.
SECONDO 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 SECONDO; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
----
*/
#ifndef TIN_H_
#define TIN_H_
#include "TinHelper.h"
#include "TinPart.h"
#include "AlgoFortune.h"
#include <vector>
#include <map>
#include <deque>
#include <stack>
#include "SecondoDependencies.h"
#include "TinLogging.h"
#include <string>
namespace routeplanningalgebra {
class TinForRoutePlanning;
}
namespace tin {
class EventQueue;
class TinAttribute;
class ColumnKey {
private:
VERTEX_COORDINATE xFrom;
VERTEX_COORDINATE xTo;
mutable uint32_t noPart;
public:
ColumnKey(VERTEX_COORDINATE ixfrom, VERTEX_COORDINATE ixto,
uint32_t inoPart);
ColumnKey(VERTEX_COORDINATE ix, uint32_t inoPart);
ColumnKey() {
}
;
~ColumnKey();
uint32_t getNoPart() const {
return noPart;
}
void setNoPart(uint32_t inoPart) const {
noPart = inoPart;
}
bool operator<(const ColumnKey & cpart) const;
};
#ifndef UNIT_TEST
class Tin: public noncopyable
#else
class Tin: public noncopyable
#endif
{
#ifndef UNIT_TEST
friend class TinAttribute;
#endif
friend class EventQueue;
friend class routeplanningalgebra::TinForRoutePlanning;
protected:
std::deque<TinPart*> tinParts;
TinConfiguration config;
AbstractType tinTypeCurrent;
TinFeatures features;
TIN_SIZE noParts;
#ifndef UNIT_TEST
mutable SmiRecordFile file;
SmiRecordId contentId;
R_Tree<2, uint32_t>* rtree;
#endif
std::map<ColumnKey, TinPart*> columnMap;
EventQueue* constructionQueue;
bool defined;
protected:
////////Construction/Destruction/////////////////////////////////
#ifndef UNIT_TEST
Tin(const bool isTemp) :
file(false,0,isTemp) {
LOGP
noParts = 0;
constructionQueue = 0;
config = TinConfiguration::DEFAULT;
rtree = 0;
defined = false;
LOGP}
;
#else
Tin() {
constructionQueue = 0;
noParts=0;
};
#endif
Tin * clone() const;
void cloneTin(Tin * result) const;
public:
Tin(VertexContainerSet * vertices,
const TinConfiguration &conf = TinConfiguration::DEFAULT,
const bool isTemp = false);
Tin(const TinConfiguration & conf, const bool isTemp);
~Tin();
////////Manipulation/////////////////////////////////////////////
public:
void unaryOp(VERTEX_Z (*op)(VERTEX_Z z));
void setDefined(bool def = true) {
defined = def;
}
bool resetConfiguration(const TinConfiguration& conf) {
if(noParts != 0)
return false;
config = conf;
return true;
}
protected:
void initSimpleLayout();
void initColumnLayout(VertexContainerSet & vc);
void finishLayout(bool updatePartsFeatures = true);
void triangulateSection(VertexContainerSet * vc);
void finishTriangulation();
void triangulateBulk(VertexContainerSet * vc);
void addTriangle(const Vertex & v1,const Vertex & v2,const Vertex & v3,
Triangle** newtriangle);
void addTriangle_p(const Vertex & v1,const Vertex & v2,const Vertex & v3,
Triangle** newtriangle);
void addPart(TinPart * p);
TinPart * getNewPart();
void finishPart(std::pair<const ColumnKey,TinPart*>& partpair,
bool updatePartFeat = false);
#ifndef UNIT_TEST
void unaryOp(void* function,Tin * result);
#endif
///////Query/////////////////////////////////////////////////////
public:
bool isDefined()const {
return defined;
}
class triangle_iterator {
protected:
Tin* tin;
std::deque<TinPart*>::iterator itParts;
TinPart::iterator itTriangles;
int currentPart;
protected:
triangle_iterator() {
tin = 0;
currentPart = 0;
}
public:
triangle_iterator(Tin* itin) {
tin = itin;
currentPart = 0;
itParts = tin->tinParts.begin();
if (itParts != tin->tinParts.end())
itTriangles = (*itParts)->begin();
}
Triangle* operator*() {
return (*itTriangles);
}
Tin::triangle_iterator& operator++(int) {
itTriangles++;
if (*itTriangles)
return *this;
else {
if (itParts != tin->tinParts.end())
(*itParts)->unloadContentData();
itParts++;
currentPart++;
if (itParts != tin->tinParts.end())
itTriangles = (*itParts)->begin();
return *this;
}
}
int getCurrentPart() {
return currentPart;
}
};
Tin::triangle_iterator begin() {
return Tin::triangle_iterator(this);
}
Triangle::triangleWalker getWalker(const Point_p & p);
VERTEX_Z atlocation(const Point_p& p);
const Rectangle& bbox() const;
VERTEX_Z minimum() const;
VERTEX_Z maximum() const;
MemoryState getMemoryState()const
{
return config.memoryState;
}
TIN_SIZE getSizeInMemory()
{
//ATTENTION this can only be an estimate,
//since STL containers do not expose their size
std::deque<TinPart *>::iterator it = tinParts.begin();
TIN_SIZE size = 0;
size += sizeof(*this);
//if(rtree)
//size +=rtree->???
//columnMap neglected as well as incompleteParts
while (it != tinParts.end()) {
LOGP
size +=(*it)->getSizeInMemory();
++it;
}
return size;
}
TIN_SIZE estimateMaxSizeInMemory(int inoParts = -1)const
{
TIN_SIZE size = 0;
//only a rough estimate !
size += sizeof(*this);
if(inoParts == -1)
size +=noParts * TinPart::estimateMaxSizeInMemory(config);
else
size +=inoParts * TinPart::estimateMaxSizeInMemory(config);
return size;
}
const TinConfiguration& getConfiguration()const
{
return config;
}
Triangle* findNeighbor(const Edge& commonEdge, Triangle* caller);
bool hasTriangle(Vertex& v1, Vertex& v2, Vertex& v3);
bool checkDelaunay();
bool checkNeighborRelations();
protected:
TinPart * getNextPartIntersecting(Rectangle& bbox);
double calculateNoColumns(VertexContainerSet & vc);
double calculateNoRows(VertexContainerSet & vc);
bool canAddTriangle(const Triangle & t, std::string & msg);
///////Presentation//////////////////////////////////////////////
public:
void print(std::ostream& os = std::cout);
void saveSTLFile(std::ostream& os = std::cout);
///////Persistence///////////////////////////////////////////////
public:
TIN_SIZE getPartHeadOrigin()const;
protected:
void setMemoryState(MemoryState st);
void setMemoryStateGradual();
TIN_SIZE getSizeOnDisc() const;
void unloadAllParts();
void loadAllParts();
#ifndef UNIT_TEST
void deleteFile();
bool open(SmiRecord& valueRecord,bool bypass = false,
SmiFileId ifileid = 0, SmiRecordId irec = 0);
bool openParts(bool bulkload = false);
TinPart * getPartFromDisc(SmiRecord & valueRecord,bool bulkload = false);
TinPart * getPartFromDisc(uint32_t idx);
public:
bool save(SmiRecord& valueRecord,bool bypass =false);
SmiRecordFile* getFile();
#endif
/////////////////////////////////////////////////////////////////
#ifndef UNIT_TEST
///////Secondo atom type required functions//////////////////////
static void parseInTinConfig(const ListExpr confExp,
TinConfiguration& conf);
static std::string BasicType();
static ListExpr Property();
static Word Create(const ListExpr typeInfo);
static void Delete(const ListExpr typeInfo, Word & w);
static ListExpr Out(ListExpr typeInfo, Word value);
static Word In(const ListExpr typeInfo, const ListExpr instance,
const int errorPos, ListExpr& errorInfo, bool& correct);
static void Close(const ListExpr typeInfo, Word & w);
static bool Open(SmiRecord& valueRecord, size_t& offset,
const ListExpr typeInfo, Word& value);
static bool Save(SmiRecord& valueRecord, size_t& offset,
const ListExpr typeInfo, Word& value);
static Word Clone(const ListExpr typeInfo, const Word & w);
static int sizeOfObj();
static bool CheckType(ListExpr type, ListExpr & errorInfo) {
return listutils::isSymbol(type,Tin::BasicType());
}
/////Operators///////////////////////////////////////////////////
static ListExpr unaryOp_tm(ListExpr args);
static int unaryOp_vm(Word* args, Word& result, int message, Word& local,
Supplier s);
static ListExpr tin2stlfile_tm(ListExpr args);
static int tin2stlfile_vm(Word* args, Word& result, int message, Word& local,
Supplier s);
static ListExpr atlocation_tm(ListExpr args);
static int atlocation_sf(ListExpr args);
static int atlocation_vm(Word* args, Word& result, int message, Word& local,
Supplier s);
static ListExpr tinmin_tm(ListExpr args);
static int tinmin_sf(ListExpr args);
static int tinmin_vm(Word* args, Word& result, int message, Word& local,
Supplier s);
static ListExpr tinmax_tm(ListExpr args);
static int tinmax_sf(ListExpr args);
static int tinmax_vm(Word* args, Word& result, int message, Word& local,
Supplier s);
static ListExpr createTin_tm(ListExpr args);
static int createTin_sf(ListExpr args);
template <typename N>
static int createTin_vm(Word* args, Word& result, int message, Word& local,
Supplier s);
static ListExpr tin2tuplestream_tm(ListExpr args);
static int tin2tuplestream_vm(Word* args, Word& result, int message,
Word& local, Supplier s);
static ListExpr tin2tinattribute_tm(ListExpr args);
static int tin2tinattribute_vm(Word* args, Word& result, int message,
Word& local, Supplier s);
static ListExpr raster2tin_tm(ListExpr args);
static int raster2tin_sf(ListExpr args);
template<class T>
static int raster2tin_vm(Word* args, Word& result, int message,
Word& local, Supplier s);
/////////////////////////////////////////////////////////////////
#endif
};
#ifndef UNIT_TEST
class TinAttribute: public Attribute, public TinPart {
protected:
Flob binData;
public:
TinAttribute() :
TinPart(true) {
}
TinAttribute(bool defined) :
Attribute(defined), binData(0) {
config = TinConfiguration::ATTRIBUTE;
}
TinAttribute(TinPart & part);
TinPart* clone(Tin*tt);
Triangle* getNeighbor(const Edge& commonEdge, Triangle* caller);
bool isContentDataLoaded() const {
return true;
}
void loadContentData() {
}
void unloadContentData() {
}
void deleteContentReference() {
}
void addContentReference() {
}
TIN_SIZE getSizeOnDisc() const {
LOGP
TIN_SIZE size = getSizeOnDisc_content();
LOGP
return size;
}
static TIN_SIZE getSizeOnDisc_head() {
LOGP
TIN_SIZE size = sizeof(TIN_SIZE) + sizeof(TIN_SIZE)
+ TinFeatures::getSizeOnDisc() + sizeof(uint8_t);
return size;
}
bool save(SmiRecord& valueRecord) {
throw std::runtime_error("Not implemented for TinAttribute.");
}
void serialize(char* storage, size_t& offset) {
throw std::runtime_error("Not implemented for TinAttribute.");
}
void rebuild(char* state, size_t& offset) {
throw std::runtime_error("Not implemented for TinAttribute.");
}
protected:
void save_content() {
throw std::runtime_error("Not implemented for TinAttribute.");
}
void open_content() {
throw std::runtime_error("Not implemented for TinAttribute.");
}
bool open(SmiRecord& valueRecord) {
throw std::runtime_error("Not implemented for TinAttribute.");
}
bool open_head(SmiRecord& valueRecord, uint32_t idx) {
throw std::runtime_error("Not implemented for TinAttribute.");
}
/////Secondo attribute type required methods/////////////////////
public:
size_t Sizeof() const {
LOGP
return sizeof(*this);
}
int Compare(const Attribute *rhs) const {
TinAttribute * attr = (TinAttribute *) rhs;
bool tok = false;
bool tinisequal = true;
const Vertex *av, *tv;
if (!this->IsDefined() || !attr->IsDefined())
return 1;
//if rhs has more or less triangles -> unequal
//the tin with more triangles is bigger
if (this->noTriangles < attr->noTriangles)
return -1;
if (this->noTriangles > attr->noTriangles)
return 1;
const_cast<TinAttribute *>(this)->syncFlob(false);
const_cast<TinAttribute *>(attr)->syncFlob(false);
//bbox check -> unequal
if (this->features == attr->features) {
//compare all triangles of this with rhs
for (uint32_t ithis = 0; ithis < this->noTriangles; ithis++) {
tok = false;
for (uint32_t iattr = 0; iattr < attr->noTriangles; iattr++) {
if (attr->arTriangles[iattr] == this->arTriangles[ithis]) {
tok = true;
break;
}
}
if (!tok) {
//if one is missing in rhs -> unequal
tinisequal = false;
break;
}
}
} else
tinisequal = false;
if (tinisequal)
return 0;
//unequal then order defined by the first number deviating
for (uint32_t index = 0; index < this->noTriangles; index++) {
for (int vert = 1; vert < 4; vert++) {
av = attr->arTriangles[index].getVertex(vert);
tv = this->arTriangles[index].getVertex(vert);
if (av->getY() != tv->getY()) {
if (av->getY() < tv->getY())
return 1;
else
return -1;
} else if (av->getX() != tv->getX()) {
if (av->getX() < tv->getX())
return 1;
else
return -1;
} else if (av->getZ() != tv->getZ()) {
if (av->getZ() < tv->getZ())
return 1;
else
return -1;
}
}
}
throw std::runtime_error("This line"
" should never be reached.(TinAttribute::Compare)");
}
Attribute * Clone() const {
LOGP
TinAttribute* newattr = new TinAttribute(false);
bool n;
const Vertex * v1, *v2, *v3;
LOGP
const_cast<TinAttribute *>(this)->syncFlob(false);
if (IsDefined()) {
newattr->config = config;
newattr->noTriangles = 0;
newattr->features = features;
newattr->ismodified = true;
newattr->pVertexContainer = pVertexContainer->clone_empty();
newattr->arTriangles = new Triangle[noTriangles];
for (int i = 0; i < noTriangles; i++) {
v1 = newattr->pVertexContainer->insertVertex(
arTriangles[i].getVertex(1), n);
v2 = newattr->pVertexContainer->insertVertex(
arTriangles[i].getVertex(2), n);
v3 = newattr->pVertexContainer->insertVertex(
arTriangles[i].getVertex(3), n);
newattr->constructTriangle(v1, v2, v3);
newattr->noTriangles++;
LOGP }
newattr->noVertices = newattr->pVertexContainer->getNoVertices();
newattr->contentRefs = 0;
newattr->noTrianglesMax = noTriangles;
newattr->SetDefined(true);
} else {
newattr->SetDefined(false);
}
newattr->syncFlob(true);
return newattr;
}
size_t HashValue() const {
return (uint) (features.m_maxValue - features.m_minValue);
}
void CopyFrom(const Attribute* right) {
LOGP
Attribute * attr1 = const_cast<Attribute *>(right);
TinAttribute * attr = static_cast<TinAttribute *>(attr1);
attr->syncFlob(false);
bool n;
const Vertex * v1, *v2, *v3;
LOGP
this->noTriangles = 0;
this->features = attr->features;
this->ismodified = true;
this->pVertexContainer = attr->pVertexContainer->clone_empty();
this->arTriangles = new Triangle[attr->noTriangles];
for (int i = 0; i < attr->noTriangles; i++) {
v1 = this->pVertexContainer->insertVertex(
attr->arTriangles[i].getVertex(1), n);
v2 = this->pVertexContainer->insertVertex(
attr->arTriangles[i].getVertex(2), n);
v3 = this->pVertexContainer->insertVertex(
attr->arTriangles[i].getVertex(3), n);
this->constructTriangle(v1, v2, v3);
this->noTriangles++;
LOGP }
this->noVertices = this->pVertexContainer->getNoVertices();
this->contentRefs = 0;
this->noTrianglesMax = attr->noTriangles;
this->syncFlob(true);
return;
}
inline int NumOfFLOBs() const {
LOGP
return 1;
}
inline virtual Flob* GetFLOB(const int i) {
LOGP
return &binData;
}
bool Adjacent(const Attribute *attrib) const {
return true;
}
static bool Open(SmiRecord& valueRecord, size_t& offset,
const ListExpr typeInfo, Word& value);
static bool Save(SmiRecord& valueRecord, size_t& offset,
const ListExpr typeInfo, Word& value);
static void* Cast(void * addr) {
LOGP
return new (addr) TinAttribute();
}
static std::string BasicType();
static bool CheckType(ListExpr type, ListExpr & errorInfo) {
return listutils::isSymbol(type, TinAttribute::BasicType());
}
static ListExpr Property();
static Word Create(const ListExpr typeInfo);
static void Delete(const ListExpr typeInfo, Word & w);
static ListExpr Out(ListExpr typeInfo, Word value);
static Word In(const ListExpr typeInfo, const ListExpr instance,
const int errorPos, ListExpr& errorInfo, bool& correct);
static int sizeOfObj();
static void Close(const ListExpr typeInfo, Word & w);
static Word Clone(const ListExpr typeInfo, const Word & w);
/////Operators///////////////////////////////////////////////////
static ListExpr tinattribute2tin_tm(ListExpr args);
static int tinattribute2tin_sf(ListExpr args);
static int tinattribute2tin_vm(Word* args, Word& result, int message,
Word& local, Supplier s);
static int atlocation_vm(Word* args, Word& result, int message,
Word& local, Supplier s);
static int tinmin_vm(Word* args, Word& result, int message, Word& local,
Supplier s);
static int tinmax_vm(Word* args, Word& result, int message, Word& local,
Supplier s);
/////////////////////////////////////////////////////////////////
protected:
void setMemoryState(MemoryState st) {
}
void Serialize2Flob();
void RebuildFromFlob();
void syncFlob(bool toFlob) {
if (toFlob) {
Serialize2Flob();
} else {
RebuildFromFlob();
}
}
};
#endif
#ifndef UNIT_TEST
const std::string map_atlocation[2][4] = { { Tin::BasicType(),
CcReal::BasicType(), CcReal::BasicType(), CcReal::BasicType() }, {
TinAttribute::BasicType(), CcReal::BasicType(), CcReal::BasicType(),
CcReal::BasicType() } };
const std::string map_min[2][2] = { { Tin::BasicType(), CcReal::BasicType() }, {
TinAttribute::BasicType(), CcReal::BasicType() } };
const std::string map_max[2][2] = { { Tin::BasicType(), CcReal::BasicType() }, {
TinAttribute::BasicType(), CcReal::BasicType() } };
template<typename N>
int Tin::createTin_vm(Word* args, Word& result, int message, Word& local,
Supplier s) {
LOGP
Stream<Tuple> stream(args[0]);
CcInt * partSize = (CcInt*) args[1].addr;
Vertex v, priorv;
Attribute* aPoint, *aHeightVal;
VertexContainerSet* vc = new VertexContainerSet(
VERTEX_CONTAINER_BIG_SIZE);
result = qp->ResultStorage(s);
Tin* resultTin = (Tin*) result.addr;
if (partSize)
resultTin->config.maxSizePart = partSize->GetIntval();
else
resultTin->config.maxSizePart = TIN_PART_STANDARD_SIZE;
try {
if (!args[0].addr)
throw std::runtime_error("Null pointer as input.(Tin::createTin_vm)");
resultTin->setMemoryStateGradual();
stream.open();
Tuple * tup;
if ((tup = stream.request()) != 0) {
aPoint = tup->GetAttribute(0);
aHeightVal = tup->GetAttribute(1);
v.setX(((::Point*) aPoint)->GetX());
v.setY(((::Point*) aPoint)->GetY());
v.setZ(((N*) aHeightVal)->GetValue());
vc->insertVertex_p(&v);
priorv = v;
tup->DeleteIfAllowed();
}
while (((tup = stream.request()) != 0)) {
aPoint = tup->GetAttribute(0);
aHeightVal = tup->GetAttribute(1);
LOGP
v.setX(((::Point*) aPoint)->GetX());
v.setY(((::Point*) aPoint)->GetY());
LOGP
v.setZ(((N*) aHeightVal)->GetValue());
LOGP
LOG(v.getY())
LOG(priorv.getY())
if (v.getY() > priorv.getY())
throw std::runtime_error(E_CREATETIN_VM);
if (v.getY() != priorv.getY() && resultTin->calculateNoRows(*vc) >= 1) {
resultTin->triangulateSection(vc);
vc = new VertexContainerSet(VERTEX_CONTAINER_BIG_SIZE);
}
vc->insertVertex_p(&v);
priorv = v;
tup->DeleteIfAllowed();
}
LOGP
resultTin->triangulateSection(vc);
resultTin->finishTriangulation();
} catch (std::exception & e) {
OUT_EXCEPT(e);
stream.close();
LOGP
return -1;
}
resultTin->setDefined();
stream.close();
LOGP
return 0;
}
template<typename T>
int Tin::raster2tin_vm(Word* args, Word& result, int message, Word& local,
Supplier s) {
LOGP
result = qp->ResultStorage(s);
Tin* nt = (Tin*) result.addr;
T* p_stype = static_cast<T*>(args[0].addr);
CcInt* maxSizePart = static_cast<CcInt*>(args[1].addr);
nt->config.maxSizePart = maxSizePart->GetIntval();
try {
if (!p_stype)
throw std::runtime_error(
"Null pointer as input. Operation not possible. (Tin::raster2tin_vm)");
VertexContainerSet * vc = new VertexContainerSet(
VERTEX_CONTAINER_BIG_SIZE);
if (!p_stype->isDefined())
throw std::runtime_error(
"The input raster is undefined.(Tin::raster2tin_vm)");
VERTEX_COORDINATE grid_origin_x = p_stype->getGrid().getOriginX();
VERTEX_COORDINATE grid_origin_y = p_stype->getGrid().getOriginY();
VERTEX_COORDINATE grid_length = p_stype->getGrid().getLength();
VERTEX_COORDINATE grid_mid = p_stype->getGrid().getLength() / 2;
grid_origin_x += grid_mid;
grid_origin_y += grid_mid;
LOG(grid_origin_x)
LOG(grid_origin_y)
LOG(grid_length)
typename T::storage_type& storage = p_stype->getStorage();
for (typename T::iter_type it = storage.begin(), e = storage.end();
it != e; ++it) {
Vertex v((it.getIndex()[0]) * grid_length + grid_origin_x,
(it.getIndex()[1]) * grid_length + grid_origin_y, (VERTEX_Z) (*it));
LOG_EXP(v.print())
vc->insertVertex_p(&v);
}
if (vc->getSizeInMemory() / 4 > OPERATE_IN_MEMORY_THRESHOLD)
nt->setMemoryStateGradual();
else
nt->setMemoryState(INMEMORY);
nt->triangulateBulk(vc);
LOGP} catch (std::exception & e) {
OUT_EXCEPT(e);
return -1;
}
nt->setDefined();
LOGP
return 0;
}
#endif
} /* namespace tin*/
#endif /* TINTYPE_H_*/