Commit 3a3aa930 authored by T.J. Corona's avatar T.J. Corona Committed by Kitware Robot

Merge topic 'mesh-ops'

30e30ea3 Update mesh visualization
a3f04ed8 Update mesh I/O operations.
Acked-by: Kitware Robot's avatarKitware Robot <kwrobot@kitware.com>
Acked-by: David Thompson's avatarDavid Thompson <david.thompson@kitware.com>
Merge-request: !1321
parents 0ae19c3b 30e30ea3
Pipeline #122752 canceled with stage
in 0 seconds
......@@ -45,9 +45,7 @@ vtkSmartPointer<vtkAlgorithm> SourceFromMesh::operator()(
// Create a vtkMeshMultiBlockSource for our mesh.
auto source = vtkSmartPointer<vtkMeshMultiBlockSource>::New();
// TODO: vtkMeshMultiBlockSource needs to update. Once that's done, we can set
// up <source> here.
source->SetMeshCollection(meshResource);
return source;
}
......
......@@ -90,7 +90,6 @@ int main(int argc, char* argv[])
vtkNew<vtkRenderer> ren;
vtkNew<vtkRenderWindow> win;
src->SetMeshCollection(c);
src->SetMeshCollectionID(collectionID.toString().c_str());
if (debug)
{
win->SetMultiSamples(16);
......
......@@ -54,7 +54,6 @@ int main(int argc, char* argv[])
vtkNew<vtkCompositePolyDataMapper2> map;
vtkNew<vtkRenderer> ren;
vtkNew<vtkRenderWindow> win;
src->SetMeshCollectionID(collectionID.toString().c_str());
if (debug)
{
win->SetMultiSamples(16);
......
......@@ -60,7 +60,6 @@ vtkMeshMultiBlockSource::vtkMeshMultiBlockSource()
this->SetNumberOfInputPorts(0);
this->CachedOutput = NULL;
this->ModelEntityID = NULL;
this->MeshCollectionID = NULL;
this->AllowNormalGeneration = 0;
this->linkInstance();
}
......@@ -70,7 +69,6 @@ vtkMeshMultiBlockSource::~vtkMeshMultiBlockSource()
this->unlinkInstance();
this->SetCachedOutput(NULL);
this->SetModelEntityID(NULL);
this->SetMeshCollectionID(NULL);
}
void vtkMeshMultiBlockSource::PrintSelf(ostream& os, vtkIndent indent)
......@@ -80,7 +78,6 @@ void vtkMeshMultiBlockSource::PrintSelf(ostream& os, vtkIndent indent)
os << indent << "Model: " << m_modelResource.get() << "\n";
os << indent << "CachedOutput: " << this->CachedOutput << "\n";
os << indent << "ModelEntityID: " << this->ModelEntityID << "\n";
os << indent << "MeshCollectionID: " << this->MeshCollectionID << "\n";
os << indent << "AllowNormalGeneration: " << (this->AllowNormalGeneration ? "ON" : "OFF") << "\n";
}
......@@ -288,102 +285,89 @@ void vtkMeshMultiBlockSource::FindEntitiesWithMesh(const smtk::mesh::CollectionP
void vtkMeshMultiBlockSource::GenerateRepresentationFromMesh(vtkMultiBlockDataSet* mbds)
{
if (this->MeshCollectionID && this->MeshCollectionID[0])
Model modelEntity;
bool modelRequiresNormals = false;
if (this->ModelEntityID && this->ModelEntityID[0] && m_modelResource)
{
smtk::common::UUID mcuid(this->MeshCollectionID);
smtk::common::UUID uid(this->ModelEntityID);
smtk::model::EntityRef entity(m_modelResource, uid);
modelEntity = entity.isModel() ? entity.as<smtk::model::Model>() : entity.owningModel();
}
Model modelEntity;
bool modelRequiresNormals = false;
if (this->ModelEntityID && this->ModelEntityID[0] && m_modelResource)
if (modelEntity.isValid() && m_meshCollection->isValid() &&
m_meshCollection->numberOfMeshes() > 0)
{
// See if the model has any instructions about
// whether to generate surface normals.
if (modelEntity.hasIntegerProperty("generate normals"))
{
smtk::common::UUID uid(this->ModelEntityID);
smtk::model::EntityRef entity(m_modelResource, uid);
modelEntity = entity.isModel() ? entity.as<smtk::model::Model>() : entity.owningModel();
const IntegerList& prop(modelEntity.integerProperty("generate normals"));
if (!prop.empty() && prop[0])
modelRequiresNormals = true;
}
if (modelEntity.isValid() && m_meshCollection->isValid() &&
m_meshCollection->numberOfMeshes() > 0)
// Map from entityref to its parent cell entity and its meshset
std::map<smtk::model::EntityRef, std::pair<smtk::model::EntityRef, smtk::mesh::MeshSet> >
entityrefMap;
std::set<smtk::model::EntityRef> touched; // make this go out of scope soon.
this->FindEntitiesWithMesh(m_meshCollection, modelEntity, entityrefMap, touched);
mbds->SetNumberOfBlocks(static_cast<unsigned>(entityrefMap.size()));
vtkIdType i;
std::map<smtk::model::EntityRef,
std::pair<smtk::model::EntityRef, smtk::mesh::MeshSet> >::iterator cit;
for (i = 0, cit = entityrefMap.begin(); cit != entityrefMap.end(); ++cit, ++i)
{
// See if the model has any instructions about
// whether to generate surface normals.
if (modelEntity.hasIntegerProperty("generate normals"))
vtkNew<vtkPolyData> poly;
mbds->SetBlock(i, poly.GetPointer());
// Set the block name to the entity UUID.
mbds->GetMetaData(i)->Set(vtkCompositeDataSet::NAME(), cit->first.name().c_str());
this->GenerateRepresentationForSingleMesh(
cit->second.second, poly.GetPointer(), cit->first, modelRequiresNormals);
// std::cout << "UUID: " << (*cit).entity().toString().c_str() << " Block: " << i << std::endl;
// as a convenient method to get the flat block index in multiblock
if (!(cit->first.entity().isNull()))
{
const IntegerList& prop(modelEntity.integerProperty("generate normals"));
if (!prop.empty() && prop[0])
modelRequiresNormals = true;
internal_AddBlockInfo(m_meshCollection, cit->first, cit->second.second, cit->second.first,
i, poly.GetPointer(), m_Meshset2BlockIdMap);
}
// Map from entityref to its parent cell entity and its meshset
std::map<smtk::model::EntityRef, std::pair<smtk::model::EntityRef, smtk::mesh::MeshSet> >
entityrefMap;
std::set<smtk::model::EntityRef> touched; // make this go out of scope soon.
this->FindEntitiesWithMesh(m_meshCollection, modelEntity, entityrefMap, touched);
mbds->SetNumberOfBlocks(static_cast<unsigned>(entityrefMap.size()));
vtkIdType i;
std::map<smtk::model::EntityRef,
std::pair<smtk::model::EntityRef, smtk::mesh::MeshSet> >::iterator cit;
for (i = 0, cit = entityrefMap.begin(); cit != entityrefMap.end(); ++cit, ++i)
{
vtkNew<vtkPolyData> poly;
mbds->SetBlock(i, poly.GetPointer());
// Set the block name to the entity UUID.
mbds->GetMetaData(i)->Set(vtkCompositeDataSet::NAME(), cit->first.name().c_str());
this->GenerateRepresentationForSingleMesh(
cit->second.second, poly.GetPointer(), cit->first, modelRequiresNormals);
// std::cout << "UUID: " << (*cit).entity().toString().c_str() << " Block: " << i << std::endl;
// as a convenient method to get the flat block index in multiblock
if (!(cit->first.entity().isNull()))
{
internal_AddBlockInfo(m_meshCollection, cit->first, cit->second.second, cit->second.first,
i, poly.GetPointer(), m_Meshset2BlockIdMap);
}
}
// TODO: how do we handle submodels in a multiblock dataset? We could have
// a cycle in the submodels, so treating them as trees would not work.
// Finally, if nothing has any tessellation information, see if any is associated
// with the model itself.
}
else
{
std::cout << "Can not find the model: "
<< (this->ModelEntityID ? this->ModelEntityID : "NULL")
<< ", use all meshes from mesh collection: " << this->MeshCollectionID << std::endl;
smtk::mesh::MeshSet allMeshes = m_meshCollection->meshes();
mbds->SetNumberOfBlocks(static_cast<unsigned>(allMeshes.size()));
// TODO: how do we handle submodels in a multiblock dataset? We could have
// a cycle in the submodels, so treating them as trees would not work.
// Finally, if nothing has any tessellation information, see if any is associated
// with the model itself.
}
else
{
smtk::mesh::MeshSet allMeshes = m_meshCollection->meshes();
mbds->SetNumberOfBlocks(static_cast<unsigned>(allMeshes.size()));
for (std::size_t i = 0; i < allMeshes.size(); ++i)
for (std::size_t i = 0; i < allMeshes.size(); ++i)
{
vtkNew<vtkPolyData> poly;
std::ostringstream defaultName;
defaultName << "mesh " << i;
smtk::mesh::MeshSet singleMesh = allMeshes.subset(i);
std::vector<std::string> meshNames = singleMesh.names();
std::string meshName = meshNames.size() > 0 ? meshNames[0] : defaultName.str();
// Set the block name to a mesh name if it has one.
// for now, use "mesh (<cell type>) <index>" for name
mbds->GetMetaData(static_cast<unsigned>(i))
->Set(vtkCompositeDataSet::NAME(), meshName.c_str());
this->GenerateRepresentationForSingleMesh(
singleMesh, poly.GetPointer(), smtk::model::EntityRef(), modelRequiresNormals);
mbds->SetBlock(static_cast<unsigned>(i), poly.GetPointer());
smtk::model::EntityRefArray ents;
bool validEnts = singleMesh.modelEntities(ents);
if (validEnts && ents.size() > 0)
{
vtkNew<vtkPolyData> poly;
std::ostringstream defaultName;
defaultName << "mesh " << i;
smtk::mesh::MeshSet singleMesh = allMeshes.subset(i);
std::vector<std::string> meshNames = singleMesh.names();
std::string meshName = meshNames.size() > 0 ? meshNames[0] : defaultName.str();
// Set the block name to a mesh name if it has one.
// for now, use "mesh (<cell type>) <index>" for name
mbds->GetMetaData(static_cast<unsigned>(i))
->Set(vtkCompositeDataSet::NAME(), meshName.c_str());
this->GenerateRepresentationForSingleMesh(
singleMesh, poly.GetPointer(), smtk::model::EntityRef(), modelRequiresNormals);
mbds->SetBlock(static_cast<unsigned>(i), poly.GetPointer());
smtk::model::EntityRefArray ents;
bool validEnts = singleMesh.modelEntities(ents);
if (validEnts && ents.size() > 0)
{
internal_AddBlockEntityInfo(
singleMesh, ents[0], i, poly.GetPointer(), m_Meshset2BlockIdMap);
}
internal_AddBlockEntityInfo(
singleMesh, ents[0], i, poly.GetPointer(), m_Meshset2BlockIdMap);
}
}
}
else
{
vtkGenericWarningMacro(<< "A valid mesh collection id was not set, abort!");
}
}
/// Generate polydata from an smtk::model with tessellation information.
......
......@@ -53,11 +53,6 @@ public:
smtk::mesh::CollectionPtr GetMeshCollection();
void SetMeshCollection(smtk::mesh::CollectionPtr);
// Description:
// Mesh collection ID that this source will be built upon.
vtkSetStringMacro(MeshCollectionID);
vtkGetStringMacro(MeshCollectionID);
void GetMeshSet2BlockIdMap(std::map<smtk::mesh::MeshSet, vtkIdType>& mesh2block);
void Dirty();
......@@ -92,8 +87,7 @@ protected:
vtkNew<vtkPolyDataNormals> m_normalGenerator;
vtkMultiBlockDataSet* CachedOutput;
char* ModelEntityID; // Model Entity UUID
char* MeshCollectionID; // Model Entity UUID
char* ModelEntityID; // Model Entity UUID
int AllowNormalGeneration;
private:
......
......@@ -41,11 +41,13 @@ set(meshSrcs
operators/DeleteMesh.cxx
operators/ElevateMesh.cxx
operators/ExportMesh.cxx
operators/Export.cxx
operators/GenerateHotStartData.cxx
operators/Import.cxx
operators/InterpolateOntoMesh.cxx
operators/Read.cxx
operators/UndoElevateMesh.cxx
operators/WriteMesh.cxx
operators/Write.cxx
resource/Registrar.cxx
......@@ -96,11 +98,13 @@ set(meshHeaders
operators/DeleteMesh.h
operators/ElevateMesh.h
operators/ExportMesh.h
operators/Export.h
operators/GenerateHotStartData.h
operators/Import.h
operators/InterpolateOntoMesh.h
operators/Read.h
operators/UndoElevateMesh.h
operators/WriteMesh.h
operators/Write.h
resource/PropertyData.h
resource/Registrar.h
......@@ -115,11 +119,13 @@ set(meshHeaders
smtk_operation_xml("${CMAKE_CURRENT_SOURCE_DIR}/operators/DeleteMesh.sbt" defOpXML)
smtk_operation_xml("${CMAKE_CURRENT_SOURCE_DIR}/operators/ElevateMesh.sbt" defOpXML)
smtk_operation_xml("${CMAKE_CURRENT_SOURCE_DIR}/operators/ExportMesh.sbt" defOpXML)
smtk_operation_xml("${CMAKE_CURRENT_SOURCE_DIR}/operators/Export.sbt" defOpXML)
smtk_operation_xml("${CMAKE_CURRENT_SOURCE_DIR}/operators/GenerateHotStartData.sbt" defOpXML)
smtk_operation_xml("${CMAKE_CURRENT_SOURCE_DIR}/operators/Import.sbt" defOpXML)
smtk_operation_xml("${CMAKE_CURRENT_SOURCE_DIR}/operators/InterpolateOntoMesh.sbt" defOpXML)
smtk_operation_xml("${CMAKE_CURRENT_SOURCE_DIR}/operators/Read.sbt" defOpXML)
smtk_operation_xml("${CMAKE_CURRENT_SOURCE_DIR}/operators/UndoElevateMesh.sbt" defOpXML)
smtk_operation_xml("${CMAKE_CURRENT_SOURCE_DIR}/operators/WriteMesh.sbt" defOpXML)
smtk_operation_xml("${CMAKE_CURRENT_SOURCE_DIR}/operators/Write.sbt" defOpXML)
#install the headers
smtk_public_headers(smtkCore ${meshHeaders})
......
......@@ -8,17 +8,21 @@
// PURPOSE. See the above copyright notice for more information.
//=========================================================================
#include "smtk/mesh/operators/ExportMesh.h"
#include "smtk/mesh/operators/Export.h"
#include "smtk/attribute/Attribute.h"
#include "smtk/attribute/ComponentItem.h"
#include "smtk/attribute/Definition.h"
#include "smtk/attribute/FileItem.h"
#include "smtk/attribute/MeshItem.h"
#include "smtk/attribute/FileItemDefinition.h"
#include "smtk/attribute/Resource.h"
#include "smtk/attribute/ResourceItem.h"
#include "smtk/attribute/StringItem.h"
#include "smtk/io/ExportMesh.h"
#include "smtk/io/mesh/MeshIO.h"
#include "smtk/mesh/ExportMesh_xml.h"
#include "smtk/mesh/Export_xml.h"
#include "smtk/mesh/core/Collection.h"
#include "smtk/mesh/core/Component.h"
#include "smtk/mesh/core/MeshSet.h"
......@@ -53,7 +57,7 @@ namespace smtk
namespace mesh
{
bool ExportMesh::ableToOperate()
bool Export::ableToOperate()
{
if (!this->Superclass::ableToOperate())
{
......@@ -62,7 +66,7 @@ bool ExportMesh::ableToOperate()
return true;
}
ExportMesh::Result ExportMesh::operateInternal()
Export::Result Export::operateInternal()
{
std::string outputfile = this->parameters()->findFile("filename")->value();
......@@ -114,9 +118,60 @@ ExportMesh::Result ExportMesh::operateInternal()
return this->createResult(smtk::operation::Operation::Outcome::SUCCEEDED);
}
const char* ExportMesh::xmlDescription() const
Export::Specification Export::createSpecification()
{
return ExportMesh_xml;
Specification spec = this->smtk::operation::XMLOperation::createSpecification();
auto exportDef = spec->findDefinition("export");
std::vector<smtk::attribute::FileItemDefinition::Ptr> fileItemDefinitions;
auto fileItemDefinitionFilter = [](
smtk::attribute::FileItemDefinition::Ptr ptr) { return ptr->name() == "filename"; };
exportDef->filterItemDefinitions(fileItemDefinitions, fileItemDefinitionFilter);
assert(fileItemDefinitions.size() == 1);
std::stringstream fileFilters;
for (auto& ioType : smtk::io::ExportMesh::SupportedIOTypes())
{
bool firstFormat = true;
for (auto& format : ioType->FileFormats())
{
if (format.CanExport())
{
if (firstFormat)
{
firstFormat = false;
}
else
{
fileFilters << ";;";
}
fileFilters << format.Name << "(";
bool first = true;
for (auto& ext : format.Extensions)
{
if (first)
{
first = false;
}
else
{
fileFilters << " ";
}
fileFilters << "*" << ext;
}
fileFilters << ")";
}
}
}
fileItemDefinitions[0]->setFileFilters(fileFilters.str());
return spec;
}
const char* Export::xmlDescription() const
{
return Export_xml;
}
}
}
......@@ -7,8 +7,8 @@
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//=========================================================================
#ifndef __smtk_mesh_WriteMesh_h
#define __smtk_mesh_WriteMesh_h
#ifndef __smtk_mesh_Export_h
#define __smtk_mesh_Export_h
#include "smtk/operation/XMLOperation.h"
......@@ -19,11 +19,11 @@ namespace mesh
/**\brief A class for writing meshes to file.
*/
class SMTKCORE_EXPORT WriteMesh : public smtk::operation::XMLOperation
class SMTKCORE_EXPORT Export : public smtk::operation::XMLOperation
{
public:
smtkTypeMacro(smtk::mesh::WriteMesh);
smtkCreateMacro(WriteMesh);
smtkTypeMacro(smtk::mesh::Export);
smtkCreateMacro(Export);
smtkSharedFromThisMacro(smtk::operation::Operation);
smtkSuperclassMacro(smtk::operation::XMLOperation);
......@@ -31,10 +31,11 @@ public:
protected:
Result operateInternal() override;
Specification createSpecification() override;
virtual const char* xmlDescription() const override;
};
} // mesh namespace
} // smtk namespace
#endif // __smtk_mesh_WriteMesh_h
#endif // __smtk_mesh_Export_h
......@@ -3,7 +3,7 @@
<Definitions>
<!-- Operation -->
<include href="smtk/operation/Operation.xml"/>
<AttDef Type="export mesh" Label="Mesh - Export" BaseType="operation">
<AttDef Type="export" Label="Mesh - Export" BaseType="operation">
<BriefDescription>
Export a mesh to disk.
</BriefDescription>
......@@ -20,13 +20,13 @@
</AssociationsDef>
<ItemDefinitions>
<File Name="filename" NumberOfRequiredValues="1" ShouldExist="false"
FileFilters="AdH 2D Mesh file (*.2dm);;AdH 3D Mesh file (*.3dm)">
FileFilters="[defined programatically]">
</File>
</ItemDefinitions>
</AttDef>
<!-- Result -->
<include href="smtk/operation/Result.xml"/>
<AttDef Type="result(export mesh)" BaseType="result">
<AttDef Type="result(export)" BaseType="result">
</AttDef>
</Definitions>
</SMTK_AttributeResource>
//=========================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//=========================================================================
#include "smtk/mesh/operators/Import.h"
#include "smtk/attribute/Attribute.h"
#include "smtk/attribute/ComponentItem.h"
#include "smtk/attribute/Definition.h"
#include "smtk/attribute/FileItem.h"
#include "smtk/attribute/FileItemDefinition.h"
#include "smtk/attribute/IntItem.h"
#include "smtk/attribute/Resource.h"
#include "smtk/attribute/ResourceItem.h"
#include "smtk/attribute/StringItem.h"
#include "smtk/io/ImportMesh.h"
#include "smtk/mesh/core/Collection.h"
#include "smtk/mesh/core/Component.h"
#include "smtk/mesh/Import_xml.h"
namespace
{
class AddMeshToResult : public smtk::mesh::MeshForEach
{
public:
AddMeshToResult(smtk::mesh::Import::Result& result)
: smtk::mesh::MeshForEach()
, m_result(result)
{
}
void forMesh(smtk::mesh::MeshSet& mesh) override
{
m_result->findComponent("created")->appendValue(smtk::mesh::Component::create(mesh));
}
private:
smtk::mesh::Import::Result& m_result;
};
}
namespace smtk
{
namespace mesh
{
Import::Result Import::operateInternal()
{
// Get the import file name
smtk::attribute::FileItem::Ptr filePathItem = this->parameters()->findFile("filename");
std::string filePath = filePathItem->value();
// Get the subset value
smtk::attribute::StringItem::Ptr labelItem = this->parameters()->findString("label");
std::string label = labelItem->value();
auto collection = smtk::mesh::Collection::create();
bool success = smtk::io::importMesh(filePath, collection, label);
if (success == false)
{
return this->createResult(smtk::operation::Operation::Outcome::FAILED);
}
auto result = this->createResult(smtk::operation::Operation::Outcome::SUCCEEDED);
AddMeshToResult addMeshToResult(result);
smtk::mesh::for_each(collection->meshes(), addMeshToResult);
result->findResource("resource")->appendValue(collection);
return result;
}
Import::Specification Import::createSpecification()
{
Specification spec = this->smtk::operation::XMLOperation::createSpecification();
auto importDef = spec->findDefinition("import");
std::vector<smtk::attribute::FileItemDefinition::Ptr> fileItemDefinitions;
auto fileItemDefinitionFilter = [](
smtk::attribute::FileItemDefinition::Ptr ptr) { return ptr->name() == "filename"; };
importDef->filterItemDefinitions(fileItemDefinitions, fileItemDefinitionFilter);
assert(fileItemDefinitions.size() == 1);
std::stringstream fileFilters;
for (auto& ioType : smtk::io::ImportMesh::SupportedIOTypes())
{
bool firstFormat = true;
for (auto& format : ioType->FileFormats())
{
if (format.CanImport())
{
if (firstFormat)
{
firstFormat = false;
}
else
{
fileFilters << ";;";
}
fileFilters << format.Name << "(";
bool first = true;
for (auto& ext : format.Extensions)
{
if (first)
{
first = false;
}
else
{
fileFilters << " ";
}
fileFilters << "*" << ext;
}
fileFilters << ")";
}
}
}
fileItemDefinitions[0]->setFileFilters(fileFilters.str());
return spec;
}
const char* Import::xmlDescription() const
{
return Import_xml;
}
}
}
//=========================================================================
// Copyright (c) Kitware, Inc.
// All rights reserved.
// See LICENSE.txt for details.
//
// This software is distributed WITHOUT ANY WARRANTY; without even
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the above copyright notice for more information.
//=========================================================================
#ifndef __smtk_mesh_Import_h
#define __smtk_mesh_Import_h
#include "smtk/session/mesh/Exports.h"