From: jfa Date: Fri, 8 Oct 2021 15:10:09 +0000 (+0300) Subject: bos #26449: SHAPER: save imported images X-Git-Tag: V9_9_0a1~23^2 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=54c444b74ff9a608c7ddfdf9310dde0b0e7c90d6;p=modules%2Fshaper.git bos #26449: SHAPER: save imported images * Imported image is stored as a binary attribute within an Import feature * Images are dumped to the same directory as a Python script (however, the full path to file is dumped) --- diff --git a/src/ConnectorPlugin/ConnectorPlugin_ExportFeature.py b/src/ConnectorPlugin/ConnectorPlugin_ExportFeature.py index 3a714b066..da88d6c2a 100644 --- a/src/ConnectorPlugin/ConnectorPlugin_ExportFeature.py +++ b/src/ConnectorPlugin/ConnectorPlugin_ExportFeature.py @@ -68,8 +68,8 @@ class ExportFeature(ModelAPI.ModelAPI_Feature): for aResIndex in range(self.Part.size(aResultType)): anObject = self.Part.object(aResultType, aResIndex) aResult = model.objectToResult(anObject) - # do nt export picture - if aResult.hasTextureFile() is True: + # do not export picture + if aResult.hasTexture() is True: continue if not aResult is None: if (not aResult.shape() or aResult.shape().isNull()) and isPart: diff --git a/src/ConnectorPlugin/ConnectorPlugin_PublishToStudyFeature.py b/src/ConnectorPlugin/ConnectorPlugin_PublishToStudyFeature.py index 8da67a31e..a721ad73b 100644 --- a/src/ConnectorPlugin/ConnectorPlugin_PublishToStudyFeature.py +++ b/src/ConnectorPlugin/ConnectorPlugin_PublishToStudyFeature.py @@ -93,7 +93,7 @@ class PublishToStudyFeature(ModelAPI.ModelAPI_Feature): aResObject = aPartDoc.object(model.ModelAPI_ResultBody_group(), aResId) aRes = model.objectToResult(aResObject) #do not export images - if aRes.hasTextureFile() is True: + if aRes.hasTexture() is True: continue aResFeatureId = str(aPartDoc.feature(aRes).data().featureId()) if aResFeatureId in aFeaturesIndices: diff --git a/src/ExchangeAPI/CMakeLists.txt b/src/ExchangeAPI/CMakeLists.txt index d241e7fcb..33ac73255 100644 --- a/src/ExchangeAPI/CMakeLists.txt +++ b/src/ExchangeAPI/CMakeLists.txt @@ -18,6 +18,7 @@ # INCLUDE(Common) +INCLUDE(UseQtExt) SET(PROJECT_HEADERS ExchangeAPI.h @@ -34,6 +35,7 @@ SET(PROJECT_LIBRARIES ModelAPI ModelHighAPI GeomAlgoAPI + ${QT_LIBRARIES} ) INCLUDE_DIRECTORIES( @@ -41,6 +43,7 @@ INCLUDE_DIRECTORIES( ${PROJECT_SOURCE_DIR}/src/ModelAPI ${PROJECT_SOURCE_DIR}/src/ModelHighAPI ${PROJECT_SOURCE_DIR}/src/GeomAlgoAPI + ${QT_INCLUDES} ) # Plugin headers dependency @@ -51,6 +54,9 @@ INCLUDE_DIRECTORIES( ${PROJECT_SOURCE_DIR}/src/ExchangePlugin ) +# additional preprocessor / compiler flags +ADD_DEFINITIONS(${QT_DEFINITIONS}) + #TODO(spo): is ${OpenCASCADE_DEFINITIONS} necessary? ADD_DEFINITIONS(-DEXCHANGEAPI_EXPORTS ${OpenCASCADE_DEFINITIONS}) ADD_LIBRARY(ExchangeAPI SHARED ${PROJECT_SOURCES} ${PROJECT_HEADERS}) diff --git a/src/ExchangeAPI/ExchangeAPI_Import.cpp b/src/ExchangeAPI/ExchangeAPI_Import.cpp index cee25a91a..eae652434 100644 --- a/src/ExchangeAPI/ExchangeAPI_Import.cpp +++ b/src/ExchangeAPI/ExchangeAPI_Import.cpp @@ -26,11 +26,17 @@ #include //-------------------------------------------------------------------------------------- #include +#include #include #include #include //-------------------------------------------------------------------------------------- #include +//-------------------------------------------------------------------------------------- +#include +#include +#include +#include ExchangeAPI_Import::ExchangeAPI_Import( const std::shared_ptr & theFeature) @@ -245,7 +251,44 @@ void ExchangeAPI_Import_Image::dump(ModelHighAPI_Dumper& theDumper) const std::string aPartName = theDumper.name(aBase->document()); std::string aFilePath = - aBase->string(ExchangePlugin_Import_ImageFeature::FILE_PATH_ID())->value(); + aBase->string(ExchangePlugin_Import_ImageFeature::FILE_PATH_ID())->value(); + + // store image into a new file near the dumped python script + ResultPtr aResult = aBase->firstResult(); + std::string aNewImageDir = theDumper.getDumpDir(); + if (aResult.get() && aResult->hasTexture()) { + // get image data + int aWidth, aHeight; + std::string aFormat; + std::list aByteList; + AttributeImagePtr anImageAttr = + aResult->data()->image(ModelAPI_ResultBody::IMAGE_ID()); + anImageAttr->texture(aWidth, aHeight, aByteList, aFormat); + + // convert image data to QPixmap + uchar* arr = new uchar[aByteList.size()]; + std::copy(aByteList.begin(), aByteList.end(), arr); + QImage image (arr, aWidth, aHeight, QImage::Format_ARGB32); + QPixmap pixmap = QPixmap::fromImage( image ); + + // get new file name + std::wstring aName = aBase->name(); + std::string anImageName (aName.begin(), aName.end()); + std::string aNewImageFile = anImageName + "." + aFormat; + QFileInfo aNewFileInfo (QDir(aNewImageDir.c_str()), aNewImageFile.c_str()); + for (int ii = 1; QFile::exists(aNewFileInfo.absoluteFilePath()); ii++) { + // construct the new file name by adding the unique number + aNewImageFile = anImageName + "_" + std::to_string(ii) + "." + aFormat; + aNewFileInfo.setFile(QDir(aNewImageDir.c_str()), aNewImageFile.c_str()); + } + + // write image to a new file + if (pixmap.save(aNewFileInfo.absoluteFilePath())) { + // to dump new file name + aFilePath = aNewFileInfo.absoluteFilePath().toStdString(); + } + delete [] arr; + } theDumper << aBase << " = model.addImportImage(" << aPartName << ", \"" << aFilePath << "\")" << std::endl; diff --git a/src/ExchangePlugin/CMakeLists.txt b/src/ExchangePlugin/CMakeLists.txt index 7efb757ff..9ffa2d408 100755 --- a/src/ExchangePlugin/CMakeLists.txt +++ b/src/ExchangePlugin/CMakeLists.txt @@ -19,6 +19,7 @@ INCLUDE(Common) INCLUDE(UnitTest) +INCLUDE(UseQtExt) INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/src/Events ${PROJECT_SOURCE_DIR}/src/Config @@ -32,8 +33,12 @@ INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/src/Events ${PROJECT_SOURCE_DIR}/src/ConstructionPlugin ${PROJECT_SOURCE_DIR}/src/PartSetPlugin ${OpenCASCADE_INCLUDE_DIR} + ${QT_INCLUDES} ) +# additional preprocessor / compiler flags +ADD_DEFINITIONS(${QT_DEFINITIONS}) + SET(PROJECT_HEADERS ExchangePlugin.h ExchangePlugin_Plugin.h @@ -82,6 +87,7 @@ SET(PROJECT_LIBRARIES GeomAlgoAPI GeomValidators XAOShaper + ${QT_LIBRARIES} ) # default dump approaches (will be set if not initialized) diff --git a/src/ExchangePlugin/ExchangePlugin_Dump.cpp b/src/ExchangePlugin/ExchangePlugin_Dump.cpp index 418ab1370..b65b28970 100644 --- a/src/ExchangePlugin/ExchangePlugin_Dump.cpp +++ b/src/ExchangePlugin/ExchangePlugin_Dump.cpp @@ -24,11 +24,14 @@ #include #include #include +#include #include #include +#include + #ifdef EXCHANGEPLUGIN_DUMP_NAMING static const bool THE_DUMP_NAMING = true; #else @@ -67,11 +70,15 @@ void ExchangePlugin_Dump::initAttributes() data()->addAttribute(EXPORT_VARIABLES_ID(), ModelAPI_AttributeBoolean::typeId()); + data()->addAttribute(DUMP_DIR_ID(), ModelAPI_AttributeString::typeId()); + // default values boolean(TOPOLOGICAL_NAMING_DUMP_ID())->setValue(THE_DUMP_NAMING); boolean(GEOMETRIC_DUMP_ID())->setValue(THE_DUMP_GEO); boolean(WEAK_NAMING_DUMP_ID())->setValue(THE_DUMP_WEAK); boolean(EXPORT_VARIABLES_ID())->setValue(false); + + ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), DUMP_DIR_ID()); } void ExchangePlugin_Dump::execute() @@ -162,6 +169,14 @@ void ExchangePlugin_Dump::dump(const std::string& theFileName) aDumper->addCustomStorage(aWeakNamingStorage); } + // pass dump directory to the dumper + AttributeStringPtr aDumpDirAttr = + this->string(ExchangePlugin_Dump::DUMP_DIR_ID()); + std::string aDumpDir; + if (aDumpDirAttr.get() && !aDumpDirAttr->isInitialized()) + aDumpDir = GeomAlgoAPI_Tools::File_Tools::path(theFileName); + aDumper->setDumpDir(aDumpDir); + if (!aDumper->process(aDoc, theFileName)) { setError("An error occurred while dumping to " + theFileName); } else { diff --git a/src/ExchangePlugin/ExchangePlugin_Dump.h b/src/ExchangePlugin/ExchangePlugin_Dump.h index 1fa72d984..e9858a7f9 100644 --- a/src/ExchangePlugin/ExchangePlugin_Dump.h +++ b/src/ExchangePlugin/ExchangePlugin_Dump.h @@ -38,6 +38,12 @@ public: static const std::string MY_DUMP_ID("Dump"); return MY_DUMP_ID; } + /// attribute name of true dumping directory + inline static const std::string& DUMP_DIR_ID() + { + static const std::string MY_DUMP_DIR_ID("dump_dir"); + return MY_DUMP_DIR_ID; + } /// attribute name of file path inline static const std::string& FILE_PATH_ID() { diff --git a/src/ExchangePlugin/ExchangePlugin_ExportFeature.cpp b/src/ExchangePlugin/ExchangePlugin_ExportFeature.cpp index 6ae4199ec..1da829a6f 100644 --- a/src/ExchangePlugin/ExchangePlugin_ExportFeature.cpp +++ b/src/ExchangePlugin/ExchangePlugin_ExportFeature.cpp @@ -211,7 +211,7 @@ void ExchangePlugin_ExportFeature::exportFile(const std::string& theFileName, /// do not export pictures ResultPtr aBodyContext = std::dynamic_pointer_cast(anAttrSelection->context()); - if(aBodyContext->hasTextureFile()) + if (aBodyContext->hasTexture()) continue; std::shared_ptr aCurShape = anAttrSelection->value(); @@ -416,13 +416,13 @@ void ExchangePlugin_ExportFeature::exportXAO(const std::string& theFileName) AttributeSelectionListPtr aSelection = selectionList(XAO_SELECTION_LIST_ID()); bool aIsSelection = aSelection->isInitialized() && aSelection->size() > 0; if (aIsSelection) { // a mode for export to geom result by result - for(int a = 0; a < aSelection->size(); a++) { + for (int a = 0; a < aSelection->size(); a++) { AttributeSelectionPtr anAttr = aSelection->value(a); ResultPtr aBodyContext = std::dynamic_pointer_cast(anAttr->context()); if (aBodyContext.get() && !aBodyContext->isDisabled() && aBodyContext->shape().get()) { /// do not export pictures - if(aBodyContext->hasTextureFile()){ + if (aBodyContext->hasTexture()){ anExCludedIsImage = true; continue; } diff --git a/src/ExchangePlugin/ExchangePlugin_Import.cpp b/src/ExchangePlugin/ExchangePlugin_Import.cpp index 6178b2259..42601ee11 100644 --- a/src/ExchangePlugin/ExchangePlugin_Import.cpp +++ b/src/ExchangePlugin/ExchangePlugin_Import.cpp @@ -156,7 +156,7 @@ void ExchangePlugin_Import::execute() void ExchangePlugin_Import_Image::execute() { - AttributeStringPtr aFilePathAttr = string(ExchangePlugin_ImportBase::FILE_PATH_ID()); + AttributeStringPtr aFilePathAttr = string(ExchangePlugin_ImportBase::FILE_PATH_ID()); std::string aFilePath = aFilePathAttr->value(); if (aFilePath.empty()) { setError("File path is empty."); diff --git a/src/ExchangePlugin/ExchangePlugin_ImportFeature.cpp b/src/ExchangePlugin/ExchangePlugin_ImportFeature.cpp index 65045f228..e077e4ca7 100644 --- a/src/ExchangePlugin/ExchangePlugin_ImportFeature.cpp +++ b/src/ExchangePlugin/ExchangePlugin_ImportFeature.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -66,6 +67,7 @@ #include +#include /* * Request for initialization of data model of the feature: adding all attributes @@ -635,35 +637,50 @@ void ExchangePlugin_ImportFeatureBase::loadNamingDS( void ExchangePlugin_Import_ImageFeature::importFile(const std::string& theFileName) { - std::string anExtension = GeomAlgoAPI_Tools::File_Tools::extension(theFileName); - std::string theTextureFileName = ""; - // Perform the import std::string anError; - std::shared_ptr aGeomShape; - if (anExtension == "PNG" || anExtension == "GIF" || - anExtension == "TIFF" || anExtension == "JPE" || - anExtension == "JPG" || anExtension == "JPEG" || - anExtension == "BMP"|| anExtension == "PPM" - ) { - aGeomShape = ImageImport(theFileName, anError); - if(anError == "") - theTextureFileName = theFileName; - } else { - anError = "Unsupported format: " + anExtension; - } - // Check if shape is valid - if (!anError.empty()) { - setError("An error occurred while importing " + theFileName + ": " + anError); - return; - } + if (anExtension == "PNG" || anExtension == "GIF" || + anExtension == "TIFF" || anExtension == "JPE" || + anExtension == "JPEG" || anExtension == "JPG" || + anExtension == "BMP" || anExtension == "PPM" + ) { + // Perform the import + QPixmap px (theFileName.c_str()); + int aWidth = px.width(); + int aHeight = px.height(); + if (aWidth < 1 || aHeight < 1) { + setError("An error occurred while importing " + theFileName + ": invalid image"); + return; + } - // Pass the results into the model - std::string anObjectName = GeomAlgoAPI_Tools::File_Tools::name(theFileName); - data()->setName(Locale::Convert::toWString(anObjectName)); + std::shared_ptr aGeomShape = ImageImport(aWidth, aHeight, anError); + + // Check if shape is valid + if (!anError.empty()) { + setError("An error occurred while importing " + theFileName + ": " + anError); + return; + } + + // Pass the results into the model + std::string anObjectName = GeomAlgoAPI_Tools::File_Tools::name(theFileName); + data()->setName(Locale::Convert::toWString(anObjectName)); + + auto resultBody = createResultBody(aGeomShape); - auto resultBody = createResultBody(aGeomShape); - resultBody->setTextureFile(theTextureFileName); - setResult(resultBody); + // Store image in result body attribute + AttributeImagePtr anImageAttr = resultBody->data()->image(ModelAPI_ResultBody::IMAGE_ID()); + if (anImageAttr.get() != NULL) { + QImage aQImage = px.toImage(); + const uchar* aImageBytes = aQImage.bits(); + std::list aByteArray (aImageBytes, aImageBytes + aQImage.sizeInBytes()); + anImageAttr->setTexture(aWidth, aHeight, aByteArray, anExtension); + } + + setResult(resultBody); + } + else { + anError = "Unsupported format: " + anExtension; + setError("An error occurred while importing " + theFileName + ": " + anError); + } } diff --git a/src/ExchangePlugin/Test/TestImportImage_1.py b/src/ExchangePlugin/Test/TestImportImage_1.py index 1c529e196..76174f8fe 100755 --- a/src/ExchangePlugin/Test/TestImportImage_1.py +++ b/src/ExchangePlugin/Test/TestImportImage_1.py @@ -66,6 +66,9 @@ tol=1e-06 assert(abs(dx-400) <= tol) assert(abs(dy-258.5) <= tol) assert(abs(dz-0) <= tol) +assert(ImportImage_1.result().resultSubShapePair()[0].hasTexture()) +assert(Translation_1.result().resultSubShapePair()[0].hasTexture()) +assert(Scale_1.result().resultSubShapePair()[0].hasTexture()) #============================================================================= # Change the image : @@ -95,7 +98,11 @@ tol=1e-06 assert(abs(dx-448) <= tol) assert(abs(dy-296.8) <= tol) assert(abs(dz-0) <= tol) +assert(ImportImage_1.result().resultSubShapePair()[0].hasTexture()) +assert(Translation_1.result().resultSubShapePair()[0].hasTexture()) +assert(Scale_1.result().resultSubShapePair()[0].hasTexture()) +assert(model.checkPythonDump()) # Close SALOME GUI import salome_utils diff --git a/src/ExchangePlugin/Test/TestImportImage_2.py b/src/ExchangePlugin/Test/TestImportImage_2.py index 94b328fb3..c292972e1 100755 --- a/src/ExchangePlugin/Test/TestImportImage_2.py +++ b/src/ExchangePlugin/Test/TestImportImage_2.py @@ -74,6 +74,9 @@ tol=1e-06 assert(abs(dx-400) <= tol) assert(abs(dy-258.5) <= tol) assert(abs(dz-0) <= tol) +assert(ImportImage_1.result().resultSubShapePair()[0].hasTexture()) +assert(Translation_1.result().resultSubShapePair()[0].hasTexture()) +assert(Scale_1.result().resultSubShapePair()[0].hasTexture()) #============================================================================= # Change the image : @@ -101,6 +104,9 @@ tol=1e-06 assert(abs(dx-560) <= tol) assert(abs(dy-361.9) <= tol) assert(abs(dz-0) <= tol) +assert(ImportImage_1.result().resultSubShapePair()[0].hasTexture()) +assert(Translation_1.result().resultSubShapePair()[0].hasTexture()) +assert(Scale_1.result().resultSubShapePair()[0].hasTexture()) # Close SALOME GUI diff --git a/src/ExchangePlugin/Test/TestImportImage_3.py b/src/ExchangePlugin/Test/TestImportImage_3.py new file mode 100755 index 000000000..221768bf3 --- /dev/null +++ b/src/ExchangePlugin/Test/TestImportImage_3.py @@ -0,0 +1,108 @@ +# Copyright (C) 2021 CEA/DEN, EDF R&D +# +# 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 +# + +import os, inspect +from salome.shaper import model + +from PyQt5.Qt import QApplication + +import salome +salome.salome_init_without_session() +salome.salome_init(1) +if QApplication.instance() is None: + app = QApplication([]) + +from tempfile import TemporaryDirectory +from ModelAPI import * + +data_dir = os.path.join(os.path.dirname(inspect.getfile(lambda: None)), "data") + +model.begin() +partSet = model.moduleDocument() + +### Create Part +Part_1 = model.addPart(partSet) +Part_1_doc = Part_1.document() + +### Create ImportImage +ImportImage_1 = model.addImportImage(Part_1_doc, os.path.join(data_dir, "1.jpg")) +model.do() +ImportImage_1.setName("drawing") +ImportImage_1.result().setName("drawing") + +### Create Translation +Translation_1 = model.addTranslation(Part_1_doc, [model.selection("FACE", "drawing")], startPoint = model.selection("VERTEX", "[drawing/Shape_1]e[drawing/Shape_4]e"), endPoint = model.selection("VERTEX", "PartSet/Origin"), keepSubResults = True) +Translation_1.setName("translation") + +### Create Scale +Scale_1 = model.addScale(Part_1_doc, [model.selection("FACE", "drawing")] , model.selection("VERTEX", "PartSet/Origin"), 0.5, keepSubResults = True) +Scale_1.setName("scale") + +model.end() + +#============================================================================= +# Tests : +#============================================================================= +model.checkResult(Scale_1, model, 1, [0], [0], [1], [4], [8]) +r=Scale_1.defaultResult() +s=r.shape() +dim=s.computeSize() +dim=dim[1:] +dx=abs(dim[3]-dim[0]) +dy=abs(dim[4]-dim[1]) +dz=abs(dim[5]-dim[2]) +tol=1e-06 +assert(abs(dx-400) <= tol) +assert(abs(dy-258.5) <= tol) +assert(abs(dz-0) <= tol) +assert(ImportImage_1.result().resultSubShapePair()[0].hasTexture()) +assert(Translation_1.result().resultSubShapePair()[0].hasTexture()) +assert(Scale_1.result().resultSubShapePair()[0].hasTexture()) + +aDr = objectToFeature(Part_1_doc.objectByName("Features", "drawing")) +assert(aDr.firstResult().hasTexture()) + +# check save/load document with an image +with TemporaryDirectory() as tmp_dir: + aSession = ModelAPI_Session.get() + aFiles = StringList() + aSession.save(tmp_dir, aFiles) + aSession.closeAll() + assert(aSession.load(tmp_dir)) + model.begin() + partSet = model.moduleDocument() + assert(partSet.size("Features") == 1) + aPart = objectToFeature(partSet.object("Features", 0)) + aPartResult = modelAPI_ResultPart(aPart.results()[0]) + aPartResult.activate() + aPartDoc = aPartResult.partDoc() + aSession.setActiveDocument(aPartDoc, True) + model.end() + aDr = objectToFeature(aPartDoc.objectByName("Features", "drawing")) + aTr = objectToFeature(aPartDoc.objectByName("Features", "translation")) + aSc = objectToFeature(aPartDoc.objectByName("Features", "scale")) + assert(aDr.firstResult().hasTexture()) + assert(aTr.firstResult().hasTexture()) + assert(aSc.firstResult().hasTexture()) + +# Close SALOME GUI +import salome_utils +import subprocess +port = salome_utils.getPortNumber() +proc = subprocess.Popen(["killSalomeWithPort.py", "{}".format(port)]) diff --git a/src/ExchangePlugin/Test/tests_gui.set b/src/ExchangePlugin/Test/tests_gui.set index 0464ada42..b4cc706cf 100755 --- a/src/ExchangePlugin/Test/tests_gui.set +++ b/src/ExchangePlugin/Test/tests_gui.set @@ -20,4 +20,5 @@ SET(TEST_WITH_GUI_NAMES TestImportImage_1.py TestImportImage_2.py + TestImportImage_3.py ) \ No newline at end of file diff --git a/src/FeaturesPlugin/FeaturesPlugin_MultiRotation.cpp b/src/FeaturesPlugin/FeaturesPlugin_MultiRotation.cpp index e8caba9bf..a3f08292a 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_MultiRotation.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_MultiRotation.cpp @@ -44,6 +44,7 @@ #include #include #include +#include #include #include @@ -166,9 +167,9 @@ void FeaturesPlugin_MultiRotation::performRotation1D() GeomAPI_ShapeHierarchy anObjects; std::list aParts; - std::string theTextureFile; - if (!FeaturesPlugin_Tools::shapesFromSelectionList( - anObjectsSelList, isKeepSubShapes, anObjects, aParts, theTextureFile)) + ResultPtr aTextureSource; + if (!FeaturesPlugin_Tools::shapesFromSelectionList + (anObjectsSelList, isKeepSubShapes, anObjects, aParts, aTextureSource)) return; // Parameters of rotation. @@ -225,7 +226,8 @@ void FeaturesPlugin_MultiRotation::performRotation1D() ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex); FeaturesPlugin_Tools::loadModifiedShapes(aResultBody, anOriginalShapes, ListOfShape(), aMakeShapeList, *anIt, "Rotated"); - aResultBody->setTextureFile(theTextureFile); + // Copy image data, if any + ModelAPI_Tools::copyImageAttribute(aTextureSource, aResultBody); setResult(aResultBody, aResultIndex++); } diff --git a/src/FeaturesPlugin/FeaturesPlugin_MultiTranslation.cpp b/src/FeaturesPlugin/FeaturesPlugin_MultiTranslation.cpp index c507c7d50..5fafcb11a 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_MultiTranslation.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_MultiTranslation.cpp @@ -37,6 +37,7 @@ #include #include #include +#include #include @@ -91,9 +92,9 @@ void FeaturesPlugin_MultiTranslation::execute() GeomAPI_ShapeHierarchy anObjects; std::list aParts; - std::string theTextureFile; - if (!FeaturesPlugin_Tools::shapesFromSelectionList( - anObjectsSelList, isKeepSubShapes, anObjects, aParts, theTextureFile)) + ResultPtr aTextureSource; + if (!FeaturesPlugin_Tools::shapesFromSelectionList + (anObjectsSelList, isKeepSubShapes, anObjects, aParts, aTextureSource)) return; std::shared_ptr aFirstDir, aSecondDir; @@ -171,7 +172,8 @@ void FeaturesPlugin_MultiTranslation::execute() ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex); FeaturesPlugin_Tools::loadModifiedShapes(aResultBody, anOriginalShapes, ListOfShape(), aMakeShapeList, *anIt, "Translated"); - aResultBody->setTextureFile(theTextureFile); + // Copy image data, if any + ModelAPI_Tools::copyImageAttribute(aTextureSource, aResultBody); setResult(aResultBody, aResultIndex++); } diff --git a/src/FeaturesPlugin/FeaturesPlugin_Placement.cpp b/src/FeaturesPlugin/FeaturesPlugin_Placement.cpp index efc09092a..8b109aed1 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Placement.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Placement.cpp @@ -71,10 +71,10 @@ void FeaturesPlugin_Placement::execute() // Getting objects. GeomAPI_ShapeHierarchy anObjects; std::list aParts; - std::string theTextureFile; + ResultPtr aTextureSource; AttributeSelectionListPtr anObjectsSelList = selectionList(OBJECTS_LIST_ID()); - if (!FeaturesPlugin_Tools::shapesFromSelectionList( - anObjectsSelList, isKeepSubShapes, anObjects, aParts, theTextureFile)) + if (!FeaturesPlugin_Tools::shapesFromSelectionList + (anObjectsSelList, isKeepSubShapes, anObjects, aParts, aTextureSource)) return; // Verify the start shape @@ -181,7 +181,8 @@ void FeaturesPlugin_Placement::execute() ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex); FeaturesPlugin_Tools::loadModifiedShapes(aResultBody, anOriginalShapes, ListOfShape(), aMakeShapeList, *anIt, "Placed"); - aResultBody->setTextureFile(theTextureFile); + // Copy image data, if any + ModelAPI_Tools::copyImageAttribute(aTextureSource, aResultBody); setResult(aResultBody, aResultIndex++); } diff --git a/src/FeaturesPlugin/FeaturesPlugin_Rotation.cpp b/src/FeaturesPlugin/FeaturesPlugin_Rotation.cpp index 1fe9334eb..8627c4c64 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Rotation.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Rotation.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -184,10 +185,10 @@ void FeaturesPlugin_Rotation::performRotation(const GeomTrsfPtr& theTrsf) // Getting objects. GeomAPI_ShapeHierarchy anObjects; std::list aParts; - std::string theTextureFile; + ResultPtr aTextureSource; AttributeSelectionListPtr anObjSelList = selectionList(OBJECTS_LIST_ID()); if (!FeaturesPlugin_Tools::shapesFromSelectionList( - anObjSelList, isKeepSubShapes, anObjects, aParts, theTextureFile)) + anObjSelList, isKeepSubShapes, anObjects, aParts, aTextureSource)) return; std::string anError; @@ -226,7 +227,8 @@ void FeaturesPlugin_Rotation::performRotation(const GeomTrsfPtr& theTrsf) ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex); FeaturesPlugin_Tools::loadModifiedShapes(aResultBody, anOriginalShapes, ListOfShape(), aMakeShapeList, *anIt, "Rotated"); - aResultBody->setTextureFile(theTextureFile); + // Copy image data, if any + ModelAPI_Tools::copyImageAttribute(aTextureSource, aResultBody); setResult(aResultBody, aResultIndex++); } diff --git a/src/FeaturesPlugin/FeaturesPlugin_Scale.cpp b/src/FeaturesPlugin/FeaturesPlugin_Scale.cpp index 73cbd10bc..6766e10dc 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Scale.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Scale.cpp @@ -32,6 +32,7 @@ #include #include #include +#include static const std::string SCALE_VERSION_1("v9.5"); @@ -92,10 +93,10 @@ void FeaturesPlugin_Scale::performScaleByFactor() // Getting objects. GeomAPI_ShapeHierarchy anObjects; std::list aParts; - std::string theTextureFile; + ResultPtr aTextureSource; AttributeSelectionListPtr anObjSelList = selectionList(OBJECTS_LIST_ID()); if (!FeaturesPlugin_Tools::shapesFromSelectionList( - anObjSelList, isKeepSubShapes, anObjects, aParts, theTextureFile)) + anObjSelList, isKeepSubShapes, anObjects, aParts, aTextureSource)) return; // Getting the center point @@ -143,7 +144,8 @@ void FeaturesPlugin_Scale::performScaleByFactor() ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex); FeaturesPlugin_Tools::loadModifiedShapes(aResultBody, anOriginalShapes, ListOfShape(), aMakeShapeList, *anIt, "Scaled"); - aResultBody->setTextureFile(theTextureFile); + // Copy image data, if any + ModelAPI_Tools::copyImageAttribute(aTextureSource, aResultBody); setResult(aResultBody, aResultIndex++); } @@ -159,10 +161,10 @@ void FeaturesPlugin_Scale::performScaleByDimensions() // Getting objects. GeomAPI_ShapeHierarchy anObjects; std::list aParts; - std::string theTextureFile; + ResultPtr aTextureSource; AttributeSelectionListPtr anObjSelList = selectionList(OBJECTS_LIST_ID()); if (!FeaturesPlugin_Tools::shapesFromSelectionList( - anObjSelList, isKeepSubShapes, anObjects, aParts, theTextureFile)) + anObjSelList, isKeepSubShapes, anObjects, aParts, aTextureSource)) return; // Getting the center point @@ -215,7 +217,8 @@ void FeaturesPlugin_Scale::performScaleByDimensions() ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex); FeaturesPlugin_Tools::loadModifiedShapes(aResultBody, anOriginalShapes, ListOfShape(), aMakeShapeList, *anIt, "Scaled"); - aResultBody->setTextureFile(theTextureFile); + // Copy image data, if any + ModelAPI_Tools::copyImageAttribute(aTextureSource, aResultBody); setResult(aResultBody, aResultIndex++); } diff --git a/src/FeaturesPlugin/FeaturesPlugin_Symmetry.cpp b/src/FeaturesPlugin/FeaturesPlugin_Symmetry.cpp index e877c4016..9a5830bcf 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Symmetry.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Symmetry.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #include @@ -204,13 +205,14 @@ void FeaturesPlugin_Symmetry::buildResult( const std::shared_ptr& theAlgo, const std::list >& theOriginalShapes, std::shared_ptr theTargetShape, int& theResultIndex, - std::string & theTextureFile) + const ResultPtr& theTextureSource) { // Store and name the result. ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex); FeaturesPlugin_Tools::loadModifiedShapes(aResultBody, theOriginalShapes, ListOfShape(), theAlgo, theTargetShape, "Symmetried"); - aResultBody->setTextureFile(theTextureFile); + // Copy image data, if any + ModelAPI_Tools::copyImageAttribute(theTextureSource, aResultBody); setResult(aResultBody, theResultIndex++); } @@ -281,10 +283,10 @@ void FeaturesPlugin_Symmetry::performSymmetry(GeomTrsfPtr theTrsf) // Getting objects. GeomAPI_ShapeHierarchy anObjects; std::list aParts; - std::string theTextureFile; + ResultPtr aTextureSource; AttributeSelectionListPtr anObjSelList = selectionList(OBJECTS_LIST_ID()); if (!FeaturesPlugin_Tools::shapesFromSelectionList( - anObjSelList, isKeepSubShapes, anObjects, aParts, theTextureFile)) + anObjSelList, isKeepSubShapes, anObjects, aParts, aTextureSource)) return; std::string anError; @@ -312,7 +314,7 @@ void FeaturesPlugin_Symmetry::performSymmetry(GeomTrsfPtr theTrsf) ListOfShape aTopLevel; anObjects.topLevelObjects(aTopLevel); for (ListOfShape::iterator anIt = aTopLevel.begin(); anIt != aTopLevel.end(); ++anIt) - buildResult(aMakeShapeList, anOriginalShapes, *anIt, aResultIndex, theTextureFile); + buildResult(aMakeShapeList, anOriginalShapes, *anIt, aResultIndex, aTextureSource); // Remove the rest results if there were produced in the previous pass. removeResults(aResultIndex); diff --git a/src/FeaturesPlugin/FeaturesPlugin_Symmetry.h b/src/FeaturesPlugin/FeaturesPlugin_Symmetry.h index 5d73f9ec8..814dcdb7b 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Symmetry.h +++ b/src/FeaturesPlugin/FeaturesPlugin_Symmetry.h @@ -23,6 +23,7 @@ #include #include +#include class GeomAPI_Trsf; class GeomAlgoAPI_MakeShapeList; @@ -137,7 +138,8 @@ private: void buildResult(const std::shared_ptr& theAlgo, const std::list >& theOriginalShapes, std::shared_ptr theTargetShape, - int& theResultIndex, std::string &theTextureFile); + int& theResultIndex, + const ResultPtr& theTextureSource); /// Create new result for the given part and transformation void buildResult(std::shared_ptr theOriginal, diff --git a/src/FeaturesPlugin/FeaturesPlugin_Tools.cpp b/src/FeaturesPlugin/FeaturesPlugin_Tools.cpp index 9a36609a4..d1a690ce1 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Tools.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Tools.cpp @@ -263,27 +263,21 @@ bool FeaturesPlugin_Tools::shapesFromSelectionList( const std::shared_ptr theSelectionList, const bool theStoreFullHierarchy, GeomAPI_ShapeHierarchy& theHierarchy, - std::list& theParts, std::string &theTextureFile) + std::list& theParts, ResultPtr& theTextureSource) { int aSize = theSelectionList->size(); - if(aSize == 1) - { + if (aSize == 1) { auto anObjectAttr = theSelectionList->value(0); - if(anObjectAttr.get()) - { + if (anObjectAttr.get()) { FeaturePtr aFeature = anObjectAttr->contextFeature(); - if(aFeature.get() && aFeature->results().size() == 1) - { - theTextureFile = aFeature->firstResult()->getTextureFile(); + if (aFeature.get() && aFeature->results().size() == 1) { + theTextureSource = aFeature->firstResult(); } - else - { - if(!aFeature.get()) - { - auto aResult = anObjectAttr->context(); - if(aResult.get()) - { - theTextureFile = aResult->getTextureFile(); + else { + if (!aFeature.get()) { + auto aResult = anObjectAttr->context(); + if (aResult.get()) { + theTextureSource = aResult; } } } diff --git a/src/FeaturesPlugin/FeaturesPlugin_Tools.h b/src/FeaturesPlugin/FeaturesPlugin_Tools.h index c9a138a37..e901063fd 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Tools.h +++ b/src/FeaturesPlugin/FeaturesPlugin_Tools.h @@ -69,7 +69,8 @@ public: const std::shared_ptr theSelectionList, const bool theStoreFullHierarchy, GeomAPI_ShapeHierarchy& theHierarchy, - std::list& theParts, std::string& theTextureFile); + std::list& theParts, + ResultPtr& theTextureSource); }; #endif /* FeaturesPlugin_Tools_H_ */ diff --git a/src/FeaturesPlugin/FeaturesPlugin_Translation.cpp b/src/FeaturesPlugin/FeaturesPlugin_Translation.cpp index 11a0dca22..9586fea92 100644 --- a/src/FeaturesPlugin/FeaturesPlugin_Translation.cpp +++ b/src/FeaturesPlugin/FeaturesPlugin_Translation.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -197,10 +198,10 @@ void FeaturesPlugin_Translation::performTranslation(const GeomTrsfPtr& theTrsf) // Getting objects. GeomAPI_ShapeHierarchy anObjects; std::list aParts; - std::string theTextureFile; + ResultPtr aTextureSource; AttributeSelectionListPtr anObjectsSelList = selectionList(OBJECTS_LIST_ID()); - if (!FeaturesPlugin_Tools::shapesFromSelectionList( - anObjectsSelList, isKeepSubShapes, anObjects, aParts, theTextureFile)) + if (!FeaturesPlugin_Tools::shapesFromSelectionList + (anObjectsSelList, isKeepSubShapes, anObjects, aParts, aTextureSource)) return; std::string anError; @@ -241,7 +242,8 @@ void FeaturesPlugin_Translation::performTranslation(const GeomTrsfPtr& theTrsf) ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex); FeaturesPlugin_Tools::loadModifiedShapes(aResultBody, anOriginalShapes, ListOfShape(), aMakeShapeList, *anIt, "Translated"); - aResultBody->setTextureFile(theTextureFile); + // Copy image data, if any + ModelAPI_Tools::copyImageAttribute(aTextureSource, aResultBody); setResult(aResultBody, aResultIndex++); } diff --git a/src/GeomAlgoAPI/CMakeLists.txt b/src/GeomAlgoAPI/CMakeLists.txt index 2fa736470..19ace76ed 100644 --- a/src/GeomAlgoAPI/CMakeLists.txt +++ b/src/GeomAlgoAPI/CMakeLists.txt @@ -173,7 +173,6 @@ SET(PROJECT_LIBRARIES ${OpenCASCADE_DataExchange_LIBRARIES} ${OpenCASCADE_ModelingAlgorithms_LIBRARIES} ${OpenCASCADE_ApplicationFramework_LIBRARIES} - ${QT_LIBRARIES} ) ADD_DEFINITIONS(-DGEOMALGOAPI_EXPORTS ${OpenCASCADE_DEFINITIONS}) @@ -184,10 +183,7 @@ SET(CMAKE_SWIG_FLAGS -w325,321,362,383,302) SET_SOURCE_FILES_PROPERTIES(GeomAlgoAPI.i PROPERTIES CPLUSPLUS ON) SET_SOURCE_FILES_PROPERTIES(GeomAlgoAPI.i PROPERTIES SWIG_DEFINITIONS "-shadow") -INCLUDE(UseQtExt) # additional include directories -INCLUDE_DIRECTORIES(${QT_INCLUDES}) - INCLUDE_DIRECTORIES( ../GeomAPI ../GeomAlgoImpl diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_ImageImport.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_ImageImport.cpp index 1f73aeef1..d0077871a 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_ImageImport.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_ImageImport.cpp @@ -19,7 +19,6 @@ #include -#include #include #include #include @@ -36,18 +35,13 @@ #include #include -std::shared_ptr ImageImport(const std::string& theFileName, - std::string& theError) +std::shared_ptr ImageImport(const int width, + const int height, + std::string& theError) { TopoDS_Shape aResShape; try { - QPixmap* pixmap = new QPixmap(theFileName.c_str()); - int height = pixmap->height(); - int width = pixmap->width(); - - delete pixmap; - TopoDS_Vertex aTriVertexes[4]; gp_Pnt aPnt1( -0.5*width, -0.5*height, 0); gp_Pnt aPnt2( 0.5*width, -0.5*height, 0); diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_ImageImport.h b/src/GeomAlgoAPI/GeomAlgoAPI_ImageImport.h index 4f9573b48..5a29f8fbf 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_ImageImport.h +++ b/src/GeomAlgoAPI/GeomAlgoAPI_ImageImport.h @@ -23,10 +23,11 @@ #include #include -#include + /// Implementation of the import STL files algorithms GEOMALGOAPI_EXPORT -std::shared_ptr ImageImport(const std::string& theFileName, - std::string& theError); +std::shared_ptr ImageImport(const int theWidth, + const int theHeight, + std::string& theError); #endif /* GEOMALGOAPI_IMAGEIMPORT_H_ */ diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Tools.cpp b/src/GeomAlgoAPI/GeomAlgoAPI_Tools.cpp index 3bdecb71d..a26b7257e 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_Tools.cpp +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Tools.cpp @@ -61,6 +61,14 @@ std::string File_Tools::name(const std::string& theFileName) return aPath.Name().ToCString(); } +std::string File_Tools::path(const std::string& theFileName) +{ + OSD_Path aPath (theFileName.c_str()); + Standard_Integer aTrekLen = + theFileName.size() - aPath.Extension().Length() - aPath.Name().Length(); + return theFileName.substr(0, aTrekLen); +} + bool AlgoError::isAlgorithmFailed(const GeomMakeShapePtr& theAlgorithm, const std::string& theFeature, std::string& theError) diff --git a/src/GeomAlgoAPI/GeomAlgoAPI_Tools.h b/src/GeomAlgoAPI/GeomAlgoAPI_Tools.h index d7020e68e..39081890a 100644 --- a/src/GeomAlgoAPI/GeomAlgoAPI_Tools.h +++ b/src/GeomAlgoAPI/GeomAlgoAPI_Tools.h @@ -63,6 +63,10 @@ public: * Returns a name of theFileName */ GEOMALGOAPI_EXPORT static std::string name(const std::string& theFileName); + /** + * Returns a directory path of theFileName + */ + GEOMALGOAPI_EXPORT static std::string path(const std::string& theFileName); }; /** \class AlgoError diff --git a/src/Model/CMakeLists.txt b/src/Model/CMakeLists.txt index 2f349c193..c270a9c13 100644 --- a/src/Model/CMakeLists.txt +++ b/src/Model/CMakeLists.txt @@ -34,6 +34,7 @@ SET(PROJECT_HEADERS Model_AttributeRefList.h Model_AttributeRefAttrList.h Model_AttributeBoolean.h + Model_AttributeImage.h Model_AttributeIntArray.h Model_AttributeString.h Model_AttributeStringArray.h @@ -72,6 +73,7 @@ SET(PROJECT_SOURCES Model_AttributeRefList.cpp Model_AttributeRefAttrList.cpp Model_AttributeBoolean.cpp + Model_AttributeImage.cpp Model_AttributeIntArray.cpp Model_AttributeString.cpp Model_AttributeStringArray.cpp diff --git a/src/Model/Model_AttributeImage.cpp b/src/Model/Model_AttributeImage.cpp new file mode 100644 index 000000000..c74e42945 --- /dev/null +++ b/src/Model/Model_AttributeImage.cpp @@ -0,0 +1,147 @@ +// Copyright (C) 2014-2021 CEA/DEN, EDF R&D +// +// 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 +// + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +void Model_AttributeImage::setTexture(const int theWidth, + const int theHeight, + const std::list& theByteArray, + const std::string& theFormat, + const bool sendUpdated) +{ + if (theWidth > 0 && theHeight > 0 && theByteArray.size() > 0) { // set new data + // Find or create attributes + Handle_TDataStd_ByteArray aByteArray = + TDataStd_ByteArray::Set(myLab, 0, theByteArray.size() - 1); + Handle_TDataStd_IntegerArray aDimensions = + TDataStd_IntegerArray::Set(myLab, 0, 1); + Handle_TDataStd_Comment aFormat = TDataStd_Comment::Set(myLab, theFormat.c_str()); + + // Dimensions + aDimensions->SetValue(0, theWidth); + aDimensions->SetValue(1, theHeight); + + // Texture + Handle(TColStd_HArray1OfByte) aNewArray = + new TColStd_HArray1OfByte(0, theByteArray.size() - 1); + std::list::const_iterator itBA = theByteArray.begin(); + for (int j = 0; itBA != theByteArray.end(); ++itBA, ++j) { + aNewArray->SetValue(j, (Standard_Byte)(*itBA)); + } + aByteArray->ChangeArray(aNewArray); + + if (sendUpdated) + owner()->data()->sendAttributeUpdated(this); + } + else { // size is zero => arrays must be erased + bool isForgotten1 = myLab.ForgetAttribute(TDataStd_ByteArray::GetID()); + bool isForgotten2 = myLab.ForgetAttribute(TDataStd_IntegerArray::GetID()); + bool isForgotten3 = myLab.ForgetAttribute(TDataStd_Comment::GetID()); + + if (sendUpdated && (isForgotten1 || isForgotten2 || isForgotten3)) + owner()->data()->sendAttributeUpdated(this); + } +} + +bool Model_AttributeImage::hasTexture() +{ + Handle_TDataStd_ByteArray aByteArray; + Handle_TDataStd_IntegerArray aDimensions; + if (myLab.FindAttribute(TDataStd_ByteArray::GetID(), aByteArray) == Standard_True && + myLab.FindAttribute(TDataStd_IntegerArray::GetID(), aDimensions) == Standard_True) { + + // Dimensions + if (aDimensions->Value(0) > 0 && aDimensions->Value(1) > 0) + // Byte array + return aByteArray->Length() > 0; + } + return false; +} + +bool Model_AttributeImage::texture(int& theWidth, + int& theHeight, + std::list& theByteArray, + std::string& theFormat) +{ + // Init return values + theWidth = 0; + theHeight = 0; + theByteArray.clear(); + theFormat = ""; + + Handle_TDataStd_ByteArray aByteArray; + Handle_TDataStd_IntegerArray aDimensions; + Handle_TDataStd_Comment aFormat; + if (myLab.FindAttribute(TDataStd_ByteArray::GetID(), aByteArray) == Standard_True && + myLab.FindAttribute(TDataStd_IntegerArray::GetID(), aDimensions) == Standard_True && + myLab.FindAttribute(TDataStd_Comment::GetID(), aFormat) == Standard_True) { + + // Dimensions + theWidth = aDimensions->Value(0); + theHeight = aDimensions->Value(1); + + // Texture + const Handle(TColStd_HArray1OfByte) byteArray = aByteArray->InternalArray(); + for (int j = byteArray->Lower(); j <= byteArray->Upper(); j++) { + theByteArray.push_back((unsigned char)byteArray->Value( j )); + } + + // Format + theFormat = TCollection_AsciiString(aFormat->Get()).ToCString(); + return true; + } + + return false; +} + +void Model_AttributeImage::copyTo(AttributeImagePtr theTarget) const +{ + std::shared_ptr aTarget = + std::dynamic_pointer_cast(theTarget); + if (aTarget) { + //Model_AttributeSelectionList::copyAttrs(myLab, aTarget->myLab); + TDF_CopyLabel aCopyAlgo (myLab, aTarget->myLab); + aCopyAlgo.Perform(); + aTarget->reinit(); + } +} + +Model_AttributeImage::Model_AttributeImage(TDF_Label& theLabel) +{ + myLab = theLabel; + reinit(); +} + +void Model_AttributeImage::reinit() +{ + myIsInitialized = myLab.IsAttribute(TDataStd_ByteArray::GetID()); +} diff --git a/src/Model/Model_AttributeImage.h b/src/Model/Model_AttributeImage.h new file mode 100644 index 000000000..c4827c322 --- /dev/null +++ b/src/Model/Model_AttributeImage.h @@ -0,0 +1,73 @@ +// Copyright (C) 2014-2021 CEA/DEN, EDF R&D +// +// 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 +// + +#ifndef MODEL_ATTRIBUTEIMAGE_H_ +#define MODEL_ATTRIBUTEIMAGE_H_ + +#include +#include + +#include + +#include + +/**\class Model_AttributeImage + * \ingroup DataModel + * \brief API for the attribute that contains image inside. + * Represented as the following OCCT attributes: + * TDataStd_ByteArray for the pixmap texture data, + * TDataStd_IntArray(2) for image dimensions (widht and height), + * TDataStd_String for image format. + */ + +class Model_AttributeImage : public ModelAPI_AttributeImage +{ + /// Stores the label as the only reference to all data + TDF_Label myLab; + + public: + /// Defines the value of the image attribute + MODEL_EXPORT virtual void setTexture(const int theWidth, + const int theHeight, + const std::list& theByteArray, + const std::string& theFormat, + const bool sendUpdated = true); + + /// Returns true, if texture width and height are non-zero + MODEL_EXPORT virtual bool hasTexture(); + + /// Returns the value of the image attribute + MODEL_EXPORT virtual bool texture(int& theWidth, + int& theHeight, + std::list& theByteArray, + std::string& theFormat); + + /// Copy the image data to the destination attribute + virtual void copyTo(std::shared_ptr theTarget) const; + + protected: + /// Initializes attibutes + Model_AttributeImage(TDF_Label& theLabel); + /// Reinitializes the internal state of the attribute (may be needed on undo/redo, abort, etc) + virtual void reinit(); + + friend class Model_Data; +}; + +#endif diff --git a/src/Model/Model_Data.cpp b/src/Model/Model_Data.cpp index 817a9e407..599c65086 100644 --- a/src/Model/Model_Data.cpp +++ b/src/Model/Model_Data.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -218,6 +219,8 @@ AttributePtr Model_Data::addAttribute( anAttr = new Model_AttributeDoubleArray(anAttrLab); } else if (theAttrType == ModelAPI_AttributeTables::typeId()) { anAttr = new Model_AttributeTables(anAttrLab); + } else if (theAttrType == ModelAPI_AttributeImage::typeId()) { + anAttr = new Model_AttributeImage(anAttrLab); } // create also GeomData attributes here because only here the OCAF structure is known else if (theAttrType == GeomData_Point::typeId()) { @@ -375,6 +378,7 @@ GET_ATTRIBUTE_BY_ID(ModelAPI_AttributeRefAttrList, refattrlist); GET_ATTRIBUTE_BY_ID(ModelAPI_AttributeIntArray, intArray); GET_ATTRIBUTE_BY_ID(ModelAPI_AttributeDoubleArray, realArray); GET_ATTRIBUTE_BY_ID(ModelAPI_AttributeTables, tables); +GET_ATTRIBUTE_BY_ID(ModelAPI_AttributeImage, image); std::shared_ptr Model_Data::attribute(const std::string& theID) { diff --git a/src/Model/Model_Data.h b/src/Model/Model_Data.h index df833acc0..bb073eb11 100644 --- a/src/Model/Model_Data.h +++ b/src/Model/Model_Data.h @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -155,6 +156,9 @@ class Model_Data : public ModelAPI_Data /// Returns the attribute that contains string values array MODEL_EXPORT virtual std::shared_ptr tables(const std::string& theID); + /// Returns the attribute that contains image + MODEL_EXPORT virtual std::shared_ptr + image(const std::string& theID); /// Returns the generic attribute by identifier /// \param theID identifier of the attribute diff --git a/src/Model/Model_ResultBody.cpp b/src/Model/Model_ResultBody.cpp index 65b687519..32f439df6 100644 --- a/src/Model/Model_ResultBody.cpp +++ b/src/Model/Model_ResultBody.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -56,6 +57,13 @@ Model_ResultBody::~Model_ResultBody() delete myBuilder; } +void Model_ResultBody::initAttributes() +{ + ModelAPI_Result::initAttributes(); + // append the image attribute. It is empty, the attribute will be filled by a request + data()->addAttribute(IMAGE_ID(), ModelAPI_AttributeImage::typeId())->setIsArgument(false); +} + bool Model_ResultBody::generated(const GeomShapePtr& theNewShape, const std::string& theName, const bool theCheckIsInResult) { @@ -408,17 +416,6 @@ void Model_ResultBody::updateSubs( myHistoryCash.Clear(); } -void Model_ResultBody::setTextureFile(const std::string & theTextureFile) -{ - ModelAPI_Result::setTextureFile(theTextureFile); - for( auto sub : mySubs){ - sub->setTextureFile(theTextureFile); - } - for(auto map : mySubsMap){ - map.first->setTextureFile(theTextureFile); - } -} - bool Model_ResultBody::isConnectedTopology() { TDF_Label aDataLab = std::dynamic_pointer_cast(data())->label(); @@ -448,6 +445,16 @@ void Model_ResultBody::cleanCash() } } +bool Model_ResultBody::hasTexture() +{ + AttributeImagePtr anImageAttr = + data()->image(ModelAPI_ResultBody::IMAGE_ID()); + if (anImageAttr.get()) { + return anImageAttr->hasTexture(); + } + return false; +} + // adds to the theSubSubs map all sub-shapes of theSub if it is compound of compsolid static void collectSubs( const GeomShapePtr theSub, TopTools_MapOfShape& theSubSubs, const bool theOneLevelMore) diff --git a/src/Model/Model_ResultBody.h b/src/Model/Model_ResultBody.h index 721312c3a..4a8479af5 100644 --- a/src/Model/Model_ResultBody.h +++ b/src/Model/Model_ResultBody.h @@ -58,6 +58,9 @@ public: /// Removes the stored builders MODEL_EXPORT virtual ~Model_ResultBody(); + /// Request for initialization of data model of the result body: adding all attributes + virtual void initAttributes(); + /// Records the subshape newShape which was generated during a topological construction. /// As an example, consider the case of a face generated in construction of a box. MODEL_EXPORT virtual bool generated(const GeomShapePtr& theNewShape, @@ -114,7 +117,7 @@ public: MODEL_EXPORT virtual void cleanCash() override; /// sets the texture file - MODEL_EXPORT virtual void setTextureFile(const std::string & theTextureFile) override; + MODEL_EXPORT virtual bool hasTexture() override; protected: diff --git a/src/ModelAPI/CMakeLists.txt b/src/ModelAPI/CMakeLists.txt index d2d565eee..bbef9d3e5 100644 --- a/src/ModelAPI/CMakeLists.txt +++ b/src/ModelAPI/CMakeLists.txt @@ -26,6 +26,7 @@ SET(PROJECT_HEADERS ModelAPI.h ModelAPI_Attribute.h ModelAPI_AttributeBoolean.h + ModelAPI_AttributeImage.h ModelAPI_AttributeIntArray.h ModelAPI_AttributeDocRef.h ModelAPI_AttributeDouble.h @@ -74,6 +75,7 @@ SET(PROJECT_HEADERS SET(PROJECT_SOURCES ModelAPI_Attribute.cpp ModelAPI_AttributeBoolean.cpp + ModelAPI_AttributeImage.cpp ModelAPI_AttributeIntArray.cpp ModelAPI_AttributeDocRef.cpp ModelAPI_AttributeDouble.cpp diff --git a/src/ModelAPI/ModelAPI_AttributeImage.cpp b/src/ModelAPI/ModelAPI_AttributeImage.cpp new file mode 100644 index 000000000..4caea4544 --- /dev/null +++ b/src/ModelAPI/ModelAPI_AttributeImage.cpp @@ -0,0 +1,35 @@ +// Copyright (C) 2014-2021 CEA/DEN, EDF R&D +// +// 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 +// + +#include + + +std::string ModelAPI_AttributeImage::attributeType() +{ + return typeId(); +} + +/// To virtually destroy the fields of successors +ModelAPI_AttributeImage::~ModelAPI_AttributeImage() +{ +} + +ModelAPI_AttributeImage::ModelAPI_AttributeImage() +{ +} diff --git a/src/ModelAPI/ModelAPI_AttributeImage.h b/src/ModelAPI/ModelAPI_AttributeImage.h new file mode 100644 index 000000000..14fc1e717 --- /dev/null +++ b/src/ModelAPI/ModelAPI_AttributeImage.h @@ -0,0 +1,78 @@ +// Copyright (C) 2014-2021 CEA/DEN, EDF R&D +// +// 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 +// + +#ifndef ModelAPI_AttributeImage_H_ +#define ModelAPI_AttributeImage_H_ + +#include +#include + +#include +#include + + +/**\class ModelAPI_AttributeImage + * \ingroup DataModel + * \brief API for the attribute that contains binary data. + * Used for images storage for an example. By default size is one, zero-based. + */ + +class ModelAPI_AttributeImage : public ModelAPI_Attribute +{ + public: + /// Defines the value of the image attribute + MODELAPI_EXPORT virtual void setTexture(const int theWidth, + const int theHeight, + const std::list& theByteArray, + const std::string& theFormat, + const bool sendUpdated = true) = 0; + + /// Returns true, if texture width and height are non-zero + MODELAPI_EXPORT virtual bool hasTexture() = 0; + + /// Returns the value of the image attribute + MODELAPI_EXPORT virtual bool texture(int& theWidth, + int& theHeight, + std::list& theByteArray, + std::string& theFormat) = 0; + + /// Copy the image data to the destination attribute + virtual void copyTo(std::shared_ptr theTarget) const = 0; + + /// Returns the type of this class of attributes + MODELAPI_EXPORT static std::string typeId() + { + return "Image"; + } + + /// Returns the type of this class of attributes, not static method + MODELAPI_EXPORT virtual std::string attributeType(); + + /// To virtually destroy the fields of successors + MODELAPI_EXPORT virtual ~ModelAPI_AttributeImage(); + + protected: + /// Objects are created for features automatically + MODELAPI_EXPORT ModelAPI_AttributeImage(); +}; + +//! Pointer on image attribute +typedef std::shared_ptr AttributeImagePtr; + +#endif diff --git a/src/ModelAPI/ModelAPI_Data.h b/src/ModelAPI/ModelAPI_Data.h index a8f22355e..a5907974a 100644 --- a/src/ModelAPI/ModelAPI_Data.h +++ b/src/ModelAPI/ModelAPI_Data.h @@ -48,6 +48,7 @@ class ModelAPI_Feature; class ModelAPI_AttributeSelection; class ModelAPI_AttributeSelectionList; class ModelAPI_AttributeIntArray; +class ModelAPI_AttributeImage; class ModelAPI_AttributeTables; class ModelAPI_Object; class GeomAPI_Shape; @@ -113,6 +114,8 @@ class MODELAPI_EXPORT ModelAPI_Data virtual std::shared_ptr intArray(const std::string& theID) = 0; /// Returns the attribute that contains string values array virtual std::shared_ptr stringArray(const std::string& theID) = 0; + /// Returns the attribute that contains image + virtual std::shared_ptr image(const std::string& theID) = 0; /// Returns the attribute that contains tables virtual std::shared_ptr tables(const std::string& theID) = 0; diff --git a/src/ModelAPI/ModelAPI_Object.h b/src/ModelAPI/ModelAPI_Object.h index 5710af6f9..32e48bc40 100644 --- a/src/ModelAPI/ModelAPI_Object.h +++ b/src/ModelAPI/ModelAPI_Object.h @@ -45,7 +45,6 @@ class ModelAPI_Object: public ModelAPI_Entity { std::shared_ptr myData; ///< manager of the data model of a feature std::shared_ptr myDoc; ///< document this object belongs to - std::string textureFile = ""; public: #ifdef DEBUG_NAMES std::wstring myName; // name of this object @@ -101,19 +100,9 @@ class ModelAPI_Object: public ModelAPI_Entity /// signal. MODELAPI_EXPORT virtual void setDisplayed(const bool theDisplay); - MODELAPI_EXPORT bool hasTextureFile() + MODELAPI_EXPORT virtual bool hasTexture() { - return (textureFile != ""); - } - - MODELAPI_EXPORT virtual void setTextureFile(const std::string & theTextureFile) - { - textureFile = theTextureFile; - } - - MODELAPI_EXPORT const std::string & getTextureFile() - { - return textureFile; + return false; } protected: diff --git a/src/ModelAPI/ModelAPI_Result.h b/src/ModelAPI/ModelAPI_Result.h index 05e48d1de..1fc3c1ab8 100644 --- a/src/ModelAPI/ModelAPI_Result.h +++ b/src/ModelAPI/ModelAPI_Result.h @@ -39,7 +39,7 @@ class ModelAPI_Result : public ModelAPI_Object public: /// Reference to the color of the result. - /// The integer array is used. It contains tree values for red green and blue values. + /// The integer array is used. It contains three values for red, green and blue values. /// The values are in [0, 255] range inline static const std::string& COLOR_ID() { diff --git a/src/ModelAPI/ModelAPI_ResultBody.h b/src/ModelAPI/ModelAPI_ResultBody.h index 5c19f711c..ec323ac28 100644 --- a/src/ModelAPI/ModelAPI_ResultBody.h +++ b/src/ModelAPI/ModelAPI_ResultBody.h @@ -58,6 +58,13 @@ protected: public: MODELAPI_EXPORT virtual ~ModelAPI_ResultBody(); + /// Reference to the image attribute of the result body. + inline static const std::string& IMAGE_ID() + { + static const std::string MY_IMAGE_ID("Image"); + return MY_IMAGE_ID; + } + /// Returns the group identifier of this result MODELAPI_EXPORT virtual std::string groupName(); diff --git a/src/ModelAPI/ModelAPI_Tools.cpp b/src/ModelAPI/ModelAPI_Tools.cpp index a3a0df3b5..02f4e721f 100644 --- a/src/ModelAPI/ModelAPI_Tools.cpp +++ b/src/ModelAPI/ModelAPI_Tools.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -1025,6 +1026,30 @@ void copyVisualizationAttrs( } } + +void copyImageAttribute (std::shared_ptr theSource, + std::shared_ptr theDest) +{ + if (!theSource.get() || !theDest.get()) + return; + + // images allowed only for ResultBody + ResultBodyPtr aSourceBody = std::dynamic_pointer_cast(theSource); + ResultBodyPtr aDestBody = std::dynamic_pointer_cast(theDest); + if (!aSourceBody.get() || !aDestBody.get()) + return; + + AttributeImagePtr aSourceImage = + theSource->data()->image(ModelAPI_ResultBody::IMAGE_ID()); + if (aSourceImage.get() && aSourceImage->hasTexture()) { + AttributeImagePtr aDestImage = + theDest->data()->image(ModelAPI_ResultBody::IMAGE_ID()); + if (aDestImage.get()) { + aSourceImage->copyTo(aDestImage); + } + } +} + std::list referencedFeatures( std::shared_ptr theTarget, const std::string& theFeatureKind, const bool theSortResults) diff --git a/src/ModelAPI/ModelAPI_Tools.h b/src/ModelAPI/ModelAPI_Tools.h index 79d4f4a8b..bf49fe5df 100644 --- a/src/ModelAPI/ModelAPI_Tools.h +++ b/src/ModelAPI/ModelAPI_Tools.h @@ -294,6 +294,13 @@ MODELAPI_EXPORT void setTransparency(std::shared_ptr theResult, MODELAPI_EXPORT void copyVisualizationAttrs(std::shared_ptr theSource, std::shared_ptr theDest); +/*! Copies image attribute from one result to another. +* \param theSource a result that contains the image data +* \param theDest a destination result that takes the image data +*/ +MODELAPI_EXPORT void copyImageAttribute(std::shared_ptr theSource, + std::shared_ptr theDest); + /*! Produces list of features that reference to the given target (directly or through sub-results) * \param theTarget the referenced result * \param theFeatureKind the resulting features filter: the feature kind or all for the empty string diff --git a/src/ModelHighAPI/ModelHighAPI_Dumper.h b/src/ModelHighAPI/ModelHighAPI_Dumper.h index a75680380..f4dca43a2 100644 --- a/src/ModelHighAPI/ModelHighAPI_Dumper.h +++ b/src/ModelHighAPI/ModelHighAPI_Dumper.h @@ -169,6 +169,14 @@ public: MODELHIGHAPI_EXPORT bool process(const std::shared_ptr& theDoc, const std::string& theFileName); + /// Keep path to the true dumping directory. + /// It is used to store image files or any other external files + /// \param theDumpDir path to the true dumping directory + MODELHIGHAPI_EXPORT + void setDumpDir(const std::string& theDumpDir) { myDumpDir = theDumpDir; } + /// Return path to the true dumping directory + MODELHIGHAPI_EXPORT std::string getDumpDir() const { return myDumpDir; } + /// Add module to list of imported modules /// \param theModuleName name of the module to be imported MODELHIGHAPI_EXPORT @@ -455,6 +463,8 @@ private: std::list myPostponed; ///< list of postponed entities (sketch constraints or folders) bool myDumpPostponedInProgress; ///< processing postponed is in progress + std::string myDumpDir; + protected: /// list of entities, used by other features but not dumped yet std::set myNotDumpedEntities; diff --git a/src/ModelHighAPI/ModelHighAPI_FeatureStore.cpp b/src/ModelHighAPI/ModelHighAPI_FeatureStore.cpp index 330e61fe1..993defc44 100644 --- a/src/ModelHighAPI/ModelHighAPI_FeatureStore.cpp +++ b/src/ModelHighAPI/ModelHighAPI_FeatureStore.cpp @@ -241,7 +241,12 @@ std::string ModelHighAPI_FeatureStore::dumpAttr(const AttributePtr& theAttr) { } else if (aType == ModelAPI_AttributeString::typeId()) { AttributeStringPtr anAttr = std::dynamic_pointer_cast(theAttr); // do not dump solver DOF for sketch as it may be changed unexpectedly - if(anAttr->id() == "SolverDOF") { + if (anAttr->id() == "SolverDOF") { + return ""; + } + // do not dump file path for Image as it is changed after DumpPython + if (aFeatOwner->getKind() == "ImportImage" && + anAttr->id() == "file_path") { return ""; } aResult<value(); diff --git a/src/ModelHighAPI/ModelHighAPI_Tools.cpp b/src/ModelHighAPI/ModelHighAPI_Tools.cpp index 14ab98878..89f61b480 100644 --- a/src/ModelHighAPI/ModelHighAPI_Tools.cpp +++ b/src/ModelHighAPI/ModelHighAPI_Tools.cpp @@ -29,6 +29,8 @@ #include #include //-------------------------------------------------------------------------------------- +#include +//-------------------------------------------------------------------------------------- #include //-------------------------------------------------------------------------------------- #include @@ -529,6 +531,8 @@ static bool dumpToPython(SessionPtr theSession, if (aDump.get()) { aDump->string("file_path")->setValue(theFilename); aDump->string("file_format")->setValue("py"); + std::string aTrek = GeomAlgoAPI_Tools::File_Tools::path(theFilename); + aDump->string("dump_dir")->setValue(aTrek); aDump->boolean("topological_naming")->setValue((theSelectionType & CHECK_NAMING) != 0); aDump->boolean("geometric_selection")->setValue((theSelectionType & CHECK_GEOMETRICAL) != 0); aDump->boolean("weak_naming")->setValue((theSelectionType & CHECK_WEAK) != 0); diff --git a/src/PartSet/PartSet_CustomPrs.cpp b/src/PartSet/PartSet_CustomPrs.cpp index 05f8d9b72..3da462996 100644 --- a/src/PartSet/PartSet_CustomPrs.cpp +++ b/src/PartSet/PartSet_CustomPrs.cpp @@ -171,9 +171,8 @@ bool PartSet_CustomPrs::displayPresentation( isModified = true; } else { - if (myFeature->firstResult().get() && myFeature->firstResult()->hasTextureFile()) - { - PartSet_Module::setTexture( myFeature->firstResult()->getTextureFile(), aPresentation); + if (myFeature->firstResult().get()) { + PartSet_Module::setTexture(aPresentation, myFeature->firstResult()); } anOperationPrs->Redisplay(); isModified = true; diff --git a/src/PartSet/PartSet_Module.cpp b/src/PartSet/PartSet_Module.cpp index c648cc072..00893ab2f 100644 --- a/src/PartSet/PartSet_Module.cpp +++ b/src/PartSet/PartSet_Module.cpp @@ -82,6 +82,7 @@ #include #include #include +#include #include #include @@ -148,9 +149,6 @@ #include #include -#ifdef HAVE_SALOME -#include -#endif #define FEATURE_ITEM_COLOR "0,0,225" @@ -1406,13 +1404,46 @@ double getResultTransparency(const ResultPtr& theResult) return aTransparency; } +static AttributeImagePtr findImage(const ObjectPtr& theResult) +{ + AttributeImagePtr anImageAttr; + + if (theResult.get()) { + ResultBodyPtr aResultBody = + std::dynamic_pointer_cast(theResult); + if (aResultBody.get()) { + anImageAttr = aResultBody->data()->image(ModelAPI_ResultBody::IMAGE_ID()); + if (!anImageAttr.get() || !anImageAttr->hasTexture()) { + // try to find an image attribute in parents + ObjectPtr aParent = theResult->document()->parent(theResult); + anImageAttr = findImage(aParent); + } + } + } + + return anImageAttr; +} + //****************************************************** -void PartSet_Module::setTexture(const std::string & theTextureFile, const AISObjectPtr& thePrs) +void PartSet_Module::setTexture(const AISObjectPtr& thePrs, + const ResultPtr& theResult) { -#ifdef HAVE_SALOME + ResultBodyPtr aResultBody = + std::dynamic_pointer_cast(theResult); + if (!aResultBody.get()) + return; + + AttributeImagePtr anImageAttr = findImage(theResult); + if (!anImageAttr.get() || !anImageAttr->hasTexture()) + return; + + int aWidth, aHeight; + std::string aFormat; + std::list aByteList; + anImageAttr->texture(aWidth, aHeight, aByteList, aFormat); + Handle(AIS_InteractiveObject) anAIS = thePrs->impl(); - if (!anAIS.IsNull()) - { + if (!anAIS.IsNull()) { /// set color to white and change material aspect, /// in order to keep a natural apect of the image. thePrs->setColor(255, 255, 255); @@ -1429,11 +1460,21 @@ void PartSet_Module::setTexture(const std::string & theTextureFile, const AISObj myDrawer->ShadingAspect()->Aspect()->SetFrontMaterial(aMatAspect); myDrawer->ShadingAspect()->Aspect()->SetBackMaterial(aMatAspect); - Handle(Image_PixMap) aPixmap; - QPixmap px(theTextureFile.c_str()); - - if (!px.isNull() ) - aPixmap = OCCViewer_Utilities::imageToPixmap( px.toImage()); + //aPixmap = OCCViewer_Utilities::imageToPixmap( px.toImage()); + Handle(Image_PixMap) aPixmap = new Image_PixMap(); + aPixmap->InitTrash(Image_PixMap::ImgBGRA, aWidth, aHeight); + std::list::iterator aByteIter = aByteList.begin(); + for (int aLine = 0; aLine < aHeight; ++aLine) { + // convert pixels from ARGB to renderer-compatible RGBA + for (int aByte = 0; aByte < aWidth; ++aByte) { + Image_ColorBGRA& aPixmapBytes = aPixmap->ChangeValue(aLine, aByte); + + aPixmapBytes.b() = (Standard_Byte) *aByteIter++; + aPixmapBytes.g() = (Standard_Byte) *aByteIter++; + aPixmapBytes.r() = (Standard_Byte) *aByteIter++; + aPixmapBytes.a() = (Standard_Byte) *aByteIter++; + } + } anAISShape->Attributes()->ShadingAspect()->Aspect()->SetTextureMap (new Graphic3d_Texture2Dmanual(aPixmap)); @@ -1442,7 +1483,6 @@ void PartSet_Module::setTexture(const std::string & theTextureFile, const AISObj anAISShape->SetDisplayMode(AIS_Shaded); } } -#endif } //****************************************************** @@ -1487,10 +1527,8 @@ void PartSet_Module::customizePresentation(const ObjectPtr& theObject, thePrs->setDeflection(getResultDeflection(aResult)); thePrs->setTransparency(getResultTransparency(aResult)); - /// set texture parameters - if(aResult->hasTextureFile()) { - setTexture(aResult->getTextureFile(), thePrs); - } + /// set texture parameters, if any + setTexture(thePrs, aResult); } if (aFeature.get() && (aFeature->getKind() == SketchPlugin_Sketch::ID())) { thePrs->setWidth(2); diff --git a/src/PartSet/PartSet_Module.h b/src/PartSet/PartSet_Module.h index e47fabe9d..7a39b8998 100644 --- a/src/PartSet/PartSet_Module.h +++ b/src/PartSet/PartSet_Module.h @@ -400,7 +400,7 @@ public: virtual void createFeatures(); /// add texture - static void setTexture(const std::string &theTextureFile, const AISObjectPtr& thePrs); + static void setTexture(const AISObjectPtr& thePrs, const ResultPtr& theResult); public slots: /// Slolt called on object display diff --git a/src/SHAPERGUI/SHAPERGUI_DataModel.cpp b/src/SHAPERGUI/SHAPERGUI_DataModel.cpp index 989771917..17bbb19a9 100644 --- a/src/SHAPERGUI/SHAPERGUI_DataModel.cpp +++ b/src/SHAPERGUI/SHAPERGUI_DataModel.cpp @@ -184,6 +184,14 @@ bool SHAPERGUI_DataModel::dumpPython(const QString& thePath, CAM_Study* theStudy ModelAPI_Session::get()->startOperation(ExchangePlugin_Dump::ID()); FeaturePtr aFeature = aDoc->addFeature(ExchangePlugin_Dump::ID()); if (aFeature.get()) { + // keep path to the true dumping directory for external files dumping + AttributeStringPtr aAttr = aFeature->string(ExchangePlugin_Dump::DUMP_DIR_ID()); + if (aAttr.get()) { + QString aDirPath = QFileInfo(thePath).path(); + aAttr->setValue(aDirPath.toStdString()); + } + + // tmp path to write the script std::string aTmpDir = aStudy->GetTmpDir(thePath.toStdString().c_str(), isMultiFile); std::string aFileName = aTmpDir + DUMP_NAME; @@ -191,7 +199,7 @@ bool SHAPERGUI_DataModel::dumpPython(const QString& thePath, CAM_Study* theStudy QFile::remove(aFileName.c_str()); } - AttributeStringPtr aAttr = aFeature->string(ExchangePlugin_Dump::FILE_PATH_ID()); + aAttr = aFeature->string(ExchangePlugin_Dump::FILE_PATH_ID()); if (aAttr.get()) aAttr->setValue(aFileName); @@ -206,7 +214,7 @@ bool SHAPERGUI_DataModel::dumpPython(const QString& thePath, CAM_Study* theStudy ModelAPI_Session::get()->finishOperation(); if (QFile::exists(aFileName.c_str())) { - QFile aInFile(aFileName.c_str()); + QFile aInFile(aFileName.c_str()); if (!aInFile.open(QIODevice::ReadOnly | QIODevice::Text)) return false; QTextStream aText(&aInFile);