📄 mtentry.cpp
字号:
/*********************************************************************
* *
* Copyright (c) 1997,1998, 1999 *
* Multimedia DB Group and DEIS - CSITE-CNR, *
* University of Bologna, Bologna, ITALY. *
* *
* All Rights Reserved. *
* *
* Permission to use, copy, and distribute this software and its *
* documentation for NON-COMMERCIAL purposes and without fee is *
* hereby granted provided that this copyright notice appears in *
* all copies. *
* *
* THE AUTHORS MAKE NO REPRESENTATIONS OR WARRANTIES ABOUT THE *
* SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING *
* BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, *
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. THE AUTHOR *
* SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A *
* RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS *
* DERIVATIVES. *
* *
*********************************************************************/
#include "MTentry.h"
#include "MT.h"
tb_function TB_FUNCTION=MIN_R_INCR;
int sizeofEntry() {
if(sizeofObject()) return(sizeofObject()+3*sizeof(double)+2*sizeof(BOOL)); // compressedEntry is: Object, rmin, rmax, distance, splitted, recomp
return 0;
}
GiSTpenalty *
MTentry::Penalty(const GiSTentry &newEntry) const
{
double retval;
assert(newEntry.IsA()==MTENTRY_CLASS);
const MTentry& e=(const MTentry &)newEntry;
double dist=object().distance(e.object())+e.maxradius();
// printf("Distance between %s & %s=%f\n", object().name, e.object().name, dist);
// return area enlargement
switch(TB_FUNCTION) {
case MIN_R_INCR: {
retval=dist-maxradius();
if(retval<0) retval=-maxDist()+dist;
// if the entry can fit in (more than) a node without enlarging its radius, we assign it to its nearest node
break;
}
case MIN_OVERLAP: {
retval=0;
for (int i=0; i<Node()->NumEntries(); i++) { // compute total overlap for this node
const MTentry& sibling=(const MTentry &)*(*(Node()))[i].Ptr();
double cost=sibling.maxradius()+dist-object().distance(sibling.object());
retval+=MAX(cost, 0);
}
break;
}
}
// cout << "Penalty for " << newEntry << " in " << this << " = " << retval << " (distance = " << dist << ")" << endl;
return new MTpenalty(retval, dist);
}
GiSTpenalty *
MTentry::Penalty(const GiSTentry &newEntry, MTpenalty *minPenalty) const
// in this case we can avoid to compute some distances by using some stored information:
// minPenalty (the minimum penalty achieved so far),
// newEntry.key->distance (the distance of the entry from the parent of this entry, stored in the SearchMinPenalty method),
// and maxradius.
{
double retval;
assert(newEntry.IsA()==MTENTRY_CLASS);
const MTentry& e=(const MTentry &)newEntry;
double dist;
// printf("Distance between %s & %s=%f\n", object().name, e.object().name, dist);
// return area enlargement
switch(TB_FUNCTION) {
case MIN_R_INCR: {
if(((MTkey *)newEntry.Key())->distance>0) { // in this case is possible to prune some entries using triangular inequality
double distPen=fabs(((MTkey *)newEntry.Key())->distance-Key()->distance)-maxradius();
MTpenalty *tmpPen;
if(distPen>=0) tmpPen=new MTpenalty(distPen, 0);
else tmpPen=new MTpenalty(distPen+maxradius()-maxDist(), 0);
if((minPenalty!=NULL)&&!((*tmpPen)<(*minPenalty))) {
delete tmpPen;
return new MTpenalty(MAXDOUBLE, 0); // ... and we avoid to compute this distance
}
delete tmpPen;
}
dist=object().distance(e.object())+e.maxradius(); // compute the distance
retval=dist-maxradius();
if(retval<0) retval=-maxDist()+dist;
// if the entry can fit in (more than) a node without enlarging its radius, we assign it to its nearest node
break;
}
case MIN_OVERLAP: {
retval=0;
dist=object().distance(e.object())+e.maxradius();
for (int i=0; i<Node()->NumEntries(); i++) { // compute total overlap for this node
const MTentry& sibling=(const MTentry &)*(*(Node()))[i].Ptr();
double cost=sibling.maxradius()+dist-object().distance(sibling.object());
retval+=MAX(cost, 0);
}
break;
}
}
// cout << "Penalty for " << newEntry << " in " << this << " = " << retval << " (distance = " << dist << ")" << endl;
return new MTpenalty(retval, dist);
}
GiSTcompressedEntry
MTentry::Compress() const
{
GiSTcompressedEntry compressedEntry;
double rmin=((MTkey *)key)->minradius(), rmax=((MTkey *)key)->maxradius(), dist=((MTkey *)key)->distance;
int sizeofObject=((MTkey *)key)->object().CompressedLength();
BOOL splitted=((MTkey *)key)->splitted, recomp=((MTkey *)key)->recomp;
compressedEntry.key=new char[CompressedLength()];
((MTkey *)key)->object().Compress(compressedEntry.key); // compress the object
memcpy(compressedEntry.key+sizeofObject, &rmin, sizeof(double));
memcpy(compressedEntry.key+sizeofObject+sizeof(double), &rmax, sizeof(double));
memcpy(compressedEntry.key+sizeofObject+2*sizeof(double), &dist, sizeof(double));
memcpy(compressedEntry.key+sizeofObject+3*sizeof(double), &splitted, sizeof(BOOL));
memcpy(compressedEntry.key+sizeofObject+3*sizeof(double)+sizeof(BOOL), &recomp, sizeof(BOOL));
// Object obj(compressedEntry.key); // decompress the object
compressedEntry.keyLen=CompressedLength();
compressedEntry.ptr=ptr;
return compressedEntry;
}
void
MTentry::Decompress(const GiSTcompressedEntry entry)
{
Object obj(entry.key); // decompress the object
double rmin, rmax, dist;
int sizeofObject=obj.CompressedLength();
BOOL splitted, recomp;
memcpy(&rmin, entry.key+sizeofObject, sizeof(double));
memcpy(&rmax, entry.key+sizeofObject+sizeof(double), sizeof(double));
memcpy(&dist, entry.key+sizeofObject+2*sizeof(double), sizeof(double));
memcpy(&dist, entry.key+sizeofObject+2*sizeof(double), sizeof(double));
memcpy(&splitted, entry.key+sizeofObject+3*sizeof(double), sizeof(BOOL));
memcpy(&recomp, entry.key+sizeofObject+3*sizeof(double)+sizeof(BOOL), sizeof(BOOL));
key=new MTkey(obj, rmin, rmax, dist, splitted, recomp);
ptr=entry.ptr;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -