Files
2026-01-23 17:03:45 +08:00

326 lines
7.9 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
----
*/
#include "MPoints.h"
using namespace std;
namespace ColumnMovingAlgebra
{
/*
1.1.3 CRel Algebra Interface
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* MPoints::Filter(
CRelAlgebra::SharedArray<const uint64_t> filter) const
{
return new MPoints(*this, filter);
}
/*
~GetCount~ returns the number of entries in the attribut array.
*/
uint64_t MPoints::GetCount() const
{
return m_MPointsData->rowCount();
}
/*
~GetSize~ returns the amount of space needed to save this attribut array
to persistant storage.
*/
uint64_t MPoints::GetSize() const
{
return m_MPointsData->savedSize() +
m_DefTimes->savedSize() +
sizeof(m_Mbr) +
sizeof(bool) +
(m_GridIndex.get() != 0 ? m_GridIndex->savedSize() : 0);
}
/*
~Save~ saves this attribut array
to persistant storage.
*/
void MPoints::Save(CRelAlgebra::Writer &target, bool includeHeader) const
{
m_MPointsData->save(target);
m_DefTimes->save(target);
GridIndex::Mbr m = m_Mbr;
target.WriteOrThrow(reinterpret_cast<char*>(&m), sizeof(m));
bool hasGrid = m_GridIndex.get() != 0;
target.WriteOrThrow(reinterpret_cast<char*>(&hasGrid), sizeof(bool));
if (hasGrid)
m_GridIndex->save(target);
}
/*
~Append~ adds the moving point at index ~row~ of the attribut array ~array~
*/
void MPoints::Append(const CRelAlgebra::AttrArray & array, uint64_t row)
{
MPoints mpoints = static_cast<const MPoints &>(array);
if (m_MPointsData->rowCount() == 0) {
if (m_GridIndex.get() == 0 && mpoints.m_GridIndex.get() != 0) {
GridIndex & g = *mpoints.m_GridIndex;
m_GridIndex = std::make_shared<GridIndex>(g.offset(), g.cellSize(),
g.splits());
}
}
addRow();
MPointsData::UnitIterator i = mpoints.m_MPointsData->unitIterator(row);
while (i.hasNext()) {
MPointsData::Unit u = i.next();
addUnit(u.interval, u.x0, u.y0, u.x1, u.y1);
}
}
/*
~Append~ adds the row orientied MPoint ~value~
*/
void MPoints::Append(Attribute & value)
{
temporalalgebra::MPoint & a = static_cast<temporalalgebra::MPoint&>(value);
addRow();
if (a.IsDefined()) {
for (int i = 0; i < a.GetNoComponents(); i++) {
temporalalgebra::UPoint c;
a.Get(i, c);
Interval interval(c.timeInterval);
addUnit(interval, c.p0.GetX(), c.p0.GetY(), c.p1.GetX(), c.p1.GetY());
}
}
}
/*
~Remove~ removes the last added moving point
*/
void MPoints::Remove()
{
m_MPointsData->removeRow();
m_DefTimes->removeRow();
if (m_GridIndex.get() != 0)
m_GridIndex->removeRow();
}
/*
~Clear~ removes all moving points
*/
void MPoints::Clear()
{
m_MPointsData->clear();
m_DefTimes->clear();
if (m_GridIndex.get() != 0)
m_GridIndex->clear();
}
/*
~IsDefined~ returns true, iff the moving point with index ~row~ has any units
*/
bool MPoints::IsDefined(uint64_t row) const
{
return m_MPointsData->unitCount(row) > 0;
}
/*
~Compare~ compares the moving point at index ~rowA~ with the moving point
at index ~rowB~ in ~arrayB~
*/
int MPoints::Compare(uint64_t rowA, const CRelAlgebra::AttrArray &arrayB,
uint64_t rowB) const
{
const MPoints & mpointsB = static_cast<const MPoints&>(arrayB);
int iDiff;
double dDiff;
int unitCountA = m_MPointsData->unitCount(rowA);
int unitCountB = mpointsB.m_MPointsData->unitCount(rowB);
iDiff = unitCountA - unitCountB;
if (iDiff != 0)
return iDiff < 0 ? -1 : 1;
MPointsData::UnitIterator iA = m_MPointsData->unitIterator(rowA);
MPointsData::UnitIterator iB = mpointsB.m_MPointsData->unitIterator(rowB);
while (iA.hasNext()) {
checkrv(iB.hasNext(), "comparison logical error", 0);
MPointsData::Unit a = iA.next();
MPointsData::Unit b = iB.next();
Interval & intervalA = a.interval;
Interval & intervalB = b.interval;
iDiff = intervalA.compare(intervalB);
if (iDiff != 0)
return iDiff < 0 ? -1 : 1;
dDiff = a.x0 - b.x0;
if (dDiff != 0)
return dDiff < 0 ? -1 : 1;
dDiff = a.x1 - b.x1;
if (dDiff != 0)
return dDiff < 0 ? -1 : 1;
dDiff = a.y0 - b.y0;
if (dDiff != 0)
return dDiff < 0 ? -1 : 1;
dDiff = a.y1 - b.y1;
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 MPoints::Compare(uint64_t row, Attribute &value) const
{
auto mpointB = static_cast<temporalalgebra::MPoint&>(value);
if (!mpointB.IsDefined())
return IsDefined(row) ? 1 : 0;
int iDiff;
double dDiff;
int unitCountA = m_MPointsData->unitCount(row);
int unitCountB = mpointB.GetNoComponents();
iDiff = unitCountA - unitCountB;
if (iDiff != 0)
return iDiff < 0 ? -1 : 1;
MPointsData::UnitIterator iA = m_MPointsData->unitIterator(row);
int iB = 0;
while (iA.hasNext()) {
checkrv(iB < unitCountB, "comparison logical error", 0);
temporalalgebra::UPoint b;
MPointsData::Unit a = iA.next();
mpointB.Get(iB, b);
Interval & intervalA = a.interval;
Interval intervalB(b.timeInterval);
iDiff = intervalA.compare(intervalB);
if (iDiff != 0)
return iDiff < 0 ? -1 : 1;
dDiff = a.x0 - b.p0.GetX();
if (dDiff != 0)
return dDiff < 0 ? -1 : 1;
dDiff = a.x1 - b.p1.GetX();
if (dDiff != 0)
return dDiff < 0 ? -1 : 1;
dDiff = a.y0 - b.p0.GetY();
if (dDiff != 0)
return dDiff < 0 ? -1 : 1;
dDiff = a.y1 - b.p1.GetY();
if (dDiff != 0)
return dDiff < 0 ? -1 : 1;
}
return 0;
}
/*
~GetHash~ returns a hash value for the moving point at index ~row~
*/
uint64_t MPoints::GetHash(uint64_t row) const
{
if (m_MPointsData->unitCount(row) == 0)
return 0;
MPointsData::UnitIterator i = m_MPointsData->unitIterator(row);
checkrv(i.hasNext(), "hash logical error", 0);
MPointsData::Unit u = i.next();
return (uint64_t)(u.interval.s ^ u.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 * MPoints::GetAttribute(uint64_t row, bool clone) const
{
temporalalgebra::MPoint * attribute =
new temporalalgebra::MPoint(m_MPointsData->unitCount(row));
attribute->StartBulkLoad();
MPointsData::UnitIterator i = m_MPointsData->unitIterator(row);
while (i.hasNext()) {
MPointsData::Unit u = i.next();
Interval & interval = u.interval;
attribute->Add(temporalalgebra::UPoint(
temporalalgebra::Interval<Instant>(interval.s, interval.e,
interval.lc, interval.rc),
u.x0, u.y0, u.x1, u.y1));
}
attribute->EndBulkLoad();
return attribute;
}
}