1 // Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // File : SALOMEDSImpl_AttributeTableOfReal.cxx
24 // Author : Michael Ponikarov
27 #include "SALOMEDSImpl_AttributeTableOfReal.hxx"
32 #define SEPARATOR '\1'
33 typedef std::map<int, double>::const_iterator MI;
35 static std::string getUnit(const std::string& theString)
37 std::string aString(theString);
38 int aPos = aString.find(SEPARATOR);
39 return aPos < 0 || aPos == aString.size()-1 ? std::string() : aString.substr(aPos+1, aString.size());
42 static std::string getTitle(const std::string& theString)
44 std::string aString(theString);
45 int aPos = aString.find(SEPARATOR);
46 return aPos < 0 ? aString :aString.substr(0, aPos);
49 const std::string& SALOMEDSImpl_AttributeTableOfReal::GetID()
51 static std::string SALOMEDSImpl_AttributeTableOfRealID ("128371A1-8F52-11d6-A8A3-0001021E8C7F");
52 return SALOMEDSImpl_AttributeTableOfRealID;
55 SALOMEDSImpl_AttributeTableOfReal* SALOMEDSImpl_AttributeTableOfReal::Set(const DF_Label& label)
57 SALOMEDSImpl_AttributeTableOfReal* A = NULL;
58 if (!(A=(SALOMEDSImpl_AttributeTableOfReal*)label.FindAttribute(SALOMEDSImpl_AttributeTableOfReal::GetID()))) {
59 A = new SALOMEDSImpl_AttributeTableOfReal();
60 label.AddAttribute(A);
65 SALOMEDSImpl_AttributeTableOfReal::SALOMEDSImpl_AttributeTableOfReal()
66 :SALOMEDSImpl_GenericAttribute("AttributeTableOfReal")
72 void SALOMEDSImpl_AttributeTableOfReal::SetNbColumns(const int theNbColumns)
77 std::map<int, double> aMap;
81 for(MI p = aMap.begin(); p != aMap.end(); p++) {
82 int aRow = (int)(p->first/myNbColumns) + 1;
83 int aCol = (int)(p->first - myNbColumns*(aRow-1));
84 if(aCol == 0) { aCol = myNbColumns; aRow--; }
85 if(aCol > theNbColumns) continue;
86 int aKey = (aRow-1)*theNbColumns+aCol;
87 myTable[aKey] = p->second;
90 myNbColumns = theNbColumns;
92 while (myCols.size() < myNbColumns) { // append empty columns titles
93 myCols.push_back(std::string(""));
96 SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved
99 void SALOMEDSImpl_AttributeTableOfReal::SetTitle(const std::string& theTitle)
105 SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved
108 std::string SALOMEDSImpl_AttributeTableOfReal::GetTitle() const
113 void SALOMEDSImpl_AttributeTableOfReal::SetRowData(const int theRow,
114 const std::vector<double>& theData)
117 if(theData.size() > myNbColumns) SetNbColumns(theData.size());
121 while (myRows.size() < theRow) { // append new row titles
122 myRows.push_back(std::string(""));
125 int i, aShift = (theRow-1)*myNbColumns, aLength = theData.size();
126 for(i = 1; i <= aLength; i++) {
127 myTable[aShift + i] = theData[i-1];
130 if(theRow > myNbRows) myNbRows = theRow;
132 SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved
135 std::vector<double> SALOMEDSImpl_AttributeTableOfReal::GetRowData(const int theRow)
137 std::vector<double> aSeq;
138 int i, aShift = (theRow-1)*myNbColumns;
139 for(i = 1; i <= myNbColumns; i++) {
140 if(myTable.find(aShift+i) != myTable.end())
141 aSeq.push_back(myTable[aShift+i]);
149 void SALOMEDSImpl_AttributeTableOfReal::SetRowTitle(const int theRow,
150 const std::string& theTitle)
154 std::string aTitle(theTitle), aUnit = GetRowUnit(theRow);
159 myRows[theRow-1] = aTitle;
161 SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved
164 void SALOMEDSImpl_AttributeTableOfReal::SetRowUnit(const int theRow,
165 const std::string& theUnit)
169 std::string aTitle = GetRowTitle(theRow);
173 myRows[theRow-1] = aTitle;
175 SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved
178 void SALOMEDSImpl_AttributeTableOfReal::SetRowUnits(const std::vector<std::string>& theUnits)
180 if (theUnits.size() != GetNbRows()) throw DFexception("Invalid number of rows");
181 int aLength = theUnits.size(), i;
182 for(i = 1; i <= aLength; i++) SetRowUnit(i, theUnits[i-1]);
184 SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved
187 std::vector<std::string> SALOMEDSImpl_AttributeTableOfReal::GetRowUnits()
189 std::vector<std::string> aSeq;
190 int aLength = myRows.size(), i;
191 for(i=0; i<aLength; i++) aSeq.push_back(getUnit(myRows[i]));
195 void SALOMEDSImpl_AttributeTableOfReal::SetRowTitles(const std::vector<std::string>& theTitles)
197 if (theTitles.size() != GetNbRows()) throw DFexception("Invalid number of rows");
198 int aLength = theTitles.size(), i;
199 for(i = 1; i <= aLength; i++) SetRowTitle(i, theTitles[i-1]);
201 SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved
204 std::vector<std::string> SALOMEDSImpl_AttributeTableOfReal::GetRowTitles()
206 std::vector<std::string> aSeq;
207 int aLength = myRows.size(), i;
208 for(i=0; i<aLength; i++) aSeq.push_back(getTitle(myRows[i]));
212 std::string SALOMEDSImpl_AttributeTableOfReal::GetRowTitle(const int theRow) const
214 return getTitle(myRows[theRow-1]);
218 std::string SALOMEDSImpl_AttributeTableOfReal::GetRowUnit(const int theRow) const
220 return getUnit(myRows[theRow-1]);
223 void SALOMEDSImpl_AttributeTableOfReal::SetColumnData(const int theColumn,
224 const std::vector<double>& theData)
227 if(theColumn > myNbColumns) SetNbColumns(theColumn);
231 int i, aLength = theData.size();
232 for(i = 1; i <= aLength; i++) {
233 myTable[myNbColumns*(i-1)+theColumn] = theData[i-1];
236 if(aLength > myNbRows) {
238 while (myRows.size() < myNbRows) { // append empty row titles
239 myRows.push_back(std::string(""));
243 SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved
246 std::vector<double> SALOMEDSImpl_AttributeTableOfReal::GetColumnData(const int theColumn)
248 std::vector<double> aSeq;
251 for(i = 1; i <= myNbRows; i++) {
252 anIndex = myNbColumns*(i-1) + theColumn;
253 if(myTable.find(anIndex) != myTable.end())
254 aSeq.push_back(myTable[anIndex]);
262 void SALOMEDSImpl_AttributeTableOfReal::SetColumnTitle(const int theColumn,
263 const std::string& theTitle)
267 while(myCols.size() < theColumn) myCols.push_back(std::string(""));
268 myCols[theColumn-1] = theTitle;
270 SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved
273 std::string SALOMEDSImpl_AttributeTableOfReal::GetColumnTitle(const int theColumn) const
275 if(myCols.empty()) return "";
276 if(myCols.size() < theColumn) return "";
277 return myCols[theColumn-1];
280 void SALOMEDSImpl_AttributeTableOfReal::SetColumnTitles(const std::vector<std::string>& theTitles)
282 if (theTitles.size() != myNbColumns) throw DFexception("Invalid number of columns");
283 int aLength = theTitles.size(), i;
284 for(i = 0; i < aLength; i++) myCols[i] = theTitles[i];
286 SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved
289 std::vector<std::string> SALOMEDSImpl_AttributeTableOfReal::GetColumnTitles()
291 std::vector<std::string> aSeq;
292 int aLength = myCols.size(), i;
293 for(i=0; i<aLength; i++) aSeq.push_back(myCols[i]);
297 int SALOMEDSImpl_AttributeTableOfReal::GetNbRows() const
302 int SALOMEDSImpl_AttributeTableOfReal::GetNbColumns() const
307 void SALOMEDSImpl_AttributeTableOfReal::PutValue(const double& theValue,
313 if(theColumn > myNbColumns) SetNbColumns(theColumn);
315 int anIndex = (theRow-1)*myNbColumns + theColumn;
316 myTable[anIndex] = theValue;
318 if(theRow > myNbRows) {
319 while (myRows.size() < theRow) { // append empty row titles
320 myRows.push_back(std::string(""));
325 SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved
328 bool SALOMEDSImpl_AttributeTableOfReal::HasValue(const int theRow,
331 if(theRow > myNbRows || theRow < 1) return false;
332 if(theColumn > myNbColumns || theColumn < 1) return false;
333 int anIndex = (theRow-1)*myNbColumns + theColumn;
334 return (myTable.find(anIndex) != myTable.end());
337 double SALOMEDSImpl_AttributeTableOfReal::GetValue(const int theRow,
340 if(theRow > myNbRows || theRow < 1) throw DFexception("Invalid cell index");
341 if(theColumn > myNbColumns || theColumn < 1) throw DFexception("Invalid cell index");
343 int anIndex = (theRow-1)*myNbColumns + theColumn;
344 if(myTable.find(anIndex) != myTable.end()) return myTable[anIndex];
346 throw DFexception("Invalid cell index");
350 void SALOMEDSImpl_AttributeTableOfReal::RemoveValue(const int theRow, const int theColumn)
353 if(theRow > myNbRows || theRow < 1) throw DFexception("Invalid cell index");
354 if(theColumn > myNbColumns || theColumn < 1) throw DFexception("Invalid cell index");
356 int anIndex = (theRow-1)*myNbColumns + theColumn;
357 if (myTable.find(anIndex) != myTable.end()) {
359 myTable.erase(anIndex);
360 SetModifyFlag(); // table is modified
364 const std::string& SALOMEDSImpl_AttributeTableOfReal::ID() const
369 void SALOMEDSImpl_AttributeTableOfReal::Restore(DF_Attribute* with)
372 SALOMEDSImpl_AttributeTableOfReal* aTable = dynamic_cast<SALOMEDSImpl_AttributeTableOfReal*>(with);
373 if(!aTable) throw DFexception("Can't Restore from a null attribute");
379 myTable = aTable->myTable;
380 myNbRows = aTable->myNbRows;
381 myNbColumns = aTable->myNbColumns;
382 myTitle = aTable->myTitle;
384 for(anIndex = 1; anIndex <= aTable->GetNbRows();anIndex++)
385 myRows.push_back(aTable->GetRowTitle(anIndex));
387 for(anIndex = 1; anIndex <= aTable->GetNbColumns(); anIndex++)
388 myCols.push_back(aTable->GetColumnTitle(anIndex));
391 DF_Attribute* SALOMEDSImpl_AttributeTableOfReal::NewEmpty() const
393 return new SALOMEDSImpl_AttributeTableOfReal();
396 void SALOMEDSImpl_AttributeTableOfReal::Paste(DF_Attribute* into)
399 SALOMEDSImpl_AttributeTableOfReal* aTable = dynamic_cast<SALOMEDSImpl_AttributeTableOfReal*>(into);
400 if(!aTable) throw DFexception("Can't Paste into a null attribute");
402 aTable->myTable.clear();
403 aTable->myCols.clear();
404 aTable->myRows.clear();
406 aTable->myTable = myTable;
407 aTable->myTitle = myTitle;
408 aTable->myNbRows = myNbRows;
409 aTable->myNbColumns = myNbColumns;
411 for(anIndex = 1; anIndex <= GetNbRows();anIndex++)
412 aTable->myRows.push_back(GetRowTitle(anIndex));
413 for(anIndex = 1; anIndex <= GetNbColumns(); anIndex++)
414 aTable->myCols.push_back(GetColumnTitle(anIndex));
417 std::vector<int> SALOMEDSImpl_AttributeTableOfReal::GetSetRowIndices(const int theRow)
419 std::vector<int> aSeq;
421 int i, aShift = myNbColumns*(theRow-1);
422 for(i = 1; i <= myNbColumns; i++) {
423 if(myTable.find(aShift + i) != myTable.end()) aSeq.push_back(i);
429 std::vector<int> SALOMEDSImpl_AttributeTableOfReal::GetSetColumnIndices(const int theColumn)
431 std::vector<int> aSeq;
434 for(i = 1; i <= myNbRows; i++) {
435 anIndex = myNbColumns*(i-1)+theColumn;
436 if(myTable.find(anIndex) != myTable.end()) aSeq.push_back(i);
442 std::string SALOMEDSImpl_AttributeTableOfReal::Save()
445 char* buffer = new char[1024];
450 sprintf(buffer, "%d\n", l);
453 aString += myTitle[i];
458 sprintf(buffer, "%d\n", myNbRows);
462 for(i=0; i<myNbRows; i++) {
463 l = myRows[i].size();
464 sprintf(buffer, "%d\n", l);
467 aString += myRows[i][j];
473 sprintf(buffer, "%d\n", myNbColumns);
477 for(i=0; i<myNbColumns; i++) {
478 l = myCols[i].size();
479 sprintf(buffer, "%d\n", l);
482 aString += myCols[i][j];
487 //Store the table values
489 sprintf(buffer, "%d\n", l);
491 for(MI p = myTable.begin(); p != myTable.end(); p++) {
492 sprintf(buffer, "%d\n%.64e\n", p->first, p->second);
500 void SALOMEDSImpl_AttributeTableOfReal::Load(const std::string& value)
502 std::vector<std::string> v;
503 int i, j, l, pos, aSize = (int)value.size();
504 for(i = 0, pos = 0; i<aSize; i++) {
505 if(value[i] == '\n') {
506 v.push_back(value.substr(pos, i-pos));
517 l = strtol(v[pos++].c_str(), NULL, 10);
519 myTitle = std::string(l, 0);
521 myTitle[i] = v[pos++][0];
525 myNbRows = strtol(v[pos++].c_str(), NULL, 10);
529 for(i=1; i<=myNbRows; i++) {
530 l = strtol(v[pos++].c_str(), NULL, 10);
531 aStr = std::string(l,0);
533 aStr[j] = v[pos++][0];
535 myRows.push_back(aStr);
539 myNbColumns = strtol(v[pos++].c_str(), NULL, 10);
543 for(i=1; i<=myNbColumns; i++) {
544 l = strtol(v[pos++].c_str(), NULL, 10);
545 aStr = std::string(l,0);
547 aStr[j] = v[pos++][0];
549 myCols.push_back(aStr);
552 //Restore the table values
553 l = strtol(v[pos++].c_str(), NULL, 10);
555 for(i=1; i<=l; i++) {
556 int aKey = strtol(v[pos++].c_str(), NULL, 10);
557 double aValue = strtod(v[pos++].c_str(), NULL);
558 myTable[aKey] = aValue;
563 std::vector<int> SALOMEDSImpl_AttributeTableOfReal::SortRow(const int theRow, SortOrder sortOrder, SortPolicy sortPolicy )
566 std::vector<int> result;
567 if ( theRow > 0 && theRow <= myNbRows ) {
568 std::vector<int> indices( myNbColumns );
570 for ( int i = 0; i < myNbColumns; i++ ) {
571 if ( sortPolicy != EmptyIgnore || HasValue(theRow, i+1) ) {
572 indices[cnt++] = i+1;
577 TableSorter<SALOMEDSImpl_AttributeTableOfReal> sorter( this, sortOrder, sortPolicy, theRow, true );
578 std::stable_sort( indices.begin(), indices.end(), sorter );
580 if ( sortPolicy == EmptyIgnore ) {
581 std::vector<int> other( myNbColumns );
583 for( int i = 0; i < myNbColumns; i++ )
584 other[i] = HasValue(theRow, i+1) ? indices[cnt++] : i+1;
589 for ( int col = 0; col < indices.size(); col++ ) {
590 int idx = indices[col];
591 if ( col+1 == idx ) continue;
592 SwapCells(theRow, col+1, theRow, idx);
594 for ( int i = col+1; i < indices.size() && idx1 == 0; i++)
595 if ( indices[i] == col+1 ) idx1 = i;
598 // no need for SetModifyFlag(), since it is done by SwapCells()
603 std::vector<int> SALOMEDSImpl_AttributeTableOfReal::SortColumn(const int theColumn, SortOrder sortOrder, SortPolicy sortPolicy )
606 std::vector<int> result;
607 if ( theColumn > 0 && theColumn <= myNbColumns ) {
608 std::vector<int> indices( myNbRows );
610 for ( int i = 0; i < myNbRows; i++ ) {
611 if ( sortPolicy != EmptyIgnore || HasValue(i+1, theColumn) ) {
612 indices[cnt++] = i+1;
617 TableSorter<SALOMEDSImpl_AttributeTableOfReal> sorter( this, sortOrder, sortPolicy, theColumn, false );
618 std::stable_sort( indices.begin(), indices.end(), sorter );
620 if ( sortPolicy == EmptyIgnore ) {
621 std::vector<int> other( myNbRows );
623 for( int i = 0; i < myNbRows; i++ )
624 other[i] = HasValue(i+1, theColumn) ? indices[cnt++] : i+1;
629 for ( int row = 0; row < indices.size(); row++ ) {
630 int idx = indices[row];
631 if ( row+1 == idx ) continue;
632 SwapCells(row+1, theColumn, idx, theColumn);
634 for ( int i = row+1; i < indices.size() && idx1 == 0; i++)
635 if ( indices[i] == row+1 ) idx1 = i;
638 // no need for SetModifyFlag(), since it is done by SwapCells()
643 std::vector<int> SALOMEDSImpl_AttributeTableOfReal::SortByRow(const int theRow, SortOrder sortOrder, SortPolicy sortPolicy )
646 std::vector<int> result;
647 if ( theRow > 0 && theRow <= myNbRows ) {
648 std::vector<int> indices( myNbColumns );
650 for ( int i = 0; i < myNbColumns; i++ ) {
651 if ( sortPolicy != EmptyIgnore || HasValue(theRow, i+1) ) {
652 indices[cnt++] = i+1;
657 TableSorter<SALOMEDSImpl_AttributeTableOfReal> sorter( this, sortOrder, sortPolicy, theRow, true );
658 std::stable_sort( indices.begin(), indices.end(), sorter );
660 if ( sortPolicy == EmptyIgnore ) {
661 std::vector<int> other( myNbColumns );
663 for( int i = 0; i < myNbColumns; i++ )
664 other[i] = HasValue(theRow, i+1) ? indices[cnt++] : i+1;
669 for ( int col = 0; col < indices.size(); col++ ) {
670 int idx = indices[col];
671 if ( col+1 == idx ) continue;
672 SwapColumns(col+1, idx);
674 for ( int i = col+1; i < indices.size() && idx1 == 0; i++)
675 if ( indices[i] == col+1 ) idx1 = i;
678 // no need for SetModifyFlag(), since it is done by SwapColumns()
683 std::vector<int> SALOMEDSImpl_AttributeTableOfReal::SortByColumn(const int theColumn, SortOrder sortOrder, SortPolicy sortPolicy )
686 std::vector<int> result;
687 if ( theColumn > 0 && theColumn <= myNbColumns ) {
688 std::vector<int> indices( myNbRows );
690 for ( int i = 0; i < myNbRows; i++ ) {
691 if ( sortPolicy != EmptyIgnore || HasValue(i+1, theColumn) ) {
692 indices[cnt++] = i+1;
697 TableSorter<SALOMEDSImpl_AttributeTableOfReal> sorter( this, sortOrder, sortPolicy, theColumn, false );
698 std::stable_sort( indices.begin(), indices.end(), sorter );
700 if ( sortPolicy == EmptyIgnore ) {
701 std::vector<int> other( myNbRows );
703 for( int i = 0; i < myNbRows; i++ )
704 other[i] = HasValue(i+1, theColumn) ? indices[cnt++] : i+1;
709 for ( int row = 0; row < indices.size(); row++ ) {
710 int idx = indices[row];
711 if ( row+1 == idx ) continue;
712 SwapRows(row+1, idx);
714 for ( int i = row+1; i < indices.size() && idx1 == 0; i++)
715 if ( indices[i] == row+1 ) idx1 = i;
718 // no need for SetModifyFlag(), since it is done by SwapRows()
723 void SALOMEDSImpl_AttributeTableOfReal::SwapCells(const int theRow1, const int theColumn1,
724 const int theRow2, const int theColumn2)
727 if (theRow1 > myNbRows || theRow1 < 1) throw DFexception("Invalid cell index");
728 if (theRow2 > myNbRows || theRow2 < 1) throw DFexception("Invalid cell index");
729 if (theColumn1 > myNbColumns || theColumn1 < 1) throw DFexception("Invalid cell index");
730 if (theColumn2 > myNbColumns || theColumn2 < 1) throw DFexception("Invalid cell index");
732 int anIndex1 = (theRow1-1)*myNbColumns + theColumn1;
733 int anIndex2 = (theRow2-1)*myNbColumns + theColumn2;
735 bool hasValue1 = myTable.find(anIndex1) != myTable.end();
736 bool hasValue2 = myTable.find(anIndex2) != myTable.end();
738 if (!hasValue1 && !hasValue2) return; // nothing changed
740 double value1 = hasValue1 ? myTable[anIndex1] : 0;
741 double value2 = hasValue2 ? myTable[anIndex2] : 0;
743 if (hasValue1 && hasValue2 && value1 == value2) return; // nothing changed
745 if (hasValue1) myTable[anIndex2] = value1;
746 else myTable.erase(anIndex2);
747 if (hasValue2) myTable[anIndex1] = value2;
748 else myTable.erase(anIndex1);
750 SetModifyFlag(); // table is modified
753 void SALOMEDSImpl_AttributeTableOfReal::SwapRows(const int theRow1, const int theRow2)
756 for (int i = 1; i <= myNbColumns; i++)
757 SwapCells(theRow1, i, theRow2, i);
759 std::string tmp = myRows[theRow1-1];
760 myRows[theRow1-1] = myRows[theRow2-1];
761 myRows[theRow2-1] = tmp;
762 // no need for SetModifyFlag(), since it is done by SwapCells()
765 void SALOMEDSImpl_AttributeTableOfReal::SwapColumns(const int theColumn1, const int theColumn2)
768 for (int i = 1; i <= myNbRows; i++)
769 SwapCells(i, theColumn1, i, theColumn2);
770 // swap column titles
771 std::string tmp = myCols[theColumn1-1];
772 myCols[theColumn1-1] = myCols[theColumn2-1];
773 myCols[theColumn2-1] = tmp;
774 // no need for SetModifyFlag(), since it is done by SwapCells()