839 lines
20 KiB
C++
839 lines
20 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 MFsObjects.h
|
|
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "MObjects.h"
|
|
|
|
namespace ColumnMovingAlgebra
|
|
{
|
|
|
|
/*
|
|
1.1 Declaration of ~MFsObjects~
|
|
|
|
~MFsObjects~ is a template class for attribute arrays of one-dimensional
|
|
moving objects.
|
|
It is used to build the attribute arrays for moving booleans, moving
|
|
integers moving reals and moving strings.
|
|
|
|
*/
|
|
template<class Unit>
|
|
class MFsObjects : public MObjects
|
|
{
|
|
public:
|
|
/*
|
|
constructors required by the crel algebra for all attribute arrays.
|
|
|
|
*/
|
|
MFsObjects();
|
|
MFsObjects(CRelAlgebra::Reader& source);
|
|
MFsObjects(CRelAlgebra::Reader& source, uint64_t rowsCount);
|
|
MFsObjects(const MFsObjects &array,
|
|
const CRelAlgebra::SharedArray<const uint64_t> &filter);
|
|
/*
|
|
destructor
|
|
|
|
*/
|
|
virtual ~MFsObjects() { }
|
|
|
|
/*
|
|
1.1.1 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.
|
|
|
|
|
|
*/
|
|
virtual AttrArray* Filter(
|
|
CRelAlgebra::SharedArray<const uint64_t> filter) const;
|
|
|
|
/*
|
|
~GetAttribute~ converts the entry in ~row~ to a attribute for row oriented
|
|
relations.
|
|
|
|
*/
|
|
virtual Attribute *GetAttribute(uint64_t row, bool clone = true) const;
|
|
/*
|
|
~GetCount~ returns the number of entries in the attribut array.
|
|
|
|
*/
|
|
virtual uint64_t GetCount() const;
|
|
/*
|
|
~GetSize~ returns the amount of space needed to save this attribut array
|
|
to persistant storage.
|
|
|
|
*/
|
|
virtual uint64_t GetSize() const;
|
|
|
|
/*
|
|
~Save~ saves this attribut array
|
|
to persistant storage.
|
|
|
|
*/
|
|
virtual void Save(CRelAlgebra::Writer &target,
|
|
bool includeHeader = true) const;
|
|
|
|
/*
|
|
~Append~ adds the entry at index ~row~ of the attribut array ~array~
|
|
|
|
*/
|
|
virtual void Append(const CRelAlgebra::AttrArray & array, uint64_t row);
|
|
/*
|
|
~Append~ adds the row orientied attribute ~value~
|
|
|
|
*/
|
|
virtual void Append(Attribute & value);
|
|
/*
|
|
~Remove~ removes the last added entry
|
|
|
|
*/
|
|
virtual void Remove();
|
|
/*
|
|
~Clear~ removes all entries
|
|
|
|
*/
|
|
virtual void Clear();
|
|
|
|
/*
|
|
~IsDefined~ returns true, iff the entry with index ~row~ is defined
|
|
|
|
*/
|
|
virtual bool IsDefined(uint64_t row) const;
|
|
|
|
/*
|
|
~Compare~ compares the entry at index ~rowA~ with the entry at index
|
|
~rowB~ in ~arrayB~
|
|
|
|
*/
|
|
virtual int Compare(uint64_t rowA, const AttrArray& arrayB,
|
|
uint64_t rowB) const;
|
|
/*
|
|
~Compare~ compares the entry at index ~rowA~ with the row oriented
|
|
attribute ~value~
|
|
|
|
*/
|
|
virtual int Compare(uint64_t row, Attribute &value) const;
|
|
|
|
/*
|
|
~GetHash~ returns a hash value for the entry at index ~row~
|
|
|
|
*/
|
|
virtual uint64_t GetHash(uint64_t row) const;
|
|
|
|
/*
|
|
1.1.2 Operators
|
|
|
|
The following functions implement the operators supported by the attribut
|
|
array.
|
|
|
|
~atInstant~ is a timeslice operator and computes an intime for moving object
|
|
entry in the attribute array and adds them to ~result~
|
|
|
|
*/
|
|
void atInstant(Instant instant, typename Unit::Instants & result);
|
|
/*
|
|
~atPeriods~ restricts the moving object entries to a given set of time
|
|
intervals and adds the resulting units to ~result~.
|
|
|
|
*/
|
|
void atPeriods(temporalalgebra::Periods periods, MFsObjects & result);
|
|
/*
|
|
~passes~ adds the indices of all moving object entries to ~result~, which
|
|
ever assume the specified value or a value in the specified range.
|
|
|
|
*/
|
|
void passes(typename Unit::Attr & value, CRelAlgebra::LongInts & result);
|
|
void passes(typename Unit::RAttr & value, CRelAlgebra::LongInts & result);
|
|
/*
|
|
~at~ restricts the all moving object entries to the specified value or
|
|
the specified range. the computed new units are added to ~result~
|
|
|
|
*/
|
|
void at(typename Unit::Attr & value, MFsObjects & result);
|
|
void at(typename Unit::RAttr & value, MFsObjects & result);
|
|
/*
|
|
~addRandomUnits~ adds random units to every moving object entry
|
|
|
|
*/
|
|
void addRandomUnits(CcInt& size, MFsObjects & result);
|
|
|
|
/*
|
|
~addMObject~ adds a new moving object entry to the attribute array
|
|
|
|
*/
|
|
void addMObject();
|
|
/*
|
|
~addUnit~ adds a new unit to the last added moving object entry
|
|
|
|
*/
|
|
void addUnit(Unit & unit);
|
|
|
|
protected:
|
|
/*
|
|
1.1.3 Attributes
|
|
|
|
~MObject~ represents a moving object entry. ~firstUnit~ is the index of the
|
|
first unit that belongs to the moving object in the array ~mUnits~.
|
|
~minimum~ and ~maximum~ are the extremes of the value of the moving object.
|
|
|
|
*/
|
|
struct MObject {
|
|
int firstUnit;
|
|
typename Unit::Value minimum, maximum;
|
|
};
|
|
|
|
/*
|
|
~mUnits~ represents the units of all moving object entries.
|
|
|
|
*/
|
|
std::shared_ptr<Array<Unit>> m_Units;
|
|
/*
|
|
~mMObjects~ represents the moving object entries.
|
|
|
|
*/
|
|
std::shared_ptr<Array<MObject>> m_MObjects;
|
|
|
|
/*
|
|
1.1.4 Helper Functions
|
|
|
|
The following functions are for convenience. They return the number of units,
|
|
the index of the first unit and one more than the last unit
|
|
of a moving object entry and also the unit for a specified unit index.
|
|
|
|
*/
|
|
int unitFirst(int mobject) const;
|
|
int unitAfterLast(int mobject) const;
|
|
int unitCount(int mobject) const;
|
|
Unit & unit(int index) const;
|
|
};
|
|
|
|
/*
|
|
1.2 Implementation of ~MFsObjects~
|
|
|
|
1.2.1 Constructors
|
|
|
|
These constructors are required by the crel algebra
|
|
|
|
*/
|
|
template<class Unit>
|
|
MFsObjects<Unit>::MFsObjects() :
|
|
m_Units(std::make_shared<Array<Unit>>()),
|
|
m_MObjects(std::make_shared<Array<MObject>>())
|
|
{
|
|
}
|
|
|
|
template<class Unit>
|
|
MFsObjects<Unit>::
|
|
MFsObjects(CRelAlgebra::Reader& source)
|
|
{
|
|
m_Units = std::make_shared<Array<Unit>>(source);
|
|
m_MObjects = std::make_shared<Array<MObject>>(source);
|
|
m_DefTimes = std::make_shared<DefTimes>(source);
|
|
}
|
|
|
|
template<class Unit>
|
|
MFsObjects<Unit>::MFsObjects(CRelAlgebra::Reader& source, uint64_t rowsCount)
|
|
{
|
|
m_Units = std::make_shared<Array<Unit>>(source);
|
|
m_MObjects = std::make_shared<Array<MObject>>(source);
|
|
m_DefTimes = std::make_shared<DefTimes>(source);
|
|
}
|
|
|
|
template<class Unit>
|
|
MFsObjects<Unit>::MFsObjects(const MFsObjects &array,
|
|
const CRelAlgebra::SharedArray<const uint64_t> &filter) :
|
|
MObjects(array, filter),
|
|
m_Units(array.m_Units),
|
|
m_MObjects(array.m_MObjects)
|
|
{
|
|
}
|
|
|
|
/*
|
|
1.2.2 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.
|
|
|
|
*/
|
|
template<class Unit>
|
|
CRelAlgebra::AttrArray* MFsObjects<Unit>::Filter(
|
|
CRelAlgebra::SharedArray<const uint64_t> filter) const
|
|
{
|
|
return new MFsObjects<Unit>
|
|
(*this, filter);
|
|
}
|
|
|
|
/*
|
|
~GetAttribute~ converts the entry in ~row~ to a attribute for row oriented
|
|
relations.
|
|
|
|
*/
|
|
template<class Unit>
|
|
Attribute * MFsObjects<Unit>::GetAttribute(uint64_t row, bool clone) const
|
|
{
|
|
typename Unit::MAttr * mattr = new typename Unit::MAttr(unitCount(row));
|
|
mattr->StartBulkLoad();
|
|
|
|
for (int ui = unitFirst(row); ui < unitAfterLast(row); ui++)
|
|
unit(ui).appendTo(*mattr);
|
|
|
|
mattr->EndBulkLoad();
|
|
return mattr;
|
|
}
|
|
|
|
/*
|
|
~GetCount~ returns the number of entries in the attribut array.
|
|
|
|
*/
|
|
template<class Unit>
|
|
uint64_t MFsObjects<Unit>::GetCount() const
|
|
{
|
|
return m_MObjects->size();
|
|
}
|
|
|
|
/*
|
|
~GetSize~ returns the amount of space needed to save this attribut array
|
|
to persistant storage.
|
|
|
|
*/
|
|
template<class Unit>
|
|
uint64_t MFsObjects<Unit>::
|
|
GetSize() const
|
|
{
|
|
return m_Units->savedSize() +
|
|
m_MObjects->savedSize() +
|
|
m_DefTimes->savedSize();
|
|
}
|
|
|
|
/*
|
|
~Save~ saves this attribut array
|
|
to persistant storage.
|
|
|
|
*/
|
|
template<class Unit>
|
|
void MFsObjects<Unit>::Save(CRelAlgebra::Writer &target,
|
|
bool includeHeader) const
|
|
{
|
|
m_Units->save(target);
|
|
m_MObjects->save(target);
|
|
m_DefTimes->save(target);
|
|
}
|
|
|
|
/*
|
|
~Append~ adds the entry at index ~row~ of the attribut array ~array~
|
|
|
|
*/
|
|
template<class Unit>
|
|
void MFsObjects<Unit>::Append(const CRelAlgebra::AttrArray & array,
|
|
uint64_t row)
|
|
{
|
|
const MFsObjects<Unit> & m =
|
|
static_cast<const MFsObjects<Unit> &>
|
|
(array);
|
|
|
|
addMObject();
|
|
|
|
for (int ui = m.unitFirst(row); ui < m.unitAfterLast(row); ui++)
|
|
addUnit(m.unit(ui));
|
|
}
|
|
|
|
/*
|
|
~Append~ adds the row orientied attribute ~value~
|
|
|
|
*/
|
|
template<class Unit>
|
|
void MFsObjects<Unit>::Append(Attribute & value)
|
|
{
|
|
auto & m = static_cast<typename Unit::MAttr&>(value);
|
|
|
|
addMObject();
|
|
|
|
if (!m.IsDefined())
|
|
return;
|
|
|
|
for (int ui = 0; ui < m.GetNoComponents(); ui++) {
|
|
Unit u(m, ui);
|
|
addUnit(u);
|
|
}
|
|
}
|
|
|
|
/*
|
|
~Remove~ removes the last added entry
|
|
|
|
*/
|
|
template<class Unit>
|
|
void MFsObjects<Unit>::Remove()
|
|
{
|
|
MObject & m = m_MObjects->back();
|
|
m_Units->resize(m.firstUnit);
|
|
m_MObjects->pop_back();
|
|
|
|
m_DefTimes->removeRow();
|
|
}
|
|
|
|
/*
|
|
~Clear~ removes all entries
|
|
|
|
*/
|
|
template<class Unit>
|
|
void MFsObjects<Unit>::Clear()
|
|
{
|
|
m_Units->clear();
|
|
m_MObjects->clear();
|
|
|
|
m_DefTimes->clear();
|
|
}
|
|
|
|
/*
|
|
~IsDefined~ returns true, iff the entry with index ~row~ is defined
|
|
|
|
*/
|
|
template<class Unit>
|
|
bool MFsObjects<Unit>::IsDefined(uint64_t row) const
|
|
{
|
|
return unitCount(row) > 0;
|
|
}
|
|
|
|
/*
|
|
~Compare~ compares the entry at index ~rowA~ with the entry at index
|
|
~rowB~ in ~arrayB~
|
|
|
|
*/
|
|
template<class Unit>
|
|
int MFsObjects<Unit>::Compare(uint64_t rowA,
|
|
const CRelAlgebra::AttrArray &arrayB, uint64_t rowB)
|
|
const
|
|
{
|
|
const MFsObjects<Unit> & mb =
|
|
static_cast<const MFsObjects<Unit>&>
|
|
(arrayB);
|
|
|
|
int iDiff = unitCount(rowA) - mb.unitCount(rowB);
|
|
if (iDiff != 0)
|
|
return iDiff < 0 ? -1 : 1;
|
|
|
|
for (int uiA = unitFirst(rowA), uiB = mb.unitFirst(rowB);
|
|
uiA < unitAfterLast(rowA); uiA++, uiB++)
|
|
{
|
|
Unit & a = unit(uiA);
|
|
Unit & b = mb.unit(uiB);
|
|
|
|
iDiff = a.interval().compare(b.interval());
|
|
if (iDiff != 0)
|
|
return iDiff < 0 ? -1 : 1;
|
|
|
|
iDiff = a.compareValue(b);
|
|
if (iDiff != 0.0)
|
|
return iDiff < 0.0 ? -1 : 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
~Compare~ compares the entry at index ~rowA~ with the row oriented
|
|
attribute ~value~
|
|
|
|
*/
|
|
template<class Unit>
|
|
int MFsObjects<Unit>::Compare(uint64_t row, Attribute &value) const
|
|
{
|
|
MFsObjects<Unit> mrs;
|
|
mrs.Append(value);
|
|
return Compare(row, mrs, 0);
|
|
}
|
|
|
|
/*
|
|
~GetHash~ returns a hash value for the entry at index ~row~
|
|
|
|
*/
|
|
template<class Unit>
|
|
uint64_t MFsObjects<Unit>::
|
|
GetHash(uint64_t row) const
|
|
{
|
|
if (m_Units->size() == 0)
|
|
return 0;
|
|
|
|
return (uint64_t)(unit(0).interval().s ^ unit(0).interval().e);
|
|
}
|
|
|
|
/*
|
|
1.1.2 Operators
|
|
|
|
The following functions implement the operators supported by the attribut
|
|
array.
|
|
|
|
~atInstant~ is a timeslice operator and computes an intime for each
|
|
moving object entry in the attribute array and adds them to ~result~. It does a
|
|
binary search on all units of each moving object entry and if it finds
|
|
a unit it calls the function ~atInstant~ for this unit to get the corresponding
|
|
intime.
|
|
|
|
*/
|
|
template<class Unit>
|
|
void MFsObjects<Unit>::atInstant(Instant instant,
|
|
typename Unit::Instants & result)
|
|
{
|
|
if (!instant.IsDefined()) {
|
|
for (uint64_t i = 0; i < GetFilter().GetCount(); i++)
|
|
result.Append(temporalalgebra::Intime<typename Unit::Attr>(instant,
|
|
Unit::undefinedAttr()));
|
|
|
|
return;
|
|
}
|
|
|
|
int64_t time = instant.millisecondsToNull();
|
|
|
|
for (auto & iterator : GetFilter()) {
|
|
int i = iterator.GetRow();
|
|
|
|
Unit * first = m_Units->data() + unitFirst(i);
|
|
Unit * afterLast = m_Units->data() + unitAfterLast(i);
|
|
Unit * u = lower_bound(first, afterLast, time,
|
|
[] (const Unit & a, const int64_t & b) -> bool {
|
|
return a.interval().e < b ||
|
|
(a.interval().e == b && !a.interval().rc);
|
|
});
|
|
|
|
if ( u == afterLast || u->interval().s > time ||
|
|
(u->interval().s == time && !u->interval().lc)) {
|
|
result.Append(temporalalgebra::Intime<typename Unit::Attr>(instant,
|
|
Unit::undefinedAttr()));
|
|
continue;
|
|
}
|
|
|
|
result.Append(u->atInstant(instant));
|
|
}
|
|
}
|
|
|
|
/*
|
|
~atPeriods~ restricts the moving object entries to a given set of time
|
|
intervals and adds the resulting units to ~result~. It performs a parallel
|
|
scan of the provided time intervalls and all units of each moving object entry.
|
|
if an overlapping pair of a time interval and a unit definition interval is
|
|
found the intersection is calculated and used as the parameter for
|
|
a call to ~restrictToInterval~ for the unit. The returned unit is added
|
|
to ~result~.
|
|
|
|
*/
|
|
template<class Unit>
|
|
void MFsObjects<Unit>::
|
|
atPeriods(temporalalgebra::Periods periods, MFsObjects & result)
|
|
{
|
|
if (!periods.IsDefined() || periods.GetNoComponents() == 0) {
|
|
for (uint64_t i = 0; i < GetFilter().GetCount(); i++)
|
|
result.addMObject();
|
|
|
|
return;
|
|
}
|
|
|
|
for (auto & iterator : GetFilter()) {
|
|
int row = iterator.GetRow();
|
|
result.addMObject();
|
|
|
|
int ai = 0, bi = unitFirst(row);
|
|
|
|
while (ai < periods.GetNoComponents() && bi < unitAfterLast(row)) {
|
|
temporalalgebra::Interval<Instant> period;
|
|
periods.Get(ai, period);
|
|
Interval a = period;
|
|
Interval b = unit(bi).interval();
|
|
|
|
if (a.intersects(b)) {
|
|
Interval c = a.intersection(b);
|
|
Unit u = unit(bi).restrictToInterval(c);
|
|
result.addUnit(u);
|
|
}
|
|
|
|
if (a.e < b.e || (a.e == b.e && b.rc))
|
|
ai++;
|
|
else
|
|
bi++;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
~passes~ adds the indices of all moving object entries to ~result~, which
|
|
ever assume the specified value. It checks the value against the minimum
|
|
and maximum of the moving object first and if the value is between, then
|
|
iterates over all units of the moving object entry.
|
|
|
|
*/
|
|
template<class Unit>
|
|
void MFsObjects<Unit>::passes(typename Unit::Attr & value,
|
|
CRelAlgebra::LongInts & result)
|
|
{
|
|
result.Clear();
|
|
|
|
if (!value.IsDefined())
|
|
return;
|
|
|
|
for (auto & iterator : GetFilter()) {
|
|
int row = iterator.GetRow();
|
|
MObject& m = (*m_MObjects)[row];
|
|
|
|
if (Unit::compare(m.minimum, value) != 1 &&
|
|
Unit::compare(m.maximum, value) != -1)
|
|
{
|
|
for (int ui = unitFirst(row); ui < unitAfterLast(row); ui++)
|
|
if (unit(ui).passes(value)) {
|
|
result.Append(row);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
~passes~ adds the indices of all moving object entries to ~result~, which
|
|
ever assume a value in the specified range.
|
|
It checks the range against the minimum
|
|
and maximum of the moving object first and in case of overlap, then
|
|
iterates over all units of the moving object entry.
|
|
|
|
*/
|
|
template<class Unit>
|
|
void MFsObjects<Unit>::passes(typename Unit::RAttr & value,
|
|
CRelAlgebra::LongInts & result)
|
|
{
|
|
result.Clear();
|
|
|
|
if (!value.IsDefined())
|
|
return;
|
|
|
|
typename Unit::Attr max, min;
|
|
value.Maximum(max);
|
|
value.Minimum(min);
|
|
|
|
for (auto & iterator : GetFilter()) {
|
|
int row = iterator.GetRow();
|
|
MObject& m = (*m_MObjects)[row];
|
|
|
|
if (Unit::compare(m.minimum, max) != 1 &&
|
|
Unit::compare(m.maximum, min) != -1)
|
|
{
|
|
for (int ui = unitFirst(row); ui < unitAfterLast(row); ui++)
|
|
if (unit(ui).passes(value)) {
|
|
result.Append(row);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
~at~ restricts the all moving object entries to the specified value.
|
|
the computed new units are added to ~result~
|
|
|
|
*/
|
|
template<class Unit>
|
|
void MFsObjects<Unit>::at(typename Unit::Attr & value, MFsObjects & result)
|
|
{
|
|
if (!value.IsDefined()) {
|
|
for (uint64_t i = 0; i < GetFilter().GetCount(); i++)
|
|
result.addMObject();
|
|
|
|
return;
|
|
}
|
|
|
|
for (auto & iterator : GetFilter()) {
|
|
int row = iterator.GetRow();
|
|
MObject& m = (*m_MObjects)[row];
|
|
|
|
result.addMObject();
|
|
|
|
if (Unit::compare(m.minimum, value) != 1 &&
|
|
Unit::compare(m.maximum, value) != -1)
|
|
{
|
|
for (int ui = unitFirst(row); ui < unitAfterLast(row); ui++)
|
|
unit(ui).at(value, result);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
~at~ restricts the all moving object entries to the specified
|
|
range. the computed new units are added to ~result~
|
|
|
|
*/
|
|
template<class Unit>
|
|
void MFsObjects<Unit>::at(typename Unit::RAttr & value, MFsObjects & result)
|
|
{
|
|
if (!value.IsDefined()) {
|
|
for (uint64_t i = 0; i < GetFilter().GetCount(); i++)
|
|
result.addMObject();
|
|
|
|
return;
|
|
}
|
|
|
|
typename Unit::Attr max, min;
|
|
value.Maximum(max);
|
|
value.Minimum(min);
|
|
|
|
for (auto & iterator : GetFilter()) {
|
|
int row = iterator.GetRow();
|
|
MObject& m = (*m_MObjects)[row];
|
|
|
|
result.addMObject();
|
|
|
|
if (Unit::compare(m.minimum, max) != 1 &&
|
|
Unit::compare(m.maximum, min) != -1)
|
|
{
|
|
for (int ui = unitFirst(row); ui < unitAfterLast(row); ui++)
|
|
unit(ui).at(value, result);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
~addMObject~ adds a new moving object entry to the attribute array
|
|
|
|
*/
|
|
template<class Unit>
|
|
void MFsObjects<Unit>::addMObject()
|
|
{
|
|
m_MObjects->emplace_back(MObject{ static_cast<int>(m_Units->size()) });
|
|
m_DefTimes->addRow();
|
|
}
|
|
|
|
/*
|
|
~addUnit~ adds a new unit to the last added moving object entry.
|
|
minimum and maximum of the moving object entry are updated.
|
|
|
|
*/
|
|
template<class Unit>
|
|
void MFsObjects<Unit>::addUnit(Unit & unit)
|
|
{
|
|
m_Units->emplace_back(unit);
|
|
m_DefTimes->addInterval(unit.interval());
|
|
|
|
if (unitCount(m_MObjects->size() - 1) == 0 ||
|
|
unit.minimum() < m_MObjects->back().minimum)
|
|
{
|
|
m_MObjects->back().minimum = unit.minimum();
|
|
}
|
|
|
|
if (unitCount(m_MObjects->size() - 1) == 0 ||
|
|
m_MObjects->back().maximum < unit.maximum())
|
|
{
|
|
m_MObjects->back().maximum = unit.maximum();
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
~addRandomUnits~ adds random units to every moving object entry
|
|
|
|
*/
|
|
template<class Unit>
|
|
void MFsObjects<Unit>::addRandomUnits(CcInt& size, MFsObjects & result)
|
|
{
|
|
if (!size.IsDefined())
|
|
return;
|
|
|
|
int count = size.GetValue();
|
|
|
|
for (auto & iterator : GetFilter()) {
|
|
int row = iterator.GetRow();
|
|
|
|
Interval interval {0, 0, true, false};
|
|
|
|
if (unitCount(row) != 0) {
|
|
Unit& u = unit(unitAfterLast(row) - 1);
|
|
interval.s = (static_cast<int64_t>(u.interval().e * 1.1)
|
|
/ MILLISECONDS + 1) * MILLISECONDS;
|
|
}
|
|
|
|
result.Append(*this, row);
|
|
|
|
for (int i = 0; i < count; i++) {
|
|
interval.e = interval.s + (5 + (rand() % 5)) * MILLISECONDS;
|
|
Unit u = Unit::random(interval);
|
|
result.addUnit(u);
|
|
interval.s = interval.e;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
1.2.4 Helper Functions
|
|
|
|
The following functions are for convenience.
|
|
|
|
~unitFirst~ returns the index of the first unit of the moving object entry
|
|
with index ~mobject~
|
|
|
|
*/
|
|
template<class Unit>
|
|
int MFsObjects<Unit>::unitFirst(int mobject) const
|
|
{
|
|
return (*m_MObjects)[mobject].firstUnit;
|
|
}
|
|
|
|
/*
|
|
~unitAfterLast~ returns one more than the index of the last unit of
|
|
the moving object entry
|
|
with index ~mobject~
|
|
|
|
*/
|
|
template<class Unit>
|
|
int MFsObjects<Unit>::unitAfterLast(int mobject) const
|
|
{
|
|
return mobject < static_cast<int>(m_MObjects->size()) - 1 ?
|
|
(*m_MObjects)[mobject + 1].firstUnit :
|
|
m_Units->size();
|
|
}
|
|
|
|
/*
|
|
~unitCount~ returns the number of units of the moving object entry
|
|
with index ~mobject~
|
|
|
|
*/
|
|
template<class Unit>
|
|
int MFsObjects<Unit>::unitCount(int mobject) const
|
|
{
|
|
return unitAfterLast(mobject) - unitFirst(mobject);
|
|
}
|
|
|
|
/*
|
|
~unit~ returns unit for a specified unit index
|
|
|
|
*/
|
|
template<class Unit>
|
|
Unit & MFsObjects<Unit>::unit(int index) const
|
|
{
|
|
return (*m_Units)[index];
|
|
}
|
|
|
|
}
|