//-----------------------------------------------------------------------------
//! Called on any change on the node, field might by also NULL
//-----------------------------------------------------------------------------
void SoMinimalEnclosingCircle::nodeChanged(SoNodeSensor* sensor)
{
   // Get the field which caused the notification.
   SoField* field = sensor->getTriggerField();

   // Handle changed fields here
   if (field == 0) {
      // at least one of the children was changed
      getPointSet(_pointSet3D, _size3D);
      _pointSet2D = new SbVec2f[_size3D];
   }
}
void RangeProfilePlotManager::signatureDeleted(Subject& subject, const std::string& signal, const boost::any& value)
{
   Signature* pSig = dynamic_cast<Signature*>(&subject);
   PointSet* pSet = getPointSet(pSig);
   if (pSet != NULL)
   {
      VERIFYNRV(mpView != NULL);
      mpView->deleteObject(pSet);
      mSigPointSets.erase(pSig);
      mpView->refresh();
   }
}
void RangeProfilePlotManager::signatureRenamed(Subject& subject, const std::string& signal, const boost::any& value)
{
   std::string newName = boost::any_cast<std::string>(value);
   DataDescriptor& desc = dynamic_cast<DataDescriptor&>(subject);
   for (std::map<Signature*, std::string>::iterator sig = mSigPointSets.begin(); sig != mSigPointSets.end(); ++sig)
   {
      if (sig->first->getDataDescriptor() == &desc)
      {
         PointSet* pSet = getPointSet(sig->first);
         if (pSet != NULL)
         {
            pSet->setObjectName(newName);
            mSigPointSets[sig->first] = newName;
            return;
         }
      }
   }
}
bool RangeProfilePlotManager::plotProfile(Signature* pSignature)
{
   VERIFY(mpView && pSignature);
   std::string plotName = pSignature->getDisplayName();
   if (plotName.empty())
   {
      plotName = pSignature->getName();
   }
   if (plotName == "Difference")
   {
      QMessageBox::warning(Service<DesktopServices>()->getMainWidget(),
         "Invalid signature", "Signatures can not be named 'Difference' as this is a reserved "
                              "name for this plot. Please rename your signature and try again.");
      return false;
   }
   const Units* pXUnits = NULL;
   const Units* pYUnits = NULL;
   std::vector<double> xData;
   std::vector<double> yData;
   std::set<std::string> dataNames = pSignature->getDataNames();
   for (std::set<std::string>::const_iterator dataName = dataNames.begin();
      dataName != dataNames.end() && (pXUnits == NULL || pYUnits == NULL);
      ++dataName)
   {
      const Units* pUnits = pSignature->getUnits(*dataName);
      if (pUnits == NULL)
      {
         continue;
      }
      if (pUnits->getUnitType() == DISTANCE)
      {
         if (pXUnits == NULL)
         {
            pXUnits = pUnits;
            xData = dv_cast<std::vector<double> >(pSignature->getData(*dataName), std::vector<double>());
         }
      }
      else if (pYUnits == NULL)
      {
         pYUnits = pUnits;
         yData = dv_cast<std::vector<double> >(pSignature->getData(*dataName), std::vector<double>());
      }
   }
   if (xData.empty() || xData.size() != yData.size())
   {
      QMessageBox::warning(Service<DesktopServices>()->getMainWidget(),
         "Invalid signature", QString("Signatures must have a distance axis. '%1' does not and will not be plotted.")
                                 .arg(QString::fromStdString(pSignature->getName())));
      return false;
   }
   std::map<Signature*, std::string>::iterator oldPointSet = mSigPointSets.find(pSignature);
   PointSet* pSet = getPointSet(pSignature);
   if (pSet != NULL)
   {
      pSet->clear(true);
   }
   std::list<PlotObject*> curObjects;
   mpView->getObjects(POINT_SET, curObjects);
   if (pSet == NULL)
   {
      std::vector<ColorType> excluded;
      excluded.push_back(ColorType(255, 255, 255)); // background
      excluded.push_back(ColorType(200, 0, 0)); // color for the difference plot
      for (std::list<PlotObject*>::const_iterator cur = curObjects.begin(); cur != curObjects.end(); ++cur)
      {
         excluded.push_back(static_cast<PointSet*>(*cur)->getLineColor());
      }
      pSet = static_cast<PointSet*>(mpView->addObject(POINT_SET, true));
      mSigPointSets[pSignature] = plotName;
      pSignature->attach(SIGNAL_NAME(Subject, Deleted), Slot(this, &RangeProfilePlotManager::signatureDeleted));
      pSignature->getDataDescriptor()->attach(SIGNAL_NAME(DataDescriptor, Renamed),
         Slot(this, &RangeProfilePlotManager::signatureRenamed));
      std::vector<ColorType> colors;
      ColorType::getUniqueColors(1, colors, excluded);
      if (!colors.empty())
      {
         pSet->setLineColor(colors.front());
      }
   }
   pSet->setObjectName(plotName);
   for (size_t idx = 0; idx < xData.size(); ++idx)
   {
      pSet->addPoint(xData[idx], yData[idx]);
   }

   VERIFY(mpPlot);
   Axis* pBottom = mpPlot->getAxis(AXIS_BOTTOM);
   Axis* pLeft = mpPlot->getAxis(AXIS_LEFT);
   VERIFYRV(pBottom && pLeft, NULL);
   if (pBottom->getTitle().empty())
   {
      pBottom->setTitle(pXUnits->getUnitName());
   }
   if (pLeft->getTitle().empty())
   {
      pLeft->setTitle(pYUnits->getUnitName());
   }
   else if (pLeft->getTitle() != pYUnits->getUnitName())
   {
      Axis* pRight = mpPlot->getAxis(AXIS_RIGHT);
      VERIFYRV(pRight, NULL);
      if (pRight->getTitle().empty())
      {
         pRight->setTitle(pYUnits->getUnitName());
      }
   }

   std::string classificationText = dv_cast<std::string>(pSignature->getMetadata()->getAttribute("Raw Classification"),
      mpPlot->getClassificationText());
   if (classificationText.empty() == false)
   {
      FactoryResource<Classification> pClassification;
      if (pClassification->setClassification(classificationText) == true)
      {
         mpPlot->setClassification(pClassification.get());
      }
      else
      {
         QMessageBox::warning(Service<DesktopServices>()->getMainWidget(), QString::fromStdString(getName()),
            "The plot could not be updated with the signature classification.  Please ensure that the plot "
            "has the proper classification.");
      }
   }

   getDockWindow()->show();
   mpView->zoomExtents();
   mpView->refresh();

   return true;
}