360 lines
9.2 KiB
C++
360 lines
9.2 KiB
C++
|
|
/*
|
||
|
|
----
|
||
|
|
This file is part of SECONDO.
|
||
|
|
|
||
|
|
Copyright (C) 2004-2009, University in Hagen, Faculty of Mathematics
|
||
|
|
and 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
|
||
|
|
----
|
||
|
|
|
||
|
|
1 MRegions.cpp
|
||
|
|
|
||
|
|
*/
|
||
|
|
|
||
|
|
#include "MRegions.h"
|
||
|
|
|
||
|
|
using namespace std;
|
||
|
|
|
||
|
|
extern NestedList* nl;
|
||
|
|
|
||
|
|
namespace ColumnMovingAlgebra
|
||
|
|
{
|
||
|
|
/*
|
||
|
|
1.1 Implementation of Constants for ~MRegions~
|
||
|
|
|
||
|
|
~SMALLNUM~ represents a small number as cut off value in the intersection
|
||
|
|
calculations
|
||
|
|
|
||
|
|
*/
|
||
|
|
const double MRegions::SMALL_NUM = 1e-8;
|
||
|
|
|
||
|
|
/*
|
||
|
|
1.1 Implementation of Virtual Functions for ~MRegions~
|
||
|
|
|
||
|
|
the following functions are required by the crel algebra for all attribute
|
||
|
|
arrays.
|
||
|
|
|
||
|
|
~Filter~ returns a duplicate of this attribut array with the speficied filter.
|
||
|
|
|
||
|
|
*/
|
||
|
|
CRelAlgebra::AttrArray* MRegions::Filter(
|
||
|
|
CRelAlgebra::SharedArray<const uint64_t> filter) const
|
||
|
|
{
|
||
|
|
return new MRegions(*this, filter);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
~GetCount~ returns the number of entries in the attribut array.
|
||
|
|
|
||
|
|
*/
|
||
|
|
uint64_t MRegions::GetCount() const
|
||
|
|
{
|
||
|
|
return m_MRegions->size();
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
~GetSize~ returns the amount of space needed to save this attribut array
|
||
|
|
to persistant storage.
|
||
|
|
|
||
|
|
*/
|
||
|
|
uint64_t MRegions::GetSize() const
|
||
|
|
{
|
||
|
|
return m_Edges->savedSize() +
|
||
|
|
m_Cycles->savedSize() +
|
||
|
|
m_Faces->savedSize() +
|
||
|
|
m_Units->savedSize() +
|
||
|
|
m_MRegions->savedSize() +
|
||
|
|
m_DefTimes->savedSize();
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
~Save~ saves this attribut array
|
||
|
|
to persistant storage.
|
||
|
|
|
||
|
|
*/
|
||
|
|
void MRegions::Save(CRelAlgebra::Writer &target, bool includeHeader) const
|
||
|
|
{
|
||
|
|
m_Edges->save(target);
|
||
|
|
m_Cycles->save(target);
|
||
|
|
m_Faces->save(target);
|
||
|
|
m_Units->save(target);
|
||
|
|
m_MRegions->save(target);
|
||
|
|
m_DefTimes->save(target);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
~Append~ adds the moving point at index ~row~ of the attribut array ~array~
|
||
|
|
|
||
|
|
*/
|
||
|
|
void MRegions::Append(const CRelAlgebra::AttrArray & array, uint64_t row)
|
||
|
|
{
|
||
|
|
const MRegions & mrs = static_cast<const MRegions &>(array);
|
||
|
|
|
||
|
|
addMRegion();
|
||
|
|
|
||
|
|
for (int ui = mrs.unitFirst(row); ui < mrs.unitAfterLast(row); ui++) {
|
||
|
|
addUnit(mrs.unit(ui).interval);
|
||
|
|
|
||
|
|
for (int fi = mrs.faceFirst(ui); fi < mrs.faceAfterLast(ui); fi++) {
|
||
|
|
addFace();
|
||
|
|
|
||
|
|
for (int ci = mrs.cycleFirst(fi); ci < mrs.cycleAfterLast(fi); ci++) {
|
||
|
|
addCycle();
|
||
|
|
|
||
|
|
for (int ei = mrs.edgeFirst(ci); ei < mrs.edgeAfterLast(ci); ei++)
|
||
|
|
addEdge(mrs.edge(ei));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
~Append~ adds the row orientied MPoint ~value~
|
||
|
|
|
||
|
|
*/
|
||
|
|
void MRegions::Append(Attribute & value)
|
||
|
|
{
|
||
|
|
auto & m = static_cast<temporalalgebra::MRegion&>(value);
|
||
|
|
auto segments = static_cast<DbArray<temporalalgebra::MSegmentData>*>
|
||
|
|
(m.GetFLOB(1));
|
||
|
|
|
||
|
|
addMRegion();
|
||
|
|
|
||
|
|
if (!m.IsDefined())
|
||
|
|
return;
|
||
|
|
|
||
|
|
for (int ui = 0; ui < m.GetNoComponents(); ui++) {
|
||
|
|
temporalalgebra::URegionEmb u;
|
||
|
|
m.Get(ui, u);
|
||
|
|
|
||
|
|
addUnit(u.getTimeInterval());
|
||
|
|
|
||
|
|
int num = u.GetSegmentsNum(), lastFace = -1, lastCycle = -1;
|
||
|
|
|
||
|
|
for (int i = 0; i < num; i++) {
|
||
|
|
temporalalgebra::MSegmentData dms;
|
||
|
|
u.GetSegment(segments, i, dms);
|
||
|
|
|
||
|
|
if (lastFace != static_cast<int>(dms.GetFaceNo())) {
|
||
|
|
addFace();
|
||
|
|
lastFace = dms.GetFaceNo();
|
||
|
|
lastCycle = -1;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (lastCycle != static_cast<int>(dms.GetCycleNo())) {
|
||
|
|
addCycle();
|
||
|
|
lastCycle = dms.GetCycleNo();
|
||
|
|
}
|
||
|
|
|
||
|
|
addEdge(Edge{ { dms.GetInitialStartX(), dms.GetInitialStartY() },
|
||
|
|
{ dms.GetFinalStartX(), dms.GetFinalStartY() } });
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
checkMRegion(m_MRegions->size() - 1);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
~Remove~ removes the last added moving point
|
||
|
|
|
||
|
|
*/
|
||
|
|
void MRegions::Remove()
|
||
|
|
{
|
||
|
|
MRegion & r = m_MRegions->back();
|
||
|
|
Unit & u = unit(r.firstUnit);
|
||
|
|
Face & f = face(u.firstFace);
|
||
|
|
Cycle & c = cycle(f.firstCycle);
|
||
|
|
|
||
|
|
m_Edges->resize(c.firstEdge);
|
||
|
|
m_Cycles->resize(f.firstCycle);
|
||
|
|
m_Faces->resize(u.firstFace);
|
||
|
|
m_Units->resize(r.firstUnit);
|
||
|
|
m_MRegions->pop_back();
|
||
|
|
|
||
|
|
m_DefTimes->removeRow();
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
~Clear~ removes all moving points
|
||
|
|
|
||
|
|
*/
|
||
|
|
void MRegions::Clear()
|
||
|
|
{
|
||
|
|
m_Edges->clear();
|
||
|
|
m_Cycles->clear();
|
||
|
|
m_Faces->clear();
|
||
|
|
m_Units->clear();
|
||
|
|
m_MRegions->clear();
|
||
|
|
|
||
|
|
m_DefTimes->clear();
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
~IsDefined~ returns true, iff the moving point with index ~row~ has any units
|
||
|
|
|
||
|
|
*/
|
||
|
|
bool MRegions::IsDefined(uint64_t row) const
|
||
|
|
{
|
||
|
|
return unitCount(row) > 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
~Compare~ compares the moving point at index ~rowA~ with the moving point
|
||
|
|
at index ~rowB~ in ~arrayB~
|
||
|
|
|
||
|
|
*/
|
||
|
|
int MRegions::Compare(uint64_t rowA, const CRelAlgebra::AttrArray &arrayB,
|
||
|
|
uint64_t rowB) const
|
||
|
|
{
|
||
|
|
const MRegions & mpointsB = static_cast<const MRegions&>(arrayB);
|
||
|
|
|
||
|
|
int iDiff = unitCount(rowA) - mpointsB.unitCount(rowB);
|
||
|
|
if (iDiff != 0)
|
||
|
|
return iDiff < 0 ? -1 : 1;
|
||
|
|
|
||
|
|
for (int uiA = unitFirst(rowA), uiB = mpointsB.unitFirst(rowB);
|
||
|
|
uiA < unitAfterLast(rowA); uiA++, uiB++)
|
||
|
|
{
|
||
|
|
iDiff = unit(uiA).interval.compare(mpointsB.unit(uiB).interval);
|
||
|
|
if (iDiff != 0)
|
||
|
|
return iDiff < 0 ? -1 : 1;
|
||
|
|
|
||
|
|
iDiff = faceCount(uiA) - mpointsB.faceCount(uiB);
|
||
|
|
if (iDiff != 0)
|
||
|
|
return iDiff < 0 ? -1 : 1;
|
||
|
|
|
||
|
|
for (int fiA = faceFirst(uiA), fiB = mpointsB.faceFirst(uiB);
|
||
|
|
fiA < faceAfterLast(uiA); fiA++, fiB++)
|
||
|
|
{
|
||
|
|
iDiff = cycleCount(fiA) - mpointsB.cycleCount(fiB);
|
||
|
|
if (iDiff != 0)
|
||
|
|
return iDiff < 0 ? -1 : 1;
|
||
|
|
|
||
|
|
for (int ciA = cycleFirst(fiA), ciB = mpointsB.cycleFirst(fiB);
|
||
|
|
ciA < cycleAfterLast(fiA); ciA++, ciB++)
|
||
|
|
{
|
||
|
|
iDiff = edgeCount(ciA) - mpointsB.edgeCount(ciB);
|
||
|
|
if (iDiff != 0)
|
||
|
|
return iDiff < 0 ? -1 : 1;
|
||
|
|
|
||
|
|
for (int eiA = edgeFirst(ciA), eiB = mpointsB.edgeFirst(ciB);
|
||
|
|
eiA < edgeAfterLast(ciA); eiA++, eiB++)
|
||
|
|
{
|
||
|
|
double dDiff;
|
||
|
|
|
||
|
|
dDiff = edge(eiA).s.x - mpointsB.edge(eiB).s.x;
|
||
|
|
if (dDiff != 0)
|
||
|
|
return dDiff < 0 ? -1 : 1;
|
||
|
|
|
||
|
|
dDiff = edge(eiA).s.y - mpointsB.edge(eiB).s.y;
|
||
|
|
if (dDiff != 0)
|
||
|
|
return dDiff < 0 ? -1 : 1;
|
||
|
|
|
||
|
|
dDiff = edge(eiA).e.x - mpointsB.edge(eiB).e.x;
|
||
|
|
if (dDiff != 0)
|
||
|
|
return dDiff < 0 ? -1 : 1;
|
||
|
|
|
||
|
|
dDiff = edge(eiA).e.y - mpointsB.edge(eiB).e.y;
|
||
|
|
if (dDiff != 0)
|
||
|
|
return dDiff < 0 ? -1 : 1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
~Compare~ compares the moving point at index ~rowA~ with the row oriented
|
||
|
|
attribute ~value~
|
||
|
|
|
||
|
|
*/
|
||
|
|
int MRegions::Compare(uint64_t row, Attribute &value) const
|
||
|
|
{
|
||
|
|
MRegions mrs;
|
||
|
|
mrs.Append(value);
|
||
|
|
return Compare(row, mrs, 0);
|
||
|
|
}
|
||
|
|
|
||
|
|
/*
|
||
|
|
~GetHash~ returns a hash value for the moving point at index ~row~
|
||
|
|
|
||
|
|
*/
|
||
|
|
uint64_t MRegions::GetHash(uint64_t row) const
|
||
|
|
{
|
||
|
|
if (m_Units->size() == 0)
|
||
|
|
return 0;
|
||
|
|
|
||
|
|
return (uint64_t)(unit(0).interval.s ^ unit(0).interval.e);
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
/*
|
||
|
|
~GetAttribute~ converts the moving point
|
||
|
|
in ~row~ to an MPoint as defined in the temporal algebra for row oriented
|
||
|
|
relations and returns it.
|
||
|
|
|
||
|
|
*/
|
||
|
|
Attribute * MRegions::GetAttribute(uint64_t row, bool clone) const
|
||
|
|
{
|
||
|
|
temporalalgebra::MRegion* mr = new temporalalgebra::MRegion(0);
|
||
|
|
|
||
|
|
for (int ui = unitFirst(row); ui < unitAfterLast(row); ui++) {
|
||
|
|
std::vector<temporalalgebra::MSegmentData> linelist;
|
||
|
|
|
||
|
|
for (int fi = faceFirst(ui), fii = 0;
|
||
|
|
fi < faceAfterLast(ui); fi++, fii++)
|
||
|
|
{
|
||
|
|
for (int ci = cycleFirst(fi), cii = 0;
|
||
|
|
ci < cycleAfterLast(fi); ci++, cii++)
|
||
|
|
{
|
||
|
|
for (int i = 0; i < edgeCount(ci); i++) {
|
||
|
|
int ei0 = edgeFirst(ci) + (i % edgeCount(ci));
|
||
|
|
int ei1 = edgeFirst(ci) + ((i + 1) % edgeCount(ci));
|
||
|
|
|
||
|
|
Edge & e0 = edge(ei0);
|
||
|
|
Edge & e1 = edge(ei1);
|
||
|
|
|
||
|
|
bool insideAbove;
|
||
|
|
|
||
|
|
if (AlmostEqual(e0.s.x, e1.s.x) && AlmostEqual(e0.s.y, e1.s.y)) {
|
||
|
|
bool eqx = AlmostEqual(e0.e.x, e1.e.x);
|
||
|
|
insideAbove = (!eqx && (e0.e.x < e1.e.x) ) ||
|
||
|
|
(eqx && !AlmostEqual(e0.e.y, e1.e.y) && (e0.e.y < e1.e.y));
|
||
|
|
} else {
|
||
|
|
bool eqx = AlmostEqual(e0.s.x, e1.s.x);
|
||
|
|
insideAbove = (!eqx && (e0.s.x < e1.s.x) ) ||
|
||
|
|
(eqx && !AlmostEqual(e0.s.y, e1.s.y) && (e0.s.y < e1.s.y));
|
||
|
|
}
|
||
|
|
insideAbove = insideAbove == (ci == cycleFirst(fi));
|
||
|
|
|
||
|
|
linelist.emplace_back(fii, cii, i, insideAbove,
|
||
|
|
e0.s.x, e0.s.y, e1.s.x, e1.s.y,
|
||
|
|
e0.e.x, e0.e.y, e1.e.x, e1.e.y);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
temporalalgebra::URegion ur(linelist, unit(ui).interval.convert(), true);
|
||
|
|
mr->AddURegion(ur);
|
||
|
|
}
|
||
|
|
|
||
|
|
return mr;
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|