#include "onf_stepconvertrastertovector.h"
#include "imgproc/types_c.h"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/core/core.hpp"
ONF_StepConvertRasterToVector::ONF_StepConvertRasterToVector() : SuperClass()
{
_filter = true;
_surfaceThreshold = 6250.0;
}
QString ONF_StepConvertRasterToVector::description() const
{
return tr("Convertir un raster en polygones");
}
QString ONF_StepConvertRasterToVector::detailledDescription() const
{
return tr("");
}
QString ONF_StepConvertRasterToVector::inputDescription() const
{
return SuperClass::inputDescription() + tr("
");
}
QString ONF_StepConvertRasterToVector::outputDescription() const
{
return SuperClass::outputDescription() + tr("
");
}
QString ONF_StepConvertRasterToVector::detailsDescription() const
{
return tr("");
}
QString ONF_StepConvertRasterToVector::URL() const
{
//return tr("STEP URL HERE");
return CT_AbstractStep::URL(); //by default URL of the plugin
}
CT_VirtualAbstractStep* ONF_StepConvertRasterToVector::createNewInstance() const
{
return new ONF_StepConvertRasterToVector();
}
//////////////////// PROTECTED METHODS //////////////////
void ONF_StepConvertRasterToVector::declareInputModels(CT_StepInModelStructureManager& manager)
{
manager.addResult(_inResult, tr("Segmentation"));
manager.setZeroOrMoreRootGroup(_inResult, _inZeroOrMoreRootGroup);
manager.addGroup(_inZeroOrMoreRootGroup, _inGroup);
manager.addItem(_inGroup, _inClusters, tr("Segmentation"));
}
void ONF_StepConvertRasterToVector::declareOutputModels(CT_StepOutModelStructureManager& manager)
{
manager.addResultCopy(_inResult);
manager.addGroup(_inGroup, _groupCluster, tr("Polygone"));
manager.addItem(_groupCluster, _outPolygon, tr("Polygone"));
manager.addItemAttribute(_outPolygon, _outPolygonIDAtt, PS_CATEGORY_MANAGER->findByUniqueName(CT_AbstractCategory::DATA_ID), tr("PolygonID"));
}
void ONF_StepConvertRasterToVector::fillPostInputConfigurationDialog(CT_StepConfigurableDialog *postInputConfigDialog)
{
postInputConfigDialog->addBool(tr("Ne concerver que les polygones s'une surface minimale"), "", "", _filter);
postInputConfigDialog->addDouble(tr("Seuil de surface minimale"), "m²", 0, std::numeric_limits::max(), 2, _surfaceThreshold);
}
void ONF_StepConvertRasterToVector::compute()
{
int PolygonID = 1;
for (CT_StandardItemGroup* grp : _inGroup.iterateOutputs(_inResult))
{
for (const CT_AbstractImage2D* clusters : grp->singularItems(_inClusters))
{
if (isStopped()) {return;}
QMap areas;
for (int y = 0 ; y < clusters->ydim() ; y++)
{
for (int x = 0 ; x < clusters->xdim() ; x++)
{
size_t index;
clusters->index(x, y, index);
double cluster = clusters->valueAtIndexAsDouble(index);
if (!qFuzzyCompare(cluster, clusters->NAAsDouble()))
{
if (!areas.contains(cluster)) {areas.insert(cluster, new ONF_StepConvertRasterToVector::pixelsArea());}
ONF_StepConvertRasterToVector::pixelsArea *area = areas.value(cluster);
if (x < area->_xmin) {area->_xmin = x;}
if (x > area->_xmax) {area->_xmax = x;}
if (y < area->_ymin) {area->_ymin = y;}
if (y > area->_ymax) {area->_ymax = y;}
}
}
}
QMapIterator it(areas);
while (it.hasNext())
{
it.next();
double cluster = it.key();
if (cluster > 0)
{
ONF_StepConvertRasterToVector::pixelsArea* area = it.value();
// Create a 1-pixel buffer around each crown
area->_xmin--;
area->_ymin--;
area->_xmax++;
area->_ymax++;
double minx = clusters->minX() + (area->_xmin) * clusters->resolution();
double miny = clusters->maxY() - (area->_ymax + 1) * clusters->resolution();
int dimx = area->_xmax - area->_xmin + 1;
int dimy = area->_ymax - area->_ymin + 1;
CT_Image2D *clusterMask = new CT_Image2D(minx, miny, dimx, dimy, clusters->resolution(), 0, 0, 0);
for (int y = area->_ymin ; y <= area->_ymax ; y++)
{
for (int x = area->_xmin ; x <= area->_xmax ; x++)
{
size_t index;
clusters->index(x, y, index);
if (qFuzzyCompare(clusters->valueAtIndexAsDouble(index), cluster))
{
int localCol = x - area->_xmin;
int localLin = y - area->_ymin;
clusterMask->setValue(localCol, localLin, 1);
}
}
}
std::vector > contours;
cv::Mat_ maskTmp = clusterMask->getMat().clone();
cv::findContours(maskTmp, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
maskTmp.release();
if (contours.size() > 0)
{
QList polygonDataList;
for (int i = 0; i < contours.size(); i++)
{
std::vector contour = contours[i];
QVector vertices;
std::reverse(contour.begin(), contour.end());
clusterMask->convertPixelContourToPolygon(contour, vertices);
CT_Polygon2DData* polyData = new CT_Polygon2DData(vertices);
polygonDataList.append(polyData);
}
for (CT_Polygon2DData* poly : polygonDataList)
{
CT_Image2D clusterMaskTmp(minx, miny, dimx, dimy, clusters->resolution(), 0, 0, 0);
for (size_t index = 0 ; index < clusterMask->nCells() ; index++)
{
double val = clusterMask->valueAtIndexAsDouble(index);
Eigen::Vector3d center;
clusterMask->getCellCenterCoordinates(index, center);
bool inside = false;
if (poly->contains(center(0), center(1)))
{
inside = true;
}
if (inside && val < 1)
{
clusterMaskTmp.setValueAtIndex(index, 1);
} else {
clusterMaskTmp.setValueAtIndex(index, 0);
}
}
contours.clear();
maskTmp = clusterMaskTmp.getMat();
cv::findContours(maskTmp, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
maskTmp.release();
for (int i = 0; i < contours.size(); i++)
{
std::vector contour = contours[i];
QVector vertices;
std::reverse(contour.begin(), contour.end());
clusterMask->convertPixelContourToPolygon(contour, vertices);
CT_Polygon2DData* polyData = new CT_Polygon2DData(vertices);
poly->addInnerPolygon(polyData);
}
if (!_filter || (_filter && poly->getArea() > _surfaceThreshold))
{
CT_StandardItemGroup *clusterGroup = new CT_StandardItemGroup();
grp->addGroup(_groupCluster, clusterGroup);
CT_Polygon2D* po = new CT_Polygon2D(poly);
clusterGroup->addSingularItem(_outPolygon, po);
po->addItemAttribute(_outPolygonIDAtt, new CT_StdItemAttributeT(PS_CATEGORY_MANAGER->findByUniqueName(CT_AbstractCategory::DATA_ID), PolygonID++));
}
}
}
delete clusterMask;
}
}
qDeleteAll(areas);
}
}
}