#include "LineLayerToGraph.h"
#include <list>
#include <algorithm>
#include "ShortPathGraph.h"
#include "ShortPathModel.h"
#include "TDgraph.h"
#include "TDGraphAnalyzer.h"
#include <QVector>
#include "../units.h"
class TDOGRPointCompare
{
public:
explicit TDOGRPointCompare(double tolerance)
: mTolerance(tolerance)
{ }
bool operator()(const OGRPoint& p1, const OGRPoint& p2) const
{
if (mTolerance <= 0)
return p1.getX() == p2.getX() ? p1.getY() < p2.getY() : p1.getX() < p2.getY();
double tx1 = ceil(p1.getX() / mTolerance);
double tx2 = ceil(p2.getX() / mTolerance);
if (tx1 == tx2)
return ceil(p1.getY() / mTolerance) < ceil(p2.getY() / mTolerance);
return tx1 < tx2;
}
private:
double mTolerance;
};
template <typename RandIter, typename Type, typename CompareOp > RandIter my_binary_search(RandIter begin, RandIter end, Type val, CompareOp comp)
{
// result if not found
RandIter not_found = end;
while (true)
{
RandIter avg = begin + (end - begin) / 2;
if (begin == avg || end == avg)
{
if (!comp(*begin, val) && !comp(val, *begin))
return begin;
if ((not_found != end) && !comp(*end, val) && !comp(val, *end))
return end;
return not_found;
}
if (comp(val, *avg))
end = avg;
else if (comp(*avg, val))
begin = avg;
else
return avg;
}
return not_found;
}
struct TDTiePointInfo
{
OGRPoint mTiedPoint;
double mLength;
OGRPoint mFirstPoint;
OGRPoint mLastPoint;
};
bool TiePointInfoCompare(const TDTiePointInfo& a, const TDTiePointInfo& b)
{
if (a.mFirstPoint == b.mFirstPoint)
return a.mLastPoint.getX() == b.mLastPoint.getX() ? a.mLastPoint.getY() < b.mLastPoint.getY() : a.mLastPoint.getX() < b.mLastPoint.getX();
return a.mFirstPoint.getX() == b.mFirstPoint.getX() ? a.mFirstPoint.getY() < b.mFirstPoint.getY() : a.mFirstPoint.getX() < b.mFirstPoint.getX();
}
bool TDLineLayerToGraph::readOriginalInfo(LayerPathInfo originalPathInfo, LayerPathInfo targetpatahinfo)
{
(void)openOriginalInfo(originalPathInfo);
IF_NULL_RETRUN_FALSE(m_orgLayer)
OGRFeature *poFeature;
m_orgLayer->ResetReading();
OGRFeatureDefn * ogrfeaturedefn = m_orgLayer->GetLayerDefn();
pmoSourceSRS = m_orgLayer->GetSpatialRef();
exportPath();
wiriteInfo(targetpatahinfo, ogrfeaturedefn);
m_cachevector.clear();
if (NULL != m_pwriteDataset)
{
GDALClose(m_pwriteDataset);
}
if (NULL != m_preadDataset)
{
GDALClose(m_preadDataset);
}
return true;
}
bool TDLineLayerToGraph::doubleNear(double a, double b, double epsilon)
{
const double diff = a - b;
return diff > -epsilon && diff <= epsilon;
}
double TDLineLayerToGraph::sqrDistToSegment(OGRPoint ogrPoint,double x1, double y1, double x2, double y2, OGRPoint& minDistPoint, double epsilon)
{
double nx, ny; //normal vector
nx = y2 - y1;
ny = -(x2 - x1);
double t;
t = (ogrPoint.getX() * ny - ogrPoint.getY() * nx - x1 * ny + y1 * nx) / ((x2 - x1) * ny - (y2 - y1) * nx);
if (t < 0.0)
{
minDistPoint.setX(x1);
minDistPoint.setY(y1);
}
else if (t > 1.0)
{
minDistPoint.setX(x2);
minDistPoint.setY(y2);
}
else
{
minDistPoint.setX(x1 + t *(x2 - x1));
minDistPoint.setY(y1 + t *(y2 - y1));
}
double dist = OGR_G_Distance(&ogrPoint, &minDistPoint);
//prevent rounding errors if the point is directly on the segment
if(doubleNear(dist, 0.0, epsilon))
{
minDistPoint.setX(ogrPoint.getX());
minDistPoint.setY(ogrPoint.getY());
return 0.0;
}
return dist;
}
void TDLineLayerToGraph::makeGraph(std::vector<OGRPoint>& additionalPoints, std::vector<OGRPoint>& tiedPoint)
{
if (!m_orgLayer)
return;
int featureCount = (int)m_orgLayer->GetFeatureCount() * 2;
int step = 0;
OGRCoordinateTransformation *ct = OGRCreateCoordinateTransformation(pmoSourceSRS, pmoTargetSRS);
buildmGraph =new TDShortPathGraph(ct,true,std::get<2>(m_params));
tiedPoint = std::vector< OGRPoint >(additionalPoints.size(), OGRPoint(0.0, 0.0));
TDTiePointInfo tmpInfo;
tmpInfo.mLength = std::numeric_limits<double>::infinity();
std::vector< TDTiePointInfo> pointLengthMap;
for (auto index = 0; index < additionalPoints.size(); index++)
{
pointLengthMap.push_back(tmpInfo);
}
std::vector< TDTiePointInfo >::iterator pointLengthIt;
//Graph's points;
std::vector< OGRPoint > points;
std::list<int> la;
OGRFeature * feature = NULL;
while ((feature = m_orgLayer->GetNextFeature()) != NULL)
{
OGRMultiLineString mpl;
if (feature->GetGeometryRef()->getGeometryType() == wkbMultiLineString)
mpl = (*feature->GetGeometryRef()->toMultiLineString());
else if (feature->GetGeometryRef()->getGeometryType() == wkbLineString)
mpl.addGeometry(feature->GetGeometryRef()->toLineString());
auto geomNum = mpl.getNumGeometries();
for (int i = 0; i < geomNum; i++)
{
OGRPoint pt1, pt2;
bool isFirstPoint = true;
auto lineString = mpl.getGeometryRef(i)->toLineString();
auto numpoint = lineString->getNumPoints();
for (int j = 0; j < numpoint; j++)
{
lineString->getPoint(j, &pt2);
pt2.transformTo(pmoSourceSRS);
points.push_back(pt2);
if (!isFirstPoint)
{
int i = 0;
for (i = 0; i != additionalPoints.size(); ++i)
{
TDTiePointInfo info;
if (pt1 == pt2)
{
info.mLength = OGR_G_Distance(&additionalPoints[i], &pt1);
info.mTiedPoint = pt1;
}
else
{
info.mLength = sqrDistToSegment(additionalPoints[i], pt1.getX(), pt1.getY(),
pt2.getX(), pt2.getY(), info.mTiedPoint);
}
if (pointLengthMap[i].mLength > info.mLength)
{
Q_UNUSED(info.mTiedPoint);
info.mFirstPoint = pt1;
info.mLastPoint = pt2;
pointLengthMap[i] = info;
tiedPoint[i] = info.mTiedPoint;
}
}
}
pt1 = pt2;
isFirstPoint = false;
}
}
}
int i = 0;
for (i = 0; i < tiedPoint.size(); ++i)
{
if (tiedPoint[i] != OGRPoint(0.0, 0.0))
{
points.push_back(tiedPoint[i]);
}
}
TDOGRPointCompare pointCompare(std::get<2>(m_params));
std::sort(points.begin(), points.end(), pointCompare);
std::vector< OGRPoint >::iterator tmp = std::unique(points.begin(), points.end());
points.resize(tmp - points.begin());
for (i = 0; i < points.size(); ++i)
buildmGraph->addVertex(i, points[i]);
for (i = 0; i < tiedPoint.size(); ++i)
tiedPoint[i] = *(my_binary_search(points.begin(), points.end(), tiedPoint[i], pointCompare));
std::sort(pointLengthMap.begin(), pointLengthMap.end(), TiePointInfoCompare);
{
// fill attribute list 'la'
std::list<int> tmpAttr;
if (std::get<3>(m_params) != -1)
{
tmpAttr.push_back(3);
}
std::list<TDArcProperter*>::const_iterator it;
std::list<int>::const_iterator it2;
for (it = mProperterList.begin(); it != mProperterList.end(); ++it)
{
std::list<int> tmp = (*it)->requiredAttributes();
for (it2 = tmp.begin(); it2 != tmp.end(); ++it2)
{
tmpAttr.push_back(*it2);
}
}
tmpAttr.sort();
int lastAttrId = -1;
for (it2 = tmpAttr.begin(); it2 != tmpAttr.end(); ++it2)
{
if (*it2 == lastAttrId)
{
continue;
}
la.push_back(*it2);
lastAttrId = *it2;
}
} // end fill attribute list 'la'
OGRFeature * attrfeature = NULL;
m_orgLayer->ResetReading();
int index = 0;
while ((attrfeature = m_orgLayer->GetNextFeature()) != NULL)
{
index++;
int directionType = std::get<3>(m_params);
std::string str = "NONE";
auto fielddef = attrfeature->GetFieldDefnRef(std::get<6>(m_params));
if (NULL != fielddef)
{
str = fielddef->GetNameRef();
}
if (str.compare(std::get<7>(m_params).toStdString()) == 0)
{
directionType = 3;
}
else if (str.compare(std::get<8>(m_params).toStdString()) == 0)
{
directionType = 1;
}
else if (str.compare(std::ge