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

500 lines
12 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
----
*/
#include "VertexContainerSet.h"
#include "Tin.h"
#include "stdlib.h"
#include "SecondoDependencies.h"
namespace tin {
VertexContainerSet::VertexContainerSet(TIN_SIZE imaxsize) :
AbstractVertexContainer(imaxsize) {
if (maxSize < 0) {
maxSize = (-maxSize) * Vertex::getSizeOnDisc()
+ getContainerSizeOnDisc();
}
if (getMaxVertexCount() < 2)
throw std::invalid_argument(E_VERTEXCONTAINER_CONSTRUCTOR);
indexYUpToDate = false;
indexXUpToDate = false;
initFeat = false;
tmpYorderedindex = 0;
tmpXorderedindex = 0;
}
VertexContainerSet::~VertexContainerSet() {
this->clear();
noVertices = 0;
if (tmpYorderedindex != 0)
delete[] tmpYorderedindex;
if (tmpXorderedindex != 0)
delete[] tmpXorderedindex;
}
void VertexContainerSet::loadVertices(const Vertex* parray,
int numberofvertices) {
if (parray == 0)
throw std::invalid_argument(E_VERTEXCONTAINER_LOADVERTICES);
if ((int)(setVertices.size() + numberofvertices) > getMaxVertexCount())
throw std::runtime_error(E_VERTEXCONTAINER_LOADVERTICES2);
while (numberofvertices > 0) {
numberofvertices--;
setVertices.insert(parray[numberofvertices]);
}
indexYUpToDate = false;
indexXUpToDate = false;
initFeat = false;
}
void VertexContainerSet::clear() {
setVertices.clear(); //since vertices have no pointers memory is clean
indexYUpToDate = false;
indexXUpToDate = false;
if (tmpYorderedindex)
delete[] tmpYorderedindex;
tmpYorderedindex = 0;
if (tmpXorderedindex)
delete[] tmpXorderedindex;
tmpXorderedindex = 0;
}
const Vertex* VertexContainerSet::insertVertex(const Vertex* v,
bool& newVertex) {
if (v == 0)
throw std::invalid_argument(E_VERTEXCONTAINER_INSERTVERTEX);
if ((int)(setVertices.size() + 1) > getMaxVertexCount())
throw std::runtime_error(E_VERTEXCONTAINER_INSERTVERTEX2);
std::pair<std::set<Vertex>::iterator, bool> r = setVertices.insert((*v));
if ((*r.first).getZ() != v->getZ())
throw std::invalid_argument(E_VERTEXCONTAINER_INSERTVERTEX3);
newVertex = r.second;
noVertices = setVertices.size();
indexYUpToDate = false;
indexXUpToDate = false;
initFeat = false;
return const_cast<Vertex*>(&(*r.first)); //TODO make this clean
}
void VertexContainerSet::resize(TIN_SIZE imaxSize) {
if (getSizeOnDisc() < imaxSize)
maxSize = imaxSize;
else
throw std::runtime_error(E_VERTEXCONTAINERSET_RESIZE);
}
void VertexContainerSet::insertVertex_p(const Vertex* v) {
if ((int)(setVertices.size() + 1) > getMaxVertexCount())
throw std::runtime_error(E_VERTEXCONTAINER_INSERTVERTEX2);
setVertices.insert((*v));
noVertices = setVertices.size();
indexYUpToDate = false;
indexXUpToDate = false;
initFeat = false;
}
void VertexContainerSet::removeVertex(const Vertex* v) {
this->setVertices.erase(*v);
noVertices = setVertices.size();
indexYUpToDate = false;
indexXUpToDate = false;
initFeat = false;
}
TIN_SIZE VertexContainerSet::getContainerSizeOnDisc() const {
return sizeof(maxSize) + sizeof(noVertices);
}
void VertexContainerSet::print(std::ostream& os) const {
std::set<Vertex>::iterator it;
os << "VertexContainer: " << " Maximum size on disc:" << getMaxSize();
os << " Current size on disc:"
<< VertexContainerSet::getSizeOnDiscStatic(noVertices)
<< " Maximum Vertex Count: " << getMaxVertexCount()
<< " Actual Vertex count: " << setVertices.size() << "\n";
it = setVertices.begin();
while (it != setVertices.end()) {
(*it).print(os);
os << "\n";
it++;
}
os << "end VertexContainer.............";
}
VertexContainerSet* VertexContainerSet::clone() {
VertexContainerSet* result = new VertexContainerSet(maxSize);
result->noVertices = noVertices;
result->setVertices = setVertices;
result->indexYUpToDate = false;
result->indexXUpToDate = false;
result->initFeat = false;
return result;
}
TinFeatures VertexContainerSet::getFeatures() const {
if (noVertices < 1)
return feat;
if (initFeat == false) {
std::set<Vertex>::iterator it;
it = setVertices.begin();
while (it != setVertices.end()) {
feat.update((*it));
++it;
}
initFeat = true;
}
return feat;
}
const Vertex* VertexContainerSet::getVertex(const Vertex& v) const {
std::set<Vertex>::iterator it;
it = setVertices.find(v);
if (it != setVertices.end())
return const_cast<Vertex*>(&(*it));
else
return 0;
}
const Vertex* VertexContainerSet::getVertexByYIndex(
const FILE_VERTEX_POINTER i) const {
LOGP
LOG(this)
LOG(noVertices)
if (noVertices < 1)
return NULL;
if (i > noVertices || i < 0)
throw std::invalid_argument(E_VERTEXCONTAINER_GETVERTEXBYINDEX);
if (indexYUpToDate == false) {
LOGP
if (i == noVertices - 1)
return &(*(setVertices.rbegin()));
if (i == 0)
return &(*(setVertices.begin()));
if (tmpYorderedindex != 0)
delete[] tmpYorderedindex;
tmpYorderedindex = new Vertex*[noVertices];
int i2 = 0;
std::set<Vertex>::iterator it;
it = setVertices.begin();
while (it != setVertices.end()) {
tmpYorderedindex[i2++] = const_cast<Vertex*>(&(*it));
++it;
}
indexYUpToDate = true;
}
LOGP
return tmpYorderedindex[i];
}
void VertexContainerSet::updateXindexAndFeatures() const {
if (noVertices < 1)
return;
if (indexXUpToDate == false) {
if (tmpXorderedindex != 0)
delete[] tmpXorderedindex;
tmpXorderedindex = new Vertex*[noVertices];
int i2 = 0;
std::set<Vertex>::iterator it;
it = setVertices.begin();
while (it != setVertices.end()) {
tmpXorderedindex[i2++] = const_cast<Vertex*>(&(*it));
feat.update((*it));
++it;
}
qsort(tmpXorderedindex, noVertices, sizeof(Vertex*), Vertex::compareByX);
initFeat = true;
indexXUpToDate = true;
}
}
const Vertex* VertexContainerSet::getVertexByXIndex(const int i) const {
if (noVertices < 1)
return NULL;
if (i > noVertices || i < 0)
throw std::invalid_argument(E_VERTEXCONTAINER_GETVERTEXBYINDEX2);
if (indexXUpToDate == false) {
updateXindexAndFeatures();
}
return tmpXorderedindex[i];
}
void VertexContainerSet::unaryOp(VERTEX_Z (*op)(VERTEX_Z z),
TinFeatures& feat) {
std::set<Vertex>::iterator it = setVertices.begin();
while (it != setVertices.end()) {
Vertex* v = const_cast<Vertex*>(&(*it));
v->setZ(op(v->getZ()));
feat.update((*it));
it++;
}
}
#ifndef UNIT_TEST
void VertexContainerSet::unaryOp(void * function, TinFeatures& feat) {
std::set<Vertex>::iterator it = setVertices.begin();
Word result;
CcReal vertex_z;
ArgVector& arguments = *qp->Argument(function);
arguments[0].setAddr(&vertex_z);
while (it != setVertices.end()) {
Vertex* v = const_cast<Vertex*>(&(*it));
vertex_z.Set(v->getZ());
result = qp->Request(function);
v->setZ(((CcReal*) result.addr)->GetValue());
feat.update((*it));
++it;
}
}
#endif
void VertexContainerSet::binaryOp(Tin& tt,
VERTEX_Z (*op)(VERTEX_Z z1, VERTEX_Z z2), TinFeatures& feat) {
std::set<Vertex>::iterator it = setVertices.begin();
VERTEX_Z z_val;
while (it != setVertices.end()) {
Vertex* v = const_cast<Vertex*>(&(*it));
Point_p p(v->getX(), v->getY());
z_val = tt.atlocation(p);
if (z_val == ERROR_VALUE) {
feat.update(*v);
it++;
continue;
} else
v->setZ(op(v->getZ(), z_val));
feat.update(*v);
it++;
}
}
AbstractVertexContainer* VertexContainerSet::clone_empty() {
VertexContainerSet* result = new VertexContainerSet(maxSize);
return result;
}
void VertexContainerSet::insertVertices(const VertexContainerSet& vc) {
if ((int)(setVertices.size() + vc.setVertices.size() + 1)
> getMaxVertexCount())
throw std::runtime_error(E_VERTEXCONTAINER_INSERTVERTICES);
setVertices.insert(vc.setVertices.begin(), vc.setVertices.end());
noVertices = setVertices.size();
indexYUpToDate = false;
indexXUpToDate = false;
initFeat = false;
}
void VertexContainerSet::addVerticesTo(AbstractVertexContainer& vc) {
vc.insertVertices(*this);
}
std::set<Vertex>::reverse_iterator
VertexContainerSet::getIteratorRbegin() const {
return setVertices.rbegin();
}
void VertexContainerSet::removeVertex(
std::set<Vertex>::reverse_iterator it) {
setVertices.erase(++(it.base()));
}
std::set<Vertex>::reverse_iterator VertexContainerSet::getIteratorRend() const {
return setVertices.rend();
}
#ifndef UNIT_TEST
void VertexContainerSet::serialize(char* storage, size_t& offset) const {
LOGP
std::set<Vertex>::iterator it;
Vertex *v;
WriteVar<TIN_SIZE>(maxSize, storage, offset);
WriteVar<TIN_SIZE>(noVertices, storage, offset);
LOG(noVertices)
it = setVertices.begin();
while (it != setVertices.end()) {
v = const_cast<Vertex*>(&(*it));
v->serialize(storage, offset);
++it;
}
LOGP}
void VertexContainerSet::rebuild(char* state, size_t & offset) {
LOGP
LOG(this)
std::set<Vertex>::iterator it;
Vertex v;
ReadVar<TIN_SIZE>(maxSize, state, offset);
ReadVar<TIN_SIZE>(noVertices, state, offset);
LOG(noVertices)
for (int i = 0; i < noVertices; i++) {
v.rebuild(state, offset);
setVertices.insert(v);
}
indexYUpToDate = false;
indexXUpToDate = false;
initFeat = false;
LOGP}
ListExpr VertexContainerSet::outContainer() const {
LOGP
std::set<Vertex>::iterator it;
it = setVertices.begin();
ListExpr ret=nl->TheEmptyList(), tmp, last;
if (it != setVertices.end()) {
ret = nl->OneElemList((*it).outVertex());
it++;
}
last = ret;
while (it != setVertices.end()) {
tmp = (*it).outVertex();
last = nl->Append(last, tmp);
it++;
}
return ret;
}
bool VertexContainerSet::open(SmiRecord& valueRecord) {
LOGP
Vertex v;
valueRecord.Read(maxSize);
valueRecord.Read(noVertices);
std::set<Vertex>::iterator preceedingIt;
LOG(noVertices)
preceedingIt = setVertices.begin();
for (int i = 0; i < noVertices; i++) {
v.open(valueRecord);
preceedingIt = setVertices.insert(preceedingIt, v);
}
indexYUpToDate = false;
indexXUpToDate = false;
initFeat = false;
LOGP
return true;
}
bool VertexContainerSet::save(SmiRecord& valueRecord) {
LOGP
std::set<Vertex>::iterator it;
Vertex *v;
valueRecord.Write(maxSize);
valueRecord.Write(noVertices);
LOG(noVertices)
it = setVertices.begin();
while (it != setVertices.end()) {
v = const_cast<Vertex*>(&(*it));
v->save(valueRecord);
++it;
}
LOGP
return true;
}
#endif
int VertexContainerSet::getYIndex(const Vertex * v) const {
if (noVertices < 1)
return -1;
if (indexYUpToDate == false) {
if (tmpYorderedindex != 0)
delete[] tmpYorderedindex;
tmpYorderedindex = new Vertex*[noVertices];
int i = 0;
std::set<Vertex>::iterator it;
it = setVertices.begin();
while (it != setVertices.end()) {
tmpYorderedindex[i++] = const_cast<Vertex*>(&(*it));
++it;
}
indexYUpToDate = true;
}
Vertex **pv = (Vertex **) bsearch(v, tmpYorderedindex, noVertices,
sizeof(Vertex*), Vertex::compareIndex);
if (pv == NULL)
return -1;
return (pv - tmpYorderedindex);
}
int VertexContainerSet::getSizeInMemory() const {
int sizexindex = 0, sizeyindex = 0;
if (tmpXorderedindex != 0)
sizexindex = sizeof(Vertex*) * noVertices;
if (tmpYorderedindex != 0)
sizeyindex = sizeof(Vertex*) * noVertices;
return sizeof(*this) + noVertices * (24 + sizeof(Vertex)) + sizexindex
+ sizeyindex; //Just a guess !!!
}
std::ostream& operator <<(std::ostream& os, VertexContainerSet& vc) {
vc.print(os);
return os;
}
}