geom/src/CurveCreator/CurveCreator_Diff.cxx
2015-02-10 13:25:20 +04:00

620 lines
19 KiB
C++

// Copyright (C) 2013-2015 CEA/DEN, EDF R&D, OPEN CASCADE
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//
// File: CurveCreator_Diff.cxx
// Author: Sergey KHROMOV
#include "CurveCreator_Diff.hxx"
#include "CurveCreator_Curve.hxx"
#include <list>
//=======================================================================
// function: Constructor
// purpose:
//=======================================================================
CurveCreator_Diff::CurveCreator_Diff()
: myNbUndos (0),
myPUndo (NULL),
myPRedo (NULL)
{
}
//=======================================================================
// function: Destructor
// purpose:
//=======================================================================
CurveCreator_Diff::~CurveCreator_Diff()
{
clear();
}
//=======================================================================
// function: init
// purpose:
//=======================================================================
bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve)
{
CurveCreator_Operation::Type aType = CurveCreator_Operation::Clear;
bool isOK = false;
if (theCurve != NULL) {
clear();
// Set redo.
myPRedo = new CurveCreator_Operation;
if (myPRedo->init(aType)) {
isOK = true;
const int aNbSections = theCurve->getNbSections();
// Construct undo for Clear command.
if (aNbSections > 0) {
setNbUndos(aNbSections);
for (int i = 0; i < aNbSections && isOK; i++) {
// Add AddSection command.
isOK = addSectionToUndo(theCurve, i, myPUndo[i]);
}
}
}
if (!isOK) {
clear();
}
}
return isOK;
}
//=======================================================================
// function: init
// purpose:
//=======================================================================
bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve,
const CurveCreator_Operation::Type theType,
const int theIntParam)
{
bool isOK = false;
if (theCurve != NULL) {
clear();
// Set redo.
myPRedo = new CurveCreator_Operation;
if (myPRedo->init(theType, theIntParam)) {
// Construct undo for RemoveSection command.
// If the last section is removed, one AddSection command is enough.
// If not last section is removed, two commands are requred: AddSection
// and MoveSection.
const int aLastIndex = theCurve->getNbSections() - 1;
if (theIntParam == aLastIndex) {
setNbUndos(1);
} else {
setNbUndos(2);
}
isOK = addSectionToUndo(theCurve, theIntParam, myPUndo[0]);
if (isOK && theIntParam != aLastIndex) {
isOK = myPUndo[1].init(CurveCreator_Operation::MoveSection,
aLastIndex, theIntParam);
}
}
if (!isOK) {
clear();
}
}
return isOK;
}
//=======================================================================
// function: init
// purpose:
//=======================================================================
bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve,
const CurveCreator_Operation::Type theType,
const int theIntParam1,
const int theIntParam2)
{
bool isOK = false;
if (theCurve != NULL) {
clear();
// Set redo.
myPRedo = new CurveCreator_Operation;
if (myPRedo->init(theType, theIntParam1, theIntParam2)) {
// Construct undo for different commands.
switch (theType) {
case CurveCreator_Operation::SetType:
case CurveCreator_Operation::SetClosed:
isOK = setTypeOrClosedToUndo
(theCurve, theType, theIntParam1, theIntParam2);
break;
case CurveCreator_Operation::MoveSection:
setNbUndos(1);
isOK = myPUndo[0].init(theType, theIntParam2, theIntParam1);
break;
default:
break;
}
}
if (!isOK) {
clear();
}
}
return isOK;
}
//=======================================================================
// function: init
// purpose:
//=======================================================================
bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve,
const CurveCreator_Operation::Type theType,
const std::list<int>& theParams)
{
bool isOK = false;
if (theCurve != NULL || theParams.empty()) {
clear();
// Set redo.
myPRedo = new CurveCreator_Operation;
if (myPRedo->init(theType, theParams)) {
// Construct undo for different commands.
switch (theType) {
case CurveCreator_Operation::Join:
{
int aSectionMain = theParams.front();
const int aNbPointsMain = theCurve->getNbPoints(aSectionMain);
std::list<int> aSectionsToJoin = theParams;
aSectionsToJoin.erase( aSectionsToJoin.begin() );
// it is important to sort the section indices in order to correct perform undo
// for the move sections to the previous positions
aSectionsToJoin.sort();
// 1rst undo for remove points from the main and n-1 undoes to contain joined sections
int aSectionsToJoinNb = aSectionsToJoin.size();
int aNbUndos = 2*aSectionsToJoinNb + 1;
setNbUndos( aNbUndos );
// Add joined sections to undo
std::list<int>::const_iterator anIt = aSectionsToJoin.begin(),
aLast = aSectionsToJoin.end();
anIt = aSectionsToJoin.begin();
int aLastSectionId = -1;
for (int i = 0; anIt != aLast && i < aSectionsToJoinNb; anIt++, i++) {
int anISection = *anIt;
isOK = addSectionToUndo( theCurve, anISection, myPUndo[i*2] );
if (isOK) {
isOK = myPUndo[i*2+1].init(CurveCreator_Operation::MoveSection,
aLastSectionId, anISection);
if (!isOK)
break;
}
}
// Construct undo for RemovePoints command.
if (isOK) {
int aNbPointsInJoined = 0;
anIt = aSectionsToJoin.begin();
for ( ; anIt != aLast; anIt++ )
aNbPointsInJoined += theCurve->getNbPoints( *anIt );
int aJoinedSize = aNbPointsMain + aNbPointsInJoined;
CurveCreator_ICurve::SectionToPointList aSectionToPointList;
for (int anIPoint = aNbPointsMain; anIPoint < aJoinedSize; anIPoint++)
aSectionToPointList.push_back(std::make_pair(aSectionMain, anIPoint));
isOK = myPUndo[aNbUndos-1].init(CurveCreator_Operation::RemovePoints, aSectionToPointList);
}
}
break;
default:
break;
}
}
if (!isOK) {
clear();
}
}
return isOK;
}
//=======================================================================
// function: init
// purpose:
//=======================================================================
bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve,
const CurveCreator_Operation::Type theType,
const std::string& theName,
const CurveCreator::Coordinates &theCoords,
const int theIntParam1,
const int theIntParam2)
{
bool isOK = false;
if (theCurve != NULL) {
clear();
// Set redo.
myPRedo = new CurveCreator_Operation;
if (myPRedo->init(theType, theName, theCoords, theIntParam1, theIntParam2)) {
// Construct undo for different commands.
switch (theType) {
case CurveCreator_Operation::AddSection:
setNbUndos(1);
isOK = myPUndo[0].init(CurveCreator_Operation::RemoveSection, -1);
break;
}
}
}
if( !isOK )
clear();
return isOK;
}
bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve,
const CurveCreator_Operation::Type theType,
const std::string &theName,
const int theIntParam1 )
{
bool isOK = false;
myPRedo = new CurveCreator_Operation;
if (myPRedo->init(theType, theName, theIntParam1 )) {
// Construct undo for different commands.
switch (theType) {
case CurveCreator_Operation::RenameSection:
setNbUndos(1);
isOK = myPUndo[0].init(CurveCreator_Operation::RenameSection,
theCurve->getSectionName(theIntParam1), theIntParam1);
break;
}
}
if( !isOK ){
clear();
}
return isOK;
}
bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve,
const CurveCreator_Operation::Type theType,
const CurveCreator_ICurve::SectionToPointList &theParamList1)
{
bool isOK = false;
if (theCurve != NULL) {
clear();
// Set redo.
myPRedo = new CurveCreator_Operation;
if (myPRedo->init(theType, theParamList1)) {
// Construct undo for different commands.
switch (theType) {
case CurveCreator_Operation::RemovePoints:
{
// Construct undo for RemovePoints command.
CurveCreator_ICurve::SectionToPointCoordsList aSectionToPointCoords;
CurveCreator::Coordinates aPointsToAdd;
const CurveCreator::Dimension aDim = theCurve->getDimension();
CurveCreator_ICurve::SectionToPointList::const_iterator anIt = theParamList1.begin(), aLast = theParamList1.end();
std::list<int> aPoints;
int aSectionId, aPointId;
for ( ; anIt != aLast; anIt++ ) {
aPointsToAdd.clear();
aSectionId = anIt->first;
aPointId = anIt->second;
const CurveCreator::Coordinates &aPoints =
theCurve->getPoints(aSectionId);
CurveCreator::Coordinates::const_iterator anIterBegin =
aPoints.begin() + (aDim*aPointId);
CurveCreator::Coordinates::const_iterator anIterEnd =
anIterBegin + aDim;
aPointsToAdd.insert(aPointsToAdd.end(), anIterBegin, anIterEnd);
aSectionToPointCoords.push_back(std::make_pair(*anIt, aPointsToAdd));
}
setNbUndos(1);
isOK = myPUndo[0].init(CurveCreator_Operation::InsertPoints,
aSectionToPointCoords);
}
break;
default:
break;
}
}
if (!isOK) {
clear();
}
}
return isOK;
}
bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve,
const CurveCreator_Operation::Type theType,
const CurveCreator_ICurve::SectionToPointCoordsList &theParamList1)
{
bool isOK = false;
if (theCurve != NULL) {
clear();
// Set redo.
myPRedo = new CurveCreator_Operation;
if (myPRedo->init(theType, theParamList1)) {
// Construct undo for different commands.
switch (theType) {
case CurveCreator_Operation::InsertPoints:
{
// Construct undo for RemovePoints command.
CurveCreator_ICurve::SectionToPointList aSectionToPointList;
CurveCreator_ICurve::SectionToPointCoordsList::const_iterator anIt = theParamList1.begin(), aLast = theParamList1.end();
for ( ; anIt != aLast; anIt++ ) {
aSectionToPointList.push_back(anIt->first);
}
setNbUndos(1);
isOK = myPUndo[0].init(CurveCreator_Operation::RemovePoints,
aSectionToPointList);
}
break;
case CurveCreator_Operation::SetCoordinates:
{
// Construct undo for SetCoordinates command.
CurveCreator_ICurve::SectionToPointCoordsList aSectionToPointOldCoords;
CurveCreator_ICurve::SectionToPointCoordsList::const_iterator anIt = theParamList1.begin(), aLast = theParamList1.end();
for ( ; anIt != aLast; anIt++ ) {
CurveCreator::Coordinates anOldCoords = theCurve->getPoint(anIt->first.first, anIt->first.second);
aSectionToPointOldCoords.push_back(std::make_pair(anIt->first, anOldCoords));
}
setNbUndos(1);
isOK = myPUndo[0].init(CurveCreator_Operation::SetCoordinates,
aSectionToPointOldCoords);
}
break;
default:
break;
}
}
if (!isOK) {
clear();
}
}
return isOK;
}
bool CurveCreator_Diff::init(const CurveCreator_Curve *theCurve,
const CurveCreator_ICurve::SectionToPointCoordsList &theOldParamList)
{
bool isOK = false;
if (theCurve != NULL && theOldParamList.size() > 0) {
clear();
// Set redo.
myPRedo = new CurveCreator_Operation;
// Construct redo for SetCoordinates command.
CurveCreator_ICurve::SectionToPointCoordsList aSectionToPointActualCoords;
CurveCreator_ICurve::SectionToPointCoordsList::const_iterator anIt =
theOldParamList.begin(), aLast = theOldParamList.end();
for ( ; anIt != aLast; anIt++ ) {
CurveCreator::Coordinates anActualCoords = theCurve->getPoint(anIt->first.first, anIt->first.second);
aSectionToPointActualCoords.push_back(std::make_pair(anIt->first, anActualCoords));
}
if (myPRedo->init(CurveCreator_Operation::SetCoordinates, aSectionToPointActualCoords)) {
// Undo for SetCoordinates command.
setNbUndos(1);
isOK = myPUndo[0].init(CurveCreator_Operation::SetCoordinates,
theOldParamList);
}
if (!isOK) {
clear();
}
}
return isOK;
}
//=======================================================================
// function: applyUndo
// purpose:
//=======================================================================
void CurveCreator_Diff::applyUndo(CurveCreator_Curve *theCurve)
{
if (myNbUndos > 0 && myPUndo != NULL) {
for (int i = 0; i < myNbUndos; i++) {
myPUndo[i].apply(theCurve);
}
}
}
//=======================================================================
// function: applyRedo
// purpose:
//=======================================================================
void CurveCreator_Diff::applyRedo(CurveCreator_Curve *theCurve)
{
if (myPRedo != NULL) {
myPRedo->apply(theCurve);
}
}
//=======================================================================
// function: clear
// purpose:
//=======================================================================
void CurveCreator_Diff::clear()
{
if (myPUndo != NULL) {
delete [] myPUndo;
myPUndo = NULL;
}
myNbUndos = 0;
if (myPRedo != NULL) {
delete myPRedo;
myPRedo = NULL;
}
}
//=======================================================================
// function: setNbUndos
// purpose:
//=======================================================================
void CurveCreator_Diff::setNbUndos(const int theNbUndos)
{
myNbUndos = theNbUndos;
myPUndo = new CurveCreator_Operation[myNbUndos];
}
//=======================================================================
// function: getSectionIndex
// purpose:
//=======================================================================
int CurveCreator_Diff::getSectionIndex(const CurveCreator_Curve *theCurve,
const int theIndex) const
{
return (theIndex == -1 ? theCurve->getNbSections() - 1 : theIndex);
}
//=======================================================================
// function: addSectionToUndo
// purpose:
//=======================================================================
bool CurveCreator_Diff::addSectionToUndo
(const CurveCreator_Curve *theCurve,
const int theIndex,
CurveCreator_Operation &theOperation) const
{
const std::string aName = theCurve->getSectionName(theIndex);
const CurveCreator::Coordinates &aPnts = theCurve->getPoints(theIndex);
const CurveCreator::SectionType aType = theCurve->getSectionType(theIndex);
const bool isClosed = theCurve->isClosed(theIndex);
bool isOK = theOperation.init(CurveCreator_Operation::AddSection,
aName, aPnts, aType, isClosed);
return isOK;
}
//=======================================================================
// function: setTypeOrClosedToUndo
// purpose:
//=======================================================================
bool CurveCreator_Diff::setTypeOrClosedToUndo
(const CurveCreator_Curve *theCurve,
const CurveCreator_Operation::Type theType,
const int theIntParam1,
const int theIntParam2)
{
bool isOK = true;
// Compute number of modified sections.
const bool isSetType = (theType == CurveCreator_Operation::SetType);
int aNbModif = 0;
std::list<int> aListOfInd;
int aValue;
int i;
if (theIntParam2 == -1) {
// The operation is applied to all sections. We need to collect
// really modified sections for undo.
const int aNbSections = theCurve->getNbSections();
if (aNbSections > 0) {
// Get sections to be modified.
for (i = 0; i < aNbSections; i++) {
if (isSetType) {
aValue = theCurve->getSectionType(i);
} else {
aValue = theCurve->isClosed(i);
}
if (theIntParam1 != aValue) {
aNbModif++;
aListOfInd.push_back(i);
}
}
if (aNbSections == aNbModif) {
// All sections are modified. We can use one single command
// with -1 section index.
aNbModif = 1;
aListOfInd.clear();
aListOfInd.push_back(-1);
}
}
} else {
// There is only particular section modified.
// Check if there is a real modification required.
if (isSetType) {
aValue = theCurve->getSectionType(theIntParam2);
} else {
aValue = theCurve->isClosed(theIntParam2);
}
if (theIntParam1 != aValue) {
aNbModif = 1;
aListOfInd.push_back(theIntParam2);
}
}
if (aNbModif > 0) {
// Store the undos
std::list<int>::iterator anIter = aListOfInd.begin();
if (isSetType) {
aValue = theCurve->getSectionType(*anIter);
} else {
aValue = theCurve->isClosed(*anIter);
}
setNbUndos(aNbModif);
for (i = 0; anIter != aListOfInd.end() && isOK; i++, anIter++) {
isOK = myPUndo[i].init(theType, aValue, *anIter);
}
}
return isOK;
}