bool ccGraphicalSegmentationTool::start()
{
    assert(m_polyVertices && m_segmentationPoly);

    if (!m_associatedWin)
    {
        ccConsole::Warning("[Graphical Segmentation Tool] No associated window!");
        return false;
    }

    m_segmentationPoly->clear();
    m_polyVertices->clear();

    //the user must not close this window!
    m_associatedWin->setUnclosable(true);
    //m_associatedWin->setPerspectiveState(false,false);
    m_associatedWin->addToOwnDB(m_segmentationPoly);
    m_associatedWin->setPickingMode(ccGLWindow::NO_PICKING);
    pauseSegmentationMode(false);

    m_somethingHasChanged = false;

    reset();

    show();

    return true;
}
bool ccGraphicalSegmentationTool::start()
{
	assert(m_polyVertices && m_segmentationPoly);

	if (!m_associatedWin)
	{
		ccLog::Warning("[Graphical Segmentation Tool] No associated window!");
		return false;
	}

	m_segmentationPoly->clear();
	m_polyVertices->clear();
	allowPolylineExport(false);

	//the user must not close this window!
	m_associatedWin->setUnclosable(true);
	m_associatedWin->addToOwnDB(m_segmentationPoly);
	m_associatedWin->setPickingMode(ccGLWindow::NO_PICKING);
	pauseSegmentationMode(false);

	m_somethingHasChanged = false;

	reset();

	return ccOverlayDialog::start();
}
void ccGraphicalSegmentationTool::doSetRectangularSelection()
{
	if (m_rectangularSelection)
		return;

	selectionModelButton->setDefaultAction(actionSetRectangularSelection);

	m_rectangularSelection=true;
	if (m_state != PAUSED)
	{
		pauseSegmentationMode(true);
		pauseSegmentationMode(false);
	}

	m_associatedWin->displayNewMessage(QString(),ccGLWindow::UPPER_CENTER_MESSAGE); //clear the area
	m_associatedWin->displayNewMessage("Segmentation [ON] (rectangular selection)",ccGLWindow::UPPER_CENTER_MESSAGE,false,3600,ccGLWindow::MANUAL_SEGMENTATION_MESSAGE);
	m_associatedWin->displayNewMessage("Right click: set opposite corners",ccGLWindow::UPPER_CENTER_MESSAGE,true,3600,ccGLWindow::MANUAL_SEGMENTATION_MESSAGE);
}
void ccGraphicalSegmentationTool::doSetRectangularSelection()
{
	if (m_rectangularSelection)
		return;

	QIcon icon(QString::fromUtf8(":/CC/Comp/images/comp/rectangleSelect.png"));
	//QIcon icon;
	//icon.addFile(QString::fromUtf8(":/CC/Comp/images/comp/rectangleSelect.png"), QSize(), QIcon::Normal, QIcon::Off);
	selectionModelButton->setIcon(icon);

	m_rectangularSelection=true;
	if (m_state != PAUSED)
	{
		pauseSegmentationMode(true);
		pauseSegmentationMode(false);
	}

	m_associatedWin->displayNewMessage("Segmentation [ON] (rectangular selection) - Right click: set opposite corners",3600);
}
void ccGraphicalSegmentationTool::doSetPolylineSelection()
{
	if (!m_rectangularSelection)
		return;

	QIcon icon(QString::fromUtf8(":/CC/Comp/images/comp/polygonSelect.png"));
	//QIcon icon;
	//icon.addFile(QString::fromUtf8(":/CC/Comp/images/comp/polygonSelect.png"), QSize(), QIcon::Normal, QIcon::Off);
	selectionModelButton->setIcon(icon);

	m_rectangularSelection=false;
	if (m_state != PAUSED)
	{
		pauseSegmentationMode(true);
		pauseSegmentationMode(false);
	}

	m_associatedWin->displayNewMessage("Segmentation [ON] (polygonal selection) - Right click: add contour points / Left click: close",3600);
}
void ccGraphicalSegmentationTool::doSetPolylineSelection()
{
	if (!m_rectangularSelection)
		return;

	QIcon icon(QString::fromUtf8(":/CC/images/ccPolygonSelect.png"));
	selectionModelButton->setIcon(icon);

	m_rectangularSelection=false;
	if (m_state != PAUSED)
	{
		pauseSegmentationMode(true);
		pauseSegmentationMode(false);
	}

	m_associatedWin->displayNewMessage(QString(),ccGLWindow::UPPER_CENTER_MESSAGE); //clear the area
	m_associatedWin->displayNewMessage("Segmentation [ON] (rectangular selection)",ccGLWindow::UPPER_CENTER_MESSAGE,false,3600,ccGLWindow::MANUAL_SEGMENTATION_MESSAGE);
	m_associatedWin->displayNewMessage("Right click: set opposite corners",ccGLWindow::UPPER_CENTER_MESSAGE,true,3600,ccGLWindow::MANUAL_SEGMENTATION_MESSAGE);
}
void ccGraphicalSegmentationTool::segment(bool inside)
{
    if (!m_associatedWin)
        return;

    if (!m_segmentationPoly)
    {
        ccConsole::Error("No polyline defined!");
        return;
    }

    if (!m_segmentationPoly->getClosingState())
    {
        ccConsole::Error("Define and/or close the segmentation border first! (right click to close)");
        return;
    }

    //viewing parameters
    const double* MM = m_associatedWin->getModelViewMatd(); //viewMat
	const double* MP = m_associatedWin->getProjectionMatd(); //projMat
	const float half_w = (float)m_associatedWin->width() * 0.5f;
	const float half_h = (float)m_associatedWin->height() * 0.5f;

	int VP[4];
	m_associatedWin->getViewportArray(VP);

	CCVector3 P;
	CCVector2 P2D;
	bool pointInside;

    //for each selected entity
    for (ccHObject::Container::iterator p=m_toSegment.begin();p!=m_toSegment.end();++p)
    {
        ccGenericPointCloud* cloud = ccHObjectCaster::ToGenericPointCloud(*p);
        assert(cloud);

        ccGenericPointCloud::VisibilityTableType* vis = cloud->getTheVisibilityArray();
		assert(vis);

        unsigned i,cloudSize = cloud->size();

        //we project each point and we check if it falls inside the segmentation polyline
        for (i=0;i<cloudSize;++i)
        {
			cloud->getPoint(i,P);

			GLdouble xp,yp,zp;
			gluProject(P.x,P.y,P.z,MM,MP,VP,&xp,&yp,&zp);
			P2D.x = xp - half_w;
			P2D.y = yp - half_h;

			pointInside = CCLib::ManualSegmentationTools::isPointInsidePoly(P2D,m_segmentationPoly);

            if ((inside && !pointInside)||(!inside && pointInside))
				vis->setValue(i,0); //hiddenValue=0
        }
    }

    m_somethingHasChanged = true;
    validButton->setEnabled(true);
	validAndDeleteButton->setEnabled(true);
    razButton->setEnabled(true);
    pauseSegmentationMode(true);
}
void ccGraphicalSegmentationTool::segment(bool keepPointsInside)
{
	if (!m_associatedWin)
		return;

	if (!m_segmentationPoly)
	{
		ccLog::Error("No polyline defined!");
		return;
	}

	if (!m_segmentationPoly->isClosed())
	{
		ccLog::Error("Define and/or close the segmentation polygon first! (right click to close)");
		return;
	}

	//viewing parameters
	const double* MM = m_associatedWin->getModelViewMatd(); //viewMat
	const double* MP = m_associatedWin->getProjectionMatd(); //projMat
	const GLdouble half_w = static_cast<GLdouble>(m_associatedWin->width())/2;
	const GLdouble half_h = static_cast<GLdouble>(m_associatedWin->height())/2;

	int VP[4];
	m_associatedWin->getViewportArray(VP);

	//for each selected entity
	for (std::set<ccHObject*>::iterator p = m_toSegment.begin(); p != m_toSegment.end(); ++p)
	{
		ccGenericPointCloud* cloud = ccHObjectCaster::ToGenericPointCloud(*p);
		assert(cloud);

		ccGenericPointCloud::VisibilityTableType* visibilityArray = cloud->getTheVisibilityArray();
		assert(visibilityArray);

		unsigned cloudSize = cloud->size();

		//we project each point and we check if it falls inside the segmentation polyline
		for (unsigned i=0; i<cloudSize; ++i)
		{
			if (visibilityArray->getValue(i) == POINT_VISIBLE)
			{
				CCVector3 P;
				cloud->getPoint(i,P);

				GLdouble xp,yp,zp;
				gluProject(P.x,P.y,P.z,MM,MP,VP,&xp,&yp,&zp);

				CCVector2 P2D(	static_cast<PointCoordinateType>(xp-half_w),
								static_cast<PointCoordinateType>(yp-half_h) );
				bool pointInside = CCLib::ManualSegmentationTools::isPointInsidePoly(P2D,m_segmentationPoly);

				visibilityArray->setValue(i, keepPointsInside != pointInside ? POINT_HIDDEN : POINT_VISIBLE );
			}
		}
	}

	m_somethingHasChanged = true;
	validButton->setEnabled(true);
	validAndDeleteButton->setEnabled(true);
	razButton->setEnabled(true);
	pauseSegmentationMode(true);
}
void ccGraphicalSegmentationTool::segment(bool keepPointsInside)
{
	if (!m_associatedWin)
		return;

	if (!m_segmentationPoly)
	{
		ccLog::Error("No polyline defined!");
		return;
	}

	if (!m_segmentationPoly->isClosed())
	{
		ccLog::Error("Define and/or close the segmentation polygon first! (right click to close)");
		return;
	}

	//viewing parameters
	ccGLCameraParameters camera;
	m_associatedWin->getGLCameraParameters(camera);
	const double half_w = camera.viewport[2] / 2.0;
	const double half_h = camera.viewport[3] / 2.0;

	//for each selected entity
	for (QSet<ccHObject*>::const_iterator p = m_toSegment.begin(); p != m_toSegment.end(); ++p)
	{
		ccGenericPointCloud* cloud = ccHObjectCaster::ToGenericPointCloud(*p);
		assert(cloud);

		ccGenericPointCloud::VisibilityTableType* visibilityArray = cloud->getTheVisibilityArray();
		assert(visibilityArray);

		unsigned cloudSize = cloud->size();

		//we project each point and we check if it falls inside the segmentation polyline
#if defined(_OPENMP)
#pragma omp parallel for
#endif
		for (int i=0; i<static_cast<int>(cloudSize); ++i)
		{
			if (visibilityArray->getValue(i) == POINT_VISIBLE)
			{
				const CCVector3* P3D = cloud->getPoint(i);

				CCVector3d Q2D;
				camera.project(*P3D, Q2D);

				CCVector2 P2D(	static_cast<PointCoordinateType>(Q2D.x-half_w),
								static_cast<PointCoordinateType>(Q2D.y-half_h) );
				
				bool pointInside = CCLib::ManualSegmentationTools::isPointInsidePoly(P2D, m_segmentationPoly);

				visibilityArray->setValue(i, keepPointsInside != pointInside ? POINT_HIDDEN : POINT_VISIBLE );
			}
		}
	}

	m_somethingHasChanged = true;
	validButton->setEnabled(true);
	validAndDeleteButton->setEnabled(true);
	razButton->setEnabled(true);
	pauseSegmentationMode(true);
}