/* ---- 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 TINPART_H_ #define TINPART_H_ #include "TinHelper.h" #include "VertexContainerArray.h" #include "VertexContainerSet.h" #include "AbstractVertexContainer.h" #include "Triangle.h" #include #include #include "TinLogging.h" namespace tin { /* 1 Class TinPart */ class TinPart: public noncopyable { protected: TinFeatures features; //features of this part (Header information) TIN_SIZE noVertices; // (Header information) TIN_SIZE noTriangles; //number of #ifndef UNIT_TEST SmiRecordId recId; //Record id for content data (Header information) bool isRecInitialized; //whether content record exists (not persisted) #endif AbstractVertexContainer *pVertexContainer; //Vertices (Content data) Triangle *arTriangles; //Triangles (Content data) TIN_SIZE noTrianglesMax; //number of triangles //maximum currently (not persisted) Tin *tin; //TIN this part belongs to (not persisted) TinConfiguration config; //Configuration of this part (not persisted) bool contentLoaded; //Indicates whether content is loaded (not persisted) mutable bool ismodified; //Indicates whether //content is modified (not persisted) int contentRefs; //counts external references to content (not persisted) class atLocationRandomIndex { private: TIN_SIZE noIndexTriangles; TIN_SIZE step; TinPart* myPart; void build() { noIndexTriangles = cbrt(myPart->noTriangles); if (noIndexTriangles) { step = myPart->noTriangles / noIndexTriangles; } else if (myPart->noTriangles > 0) noIndexTriangles = 1; } public: atLocationRandomIndex(TinPart * p) { noIndexTriangles = 0; step = 0; myPart = p; } ~atLocationRandomIndex() { } Triangle* getAtLocationIndex(const Point_p & p) { const Vertex *v; Vector2D dist; Triangle * result = 0; double minDist = std::numeric_limits::max(); build(); try { for (FILE_TRIANGLE_POINTER i = 0; i < noIndexTriangles; i++) { v = myPart->getTriangleByIndex(i * step)->getVertex(1); dist = p - *v; if (dist.getLength().u < minDist) { minDist = dist.getLength().u; result = myPart->getTriangleByIndex(i * step); } } } catch (std::exception & e) { //might throw because of empty part...so index out of bounds } return result; } } idxAtLocation; ////////Construction/Destruction///////////////////////////////// protected: TinPart() : idxAtLocation(this) { pVertexContainer = 0; arTriangles = 0; tin = 0; noTriangles = 0; noTrianglesMax = 0; noVertices = 0; contentRefs = 0; contentLoaded = true; ismodified = true; #ifndef UNIT_TEST isRecInitialized = false; #endif } TinPart(bool theEmptyConstructor) : features(true), pVertexContainer(0), arTriangles(0), config(true), idxAtLocation(this) { } public: virtual ~TinPart() { if (pVertexContainer != 0) { delete pVertexContainer; pVertexContainer = 0; } if (arTriangles) { delete[] arTriangles; arTriangles = 0; } noTriangles = 0; } static TinPart* getInstanceNew(Tin* tt, const TinConfiguration& conf = TinConfiguration::DEFAULT); #ifndef UNIT_TEST static TinPart* getInstanceFromDisc(Tin* tt, SmiRecord& valueRecord, bool bulkload, const TinConfiguration& conf = TinConfiguration::DEFAULT); static TinPart* getInstanceFromDiscRandomAccess(Tin* tt, SmiRecord& valueRecord, const uint32_t idx, const TinConfiguration& conf = TinConfiguration::DEFAULT); static TinPart* getInstanceFromBuffer(Tin* tt, char* buffer, size_t &offset, bool bulkload, const TinConfiguration& conf); #endif virtual TinPart* clone(Tin*tt); protected: static TinPart* getInstanceNew_fortestonly(Tin* tt, const Vertex *iarTriangles, int inoTriangles, int& noTrianglesAdded, const TinConfiguration& conf = TinConfiguration::DEFAULT); ////////Manipulation///////////////////////////////////////////// public: void overlay(Tin& tt, VertexContainerSet& vc); #ifndef UNIT_TEST void unaryOp(void* function); #endif TinPart* unaryOp(VERTEX_Z (*op)(VERTEX_Z), TinFeatures & feat); TinPart* binaryOp(AbstractTinType* tinResult, VERTEX_Z (*op)(VERTEX_Z z1, VERTEX_Z z2)); void updateFeatures(); bool addTriangle(const Vertex& v1, const Vertex& v2, const Vertex& v3, Triangle** newtriangle); bool addTriangle_p(const Vertex& v1, const Vertex& v2, const Vertex& v3, Triangle** newtriangle); bool addTriangle_p2(const Vertex& v1, const Vertex& v2, const Vertex& v3, Triangle** newtriangle); protected: Triangle* constructTriangle(const Vertex* v1, const Vertex* v2, const Vertex* v3); void initContentMemory(); void initContentMemory(TIN_SIZE inoVertices, TIN_SIZE inoTriangles); void freeContentMemory(); void setModified(bool val = true) const { ismodified = val; } ///////Query///////////////////////////////////////////////////// public: TIN_SIZE getNoTriangles() const { return noTriangles; } Triangle::triangleWalker getWalker(Point_p * path, int noPoints); static TIN_SIZE estimateNoTrianglesTotal(TIN_SIZE imaxSizePart) { return ((imaxSizePart - TinPart::estimateVertexContainerSizeOnDisc(imaxSizePart) - (TinFeatures::getSizeOnDisc() + sizeof(int))) / Triangle::getSizeOnDisc()); } TIN_SIZE getSizeInMemory(); static TIN_SIZE estimateMaxSizeInMemory(const TinConfiguration & conf); bool isModified() const { return ismodified; } class iterator { private: int currentTriangle; TinPart* tinpart; public: iterator() { currentTriangle = -1; tinpart = 0; } iterator(TinPart* itinpart) { if (itinpart) itinpart->loadContentData(); if (itinpart && itinpart->noTriangles > 0) currentTriangle = 0; else currentTriangle = -1; tinpart = itinpart; } Triangle* operator*() { if (currentTriangle != -1) return &tinpart->arTriangles[currentTriangle]; else return 0; } void operator++(int) { if (currentTriangle != -1 && currentTriangle + 1 < tinpart->noTriangles) currentTriangle++; else currentTriangle = -1; } }; bool isValidTriangle(const Triangle & at, std::string & error_msg); void addVerticesTo(VertexContainerSet& vc); std::set* getEdgeSet(); const TinFeatures& getFeatures() const { return features; } virtual bool isContentDataLoaded() const { return contentLoaded; } Triangle * getTriangleArrayBaseAdress() const { return arTriangles; } Triangle * getTriangleByIndex(FILE_TRIANGLE_POINTER index) { if (index >= noTrianglesMax || index < 0) throw std::runtime_error(E_TINPART_GETTRIANGLEBYINDEX); return &arTriangles[index]; } bool canAdd(); VERTEX_Z atlocation_brute_force(const Point_p& p); VERTEX_Z atlocation_bywalker(const Point_p& p); Triangle* findEdgeInPart(const Edge & e, Triangle* caller); VERTEX_Z atlocation(const Point_p& p); void atlocation_noload(const Point_p& p, Triangle ** ret); const Rectangle& bbox() const; VERTEX_Z minimum() const; VERTEX_Z maximum() const; TinPart::iterator begin() { return TinPart::iterator(this); } bool hasTriangle(Vertex &v1, Vertex &v2, Vertex &v3); bool checkDelaunay(); bool checkNeighborRelations(); virtual Triangle* getNeighbor(const Edge& commonEdge, Triangle* caller); protected: ///////Presentation////////////////////////////////////////////// public: #ifndef UNIT_TEST ListExpr outPart(); #endif friend std::ostream& operator<<(std::ostream & os, TinPart &a); ///////Persistence/////////////////////////////////////////////// public: virtual void loadContentData(); virtual void unloadContentData(); virtual void setMemoryState(MemoryState st) { LOGP config.memoryState = st; } virtual void deleteContentReference(); virtual void addContentReference(); static TIN_SIZE estimateVertexContainerSizeOnDisc(TIN_SIZE imaxSizePart); virtual TIN_SIZE getSizeOnDisc() const { LOGP TIN_SIZE size = getSizeOnDisc_head() + getSizeOnDisc_content(); LOGP return size; } static TIN_SIZE getSizeOnDisc_head() { LOGP TIN_SIZE size = sizeof(TIN_SIZE) + sizeof(TIN_SIZE) + TinFeatures::getSizeOnDisc(); // sizeof(TinPart::noTriangles) // + sizeof(TinPart::noVertices) + TinFeatures::getSizeOnDisc(); #ifndef UNIT_TEST size += sizeof(SmiRecordId); // size += sizeof(TinPart::recId); #endif LOGP return size; } virtual TIN_SIZE getSizeOnDisc_content() const { LOGP TIN_SIZE size = ( config.abstractType == MANIPULATE ? VertexContainerSet::getSizeOnDiscStatic(noVertices) : VertexContainerArray::getSizeOnDiscStatic(noVertices)) + noTriangles * Triangle::getSizeOnDisc(); LOGP return size; } #ifndef UNIT_TEST virtual bool save(SmiRecord& valueRecord); virtual void serialize(char* storage, size_t& offset); virtual void rebuild(char* state, size_t& offset); protected: virtual void save_content(); virtual void open_content(); virtual bool open(SmiRecord& valueRecord); virtual bool open_head(SmiRecord& valueRecord, uint32_t idx); #endif ///////////////////////////////////////////////////////////////// friend class TinPart_test; friend class TinAttribute; }; } /* namespace tin*/ #endif /* TINPART_H_*/