Commit f909bb60 authored by David Thompson's avatar David Thompson
Browse files

Progress on a polygonal modeler.

New Modeling Kernel
-------------------

This commit adds a new modeling kernel based on
[Boost.polygon](http://www.boost.org/doc/libs/1_58_0/libs/polygon/doc/index.htm).
It currently supports a very limited set of operations:

+ Creation a model.
+ Creation of model vertices.
+ Creation of model edges.

Internally, an edge split operation is provided but not yet exposed.

Miscellany
----------

+ Fix a bug in attribute association.
  Because model entity items in attributes may have a membership mask,
  calling `setValue()` does not guarantee that the association will
  occur. Return the proper boolean or infinite recursion will occur
  inside `Attribute::associateEntity()`.
+ Add a Python-callable variant of ImportJSON::ofLog.
+ Have `smtk.simple` hang on to operator results so that scripts can access them if they need to.
+ Fix error log printout in `smtk.simple` API.
+ Have python test `addToScene()` method return pipeline objects.
parent d5a3fb6a
......@@ -106,6 +106,7 @@ option(SMTK_ENABLE_PARAVIEW_SUPPORT "Build paraview plugins for model sessions"
option(SMTK_ENABLE_CGM_SESSION "Build CGM component" OFF)
option(SMTK_ENABLE_DISCRETE_SESSION "Build discrete model session components" OFF)
option(SMTK_ENABLE_POLYGON_SESSION "Build Boost.polygon model session." ON)
if (SMTK_ENABLE_VTK_SUPPORT)
option(SMTK_ENABLE_EXODUS_SESSION "Build a session to Exodus-II side sets" ON)
endif()
......
......@@ -15,3 +15,7 @@ that may each interact with different solid modeling kernels.
sessions.rst
property-names.rst
user-interface.rst
session-cgm.rst
session-discrete.rst
session-exodus.rst
session-polygon.rst
Session: CGM
------------
SMTK has a *CGM* session type that bridges the `Common Geometry Model (CGM) <CGM>`_ meta-modeling kernel.
Depending on how your CGM library is compiled, it provides access to the ACIS and/or OpenCascade CAD kernels,
which are parametric modeling kernels that provide a full boundary-representation topology.
CGM also includes a discrete modeling kernel of its own focused on 3-dimensional polyhedral solid models.
While multiple CAD kernels may be used in the same CGM session, this is not the usual case.
.. todo:: The CGM session provides 2 "static" settings controlling the accuracy of model entity tessellations.
.. todo:: Starting CGM with a different Engine
.. todo:: CGM engines and file types
.. _CGM: http://sigma.mcs.anl.gov/cgm-library/
Session: Discrete
-----------------
SMTK has a session type named *discrete* that bridges a VTK-based discrete modeling kernel.
This kernel provides access to 2-D and 3-D polygonal and polyhedral models,
with operators that allow model edges and faces to be split or merged.
Models need not include a full topology (e.g., only volumes and faces may be represented,
with edges implied; or geometric entities may be modeled but not all of their oriented use-records).
However, several operations such as "*create edges"* exist to generate a full topology from
a self-consistent but incomplete model.
Session: Exodus
---------------
SMTK has a session type named *exodus* that is not technically a modeling kernel
but does allow you to mark up meshes saved in the Exodus-II_ file format for use
in an existing simulation — assuming that element blocks and side sets that
segregate the model into one or more regions per material and one or more
groups per boundary-condition are already present in the exodus mesh.
.. todo:: Describe what blocks and sets are
.. todo:: Describe how blocks and sets are mapped to models and groups
.. todo:: Show simple example?
.. _Exodus-II: http://exodusii.sf.net/
Session: Polygon
----------------
SMTK has a session type named *polygon* that bridges Boost.polygon_'s modeling kernel.
This kernel provides access to 2-D polygonal models,
with operators that allow model edges and faces to be split or merged
as well as boolean operations and Voronoi diagram computation.
Boost's polygonal modeler uses integer arithmetic to achieve high performance
with robust geometric predicates.
SMTK converts 3-D floating-point coordinates into 2-D integer coordinates for you,
but you must provide several pieces of information for each model instance:
* A base point for the plane holding the polygon
* Either x- and y-axis vectors (in 3-D world coordinates) describing the planar
coordinate system you wish to use, or an x-axis and the plane's normal vector.
* Either a minimum feature size (in world coordinates) that your model should
represent or an integer model scaling factor that each world coordinate is
multiplied by before rounding to an integer.
This session does not allow model edges to have more than 2 model vertices.
A model edge may have zero or one vertices when the edge is a periodic loop denoted
with identical first and last points; in this case, the first and last
point must also be the model vertex.
A model edge must have two model vertices when it is not periodic, one at each
end of the edge.
Model edges may have any number of interior points that are not model vertices.
These restrictions are imposed so that it is possible to quickly determine what
model face lies adjacent to each model vertex.
If model edges could have interior vertices,
the assumption that each edge may border at most 2 faces
would be much more difficult to enforce and validate.
This decision regarding model vertices and edges has further implications.
Edges may not have any self-intersections other than at points where segments meet.
When edges are joined into loops to form a face,
they are intersected with one another first;
if any intersections are found, then the model edges are split when
the face is created.
Note that SMTK is slightly more restrictive (in that it splits edges and
creates model vertices) than Boost requires because Boost does not model
edges at all; instead it models polygons as sequences of points –
optionally with a list of holes which are themselves polygons.
In Boost's modeler, points are not shared between faces;
each face is a model in its own right.
Because of this, it is simple for Boost to use *keyholed edges* to
represent holes in faces.
Keyholed edges are edges coincident along a portion of their length
and effectively split a face with holes into a face with no holes but
with infinitesimal slivers connecting the region outside the face to
each hole.
SMTK can accept keyholed edges but they must be broken into multiple
model edges at intersections so that SMTK's assumption that planar edges
border at most 2 different surface regions.
Meshing Boost.polygon models
============================
Boost polygonal models are conforming piecewise-linear cell complexes (PLCs), and
may thus be meshed by any SMTK mesh worker that accepts models in this form.
.. _Boost.polygon: http://www.boost.org/doc/libs/1_59_0/libs/polygon/doc/index.htm
......@@ -141,6 +141,7 @@ namespace smtk
typedef std::vector<smtk::model::UseEntity> UseEntities;
class Vertex;
typedef std::vector<smtk::model::Vertex> Vertices;
typedef std::set<smtk::model::Vertex> VertexSet;
class VertexUse;
typedef std::vector<smtk::model::VertexUse> VertexUses;
class Volume;
......@@ -176,6 +177,7 @@ namespace smtk
class ExportJSON;
class ImportJSON;
class OperatorLog;
class Logger;
}
namespace common
......
......@@ -146,8 +146,7 @@ bool ModelEntityItem::appendValue(const smtk::model::EntityRef& val)
{
if (!this->isSet(i))
{
this->setValue(i, val);
return true;
return this->setValue(i, val);
}
}
// Second - are we allowed to change the number of values?
......
......@@ -12,6 +12,17 @@ if(SMTK_ENABLE_DISCRETE_SESSION)
add_subdirectory(discrete)
endif()
################################################################################
# Build Boost.Polygon session
################################################################################
if (SMTK_ENABLE_POLYGON_SESSION)
if (${Boost_MAJOR_VERSION} LESS 2 AND ${Boost_MINOR_VERSION} LESS 52)
message(FATAL_ERROR
"Polygon session requires Boost 1.52 or newer, found ${Boost_VERSION}")
endif()
add_subdirectory(polygon)
endif()
################################################################################
# Build Exodus-II session
################################################################################
......
set(polygonSrcs
Session.cxx
Operator.cxx
internal/Model.cxx
internal/Vertex.cxx
operators/CreateModel.cxx
operators/CreateVertices.cxx
operators/CreateEdge.cxx
operators/CreateFaces.cxx
operators/SplitEdge.cxx
)
set(polygonHeaders
Session.h
Operator.h
internal/Model.h
operators/CreateModel.h
operators/CreateVertices.h
operators/CreateEdge.h
operators/CreateFaces.h
operators/SplitEdge.h
)
smtk_session_json("${CMAKE_CURRENT_SOURCE_DIR}/Session.json" polygonSessionJSON)
smtk_operator_xml("${CMAKE_CURRENT_SOURCE_DIR}/operators/CreateModel.sbt" polygonOperatorXML)
smtk_operator_xml("${CMAKE_CURRENT_SOURCE_DIR}/operators/CreateVertices.sbt" polygonOperatorXML)
smtk_operator_xml("${CMAKE_CURRENT_SOURCE_DIR}/operators/CreateEdge.sbt" polygonOperatorXML)
smtk_operator_xml("${CMAKE_CURRENT_SOURCE_DIR}/operators/CreateFaces.sbt" polygonOperatorXML)
smtk_operator_xml("${CMAKE_CURRENT_SOURCE_DIR}/operators/SplitEdge.sbt" polygonOperatorXML)
add_library(smtkPolygonSession ${polygonSrcs})
target_link_libraries(smtkPolygonSession
LINK_PUBLIC
smtkCore
)
smtk_export_header(smtkPolygonSession Exports.h)
# On Mac OS X, set the directory included as part of the installed library's path:
if (BUILD_SHARED_LIBS)
set_target_properties(smtkPolygonSession PROPERTIES INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/lib")
endif()
# Install the library and exports the library when used from a build tree
smtk_install_library(smtkPolygonSession)
# Install the headers
smtk_public_headers(${polygonHeaders})
install(FILES PointerDefs.h DESTINATION include/smtk/${SMTK_VERSION}/smtk/bridge/polygon)
target_include_directories(smtkPolygonSession
PUBLIC
$<BUILD_INTERFACE:${SMTK_SOURCE_DIR}/smtk/bridge/discrete/extension/meshing>
)
if(SMTK_ENABLE_PYTHON_WRAPPING AND Shiboken_FOUND)
# Extract the headers from polygon library we built to give them to shiboken
sbk_wrap_library(smtkPolygonSession
GENERATOR_ARGS --avoid-protected-hack
WORKING_DIRECTORY ${SMTK_SOURCE_DIR}/smtk
LOCAL_INCLUDE_DIRECTORIES
${SMTK_SOURCE_DIR}/smtk/common
${SMTK_SOURCE_DIR}/smtk/attribute
${SMTK_SOURCE_DIR}/smtk/model
${SMTK_SOURCE_DIR}/smtk/session
${SMTK_SOURCE_DIR}/smtk/bridge/polygon
${SMTK_SOURCE_DIR}/smtk/simulation
${SMTK_SOURCE_DIR}/smtk/io
${SMTK_SOURCE_DIR}/smtk/view
${SMTK_SOURCE_DIR}/smtk
${SMTK_BINARY_DIR}/smtk
${CMAKE_CURRENT_BINARY_DIR}
TYPESYSTEM ${CMAKE_CURRENT_SOURCE_DIR}/typesystem.xml
HEADERS ${polygonHeaders}
DEPENDS smtkCore
)
endif()
if(SMTK_ENABLE_PARAVIEW_SUPPORT)
add_subdirectory(plugin)
endif()
if (SMTK_ENABLE_TESTING)
add_subdirectory(testing)
endif()
//=========================================================================
// 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/bridge/polygon/Operator.h"
#include "smtk/bridge/polygon/Session.h"
#include "smtk/model/EntityRef.h"
namespace smtk {
namespace bridge {
namespace polygon {
/// Return a shared pointer to the session backing a polygon operator.
Session* Operator::polygonSession()
{
return dynamic_cast<smtk::bridge::polygon::Session*>(this->session());
}
/*
/// A helper to return the polygon entity associated with \a smtkEntity.
internal::Entity* Operator::polygonEntity(const smtk::model::EntityRef& smtkEntity)
{
ToolDataUser* tdu = TDUUID::findEntityById(smtkEntity.entity());
RefEntity* ent = dynamic_cast<RefEntity*>(tdu);
return ent;
}
*/
} // namespace polygon
} //namespace bridge
} // namespace smtk
//=========================================================================
// 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_session_polygon_Operator_h
#define __smtk_session_polygon_Operator_h
#include "smtk/bridge/polygon/Exports.h"
#include "smtk/model/Operator.h"
#include "smtk/model/Manager.h"
namespace smtk {
namespace bridge {
namespace polygon {
class Session;
/**\brief An operator using the polygon kernel.
*
* This is a base class for actual polygon operators.
* It provides convenience methods for accessing polygon-specific data
* for its subclasses to use internally.
*/
class SMTKPOLYGONSESSION_EXPORT Operator : public smtk::model::Operator
{
protected:
Session* polygonSession();
/*
internal::Entity* polygonEntity(const smtk::model::EntityRef& smtkEntity);
template<typename T>
T polygonEntityAs(const smtk::model::EntityRef& smtkEntity);
*/
};
/*
/// A convenience method for returning the polygon counterpart of an SMTK entity already cast to a subtype.
template<typename T>
T Operator::polygonEntityAs(const smtk::model::EntityRef& smtkEntity)
{
return dynamic_cast<T>(this->polygonEntity(smtkEntity));
}
*/
} // namespace polygon
} // namespace bridge
} // namespace smtk
#endif // __smtk_session_polygon_Operator_h
//=============================================================================
// 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_session_polygon_PointerDefs_h
#define __smtk_session_polygon_PointerDefs_h
#include "smtk/SharedPtr.h"
#include "smtk/SystemConfig.h"
namespace smtk {
namespace bridge {
namespace polygon {
class Session;
typedef smtk::shared_ptr< smtk::bridge::polygon::Session > SessionPtr;
} // namespace polygon
} // namespace bridge
} // namespace smtk
#endif // __smtk_session_polygon_PointerDefs_h
//=========================================================================
// 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/bridge/polygon/Session.h"
#include "smtk/AutoInit.h"
#include "smtk/model/EntityRef.h"
#include "smtk/model/SessionRef.h"
#include "smtk/model/Model.h"
#include "smtk/model/Group.h"
#include "smtk/model/VolumeUse.h"
#include "smtk/model/FaceUse.h"
#include "smtk/model/EdgeUse.h"
#include "smtk/model/VertexUse.h"
#include "smtk/model/Volume.h"
#include "smtk/model/Face.h"
#include "smtk/model/Edge.h"
#include "smtk/model/Vertex.h"
#include "smtk/model/Manager.h"
#include "smtk/model/Shell.h"
#include "smtk/model/Chain.h"
#include "smtk/model/Loop.h"
#include "smtk/common/UUID.h"
#include "smtk/Options.h"
#include "smtk/AutoInit.h"
#include "smtk/bridge/polygon/internal/Model.h"
#include <string.h> // for strcmp
using smtk::model::EntityRef;
using namespace smtk::common;
namespace smtk {
namespace bridge {
namespace polygon {
/// Default constructor.
Session::Session()
{
this->initializeOperatorSystem(Session::s_operators);
}
/// Virtual destructor. Here because Session overrides virtual methods from Session.
Session::~Session()
{
}
/// The polygon session supports smtk::model::SESSION_EVERYTHING.
smtk::model::SessionInfoBits Session::allSupportedInformation() const
{
return smtk::model::SESSION_EVERYTHING;
}
smtk::model::SessionInfoBits Session::transcribeInternal(
const smtk::model::EntityRef& entity,
smtk::model::SessionInfoBits requestedInfo,
int depth)
{
(void)entity;
(void)requestedInfo;
(void)depth;
return smtk::model::SESSION_EVERYTHING;
}
void Session::addStorage(
const smtk::common::UUID& uid,
smtk::bridge::polygon::internal::entity::Ptr s)
{
this->m_storage[uid] = s;
}
bool Session::removeStorage(const smtk::common::UUID& uid)
{
return this->m_storage.erase(uid) > 0;
}
} // namespace polygon
} //namespace bridge
} // namespace smtk
#include "smtk/bridge/polygon/Session_json.h" // For Session_json
smtkImplementsModelingKernel(
SMTKPOLYGONSESSION_EXPORT,
polygon,
Session_json,
smtk::model::SessionHasNoStaticSetup,
smtk::bridge::polygon::Session,
true /* inherit "universal" operators */
);
smtkComponentInitMacro(smtk_polygon_create_model_operator);
//=========================================================================
// 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_session_polygon_Session_h
#define __smtk_session_polygon_Session_h
#include "smtk/bridge/polygon/Exports.h"
#include "smtk/bridge/polygon/PointerDefs.h"
#include "smtk/bridge/polygon/internal/Entity.h"
#include "smtk/model/Session.h"
namespace smtk {
namespace bridge {
namespace polygon {
namespace internal {
class pmodel;
class vertex;
}
/**\brief Methods that handle translation between polygon and SMTK instances.
*
* While the TDUUID class keeps a map from SMTK UUIDs to polygon ToolDataUser
* pointers, this is not enough to handle everything SMTK provides:
* there is no way to track cell-use or shell entities since they do
* not inherit ToolDataUser instances. Also, some engines (e.g., facet)
* do not appear to store some entity types (e.g., RefGroup).
*
* Also, simply loading a polygon file does not translate the entire model
* into SMTK; instead, it assigns UUIDs to entities if they do not already
* exist. This class (Session) provides a method for requesting the
* entity, arrangement, and/or tessellation information for a UUID be
* mapped into SMTK from polygon.
*/
class SMTKPOLYGONSESSION_EXPORT Session : public smtk::model::Session
{
public:
smtkTypeMacro(Session);
smtkSuperclassMacro(smtk::model::Session);
smtkSharedFromThisMacro(smtk::model::Session);
smtkCreateMacro(smtk::model::Session);
smtkDeclareModelingKernel();
typedef smtk::model::SessionInfoBits SessionInfoBits;
virtual ~Session();
virtual SessionInfoBits allSupportedInformation() const;
protected:
friend class Operator;
friend class CreateModel;
friend class CreateVertices;
friend class CreateEdge;
friend class SplitEdge;
friend class internal::pmodel;
Session();
virtual smtk::model::SessionInfoBits transcribeInternal(
const smtk::model::EntityRef& entity, SessionInfoBits requestedInfo, int depth = -1);
void addStorage(const smtk::common::UUID& uid, smtk::bridge::polygon::internal::entity::Ptr storage);
bool removeStorage(const smtk::common::UUID& uid);
template<typename T>
typename T::Ptr findStorage(const smtk::common::UUID& uid)
{
internal::EntityIdToPtr::iterator it = this->m_storage.find(uid);
if (it != this->m_storage.end())
return smtk::dynamic_pointer_cast<T>(it->second);
static typename T::Ptr blank;
return blank;
}
template<typename T>
T findOrAddStorage(const smtk::common::UUID& uid)
{
internal::EntityIdToPtr::iterator it = this->m_storage.find(uid);
if (it != this->m_storage.end())
return smtk::dynamic_pointer_cast<T>(it->second);
T blank = T::create();
it = this->m_storage.insert(
internal::EntityIdToPtr::value_type(
uid,smtk::dynamic_pointer_cast<internal::entity>(blank))).first;
return smtk::dynamic_pointer_cast<T>(it->second);
}
internal::EntityIdToPtr m_storage;
private:
Session(const Session&); // Not implemented.
void operator = (const Session&); // Not implemented.
};
} // namespace polygon
} //namespace bridge
} // namespace smtk
#endif // __smtk_session_polygon_Session_h
{
"kernel": "polygon",
"engines": [
{
"name": "native",
"filetypes": [
".poly (Triangle polygon file)",
".smesh (Surface mesh)"
]
}
]
}
//=============================================================================
// 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_bridge_polygon_internal_bpConfig_h
#define __smtk_bridge_polygon_internal_bpConfig_h
#ifndef SHIBOKEN_SKIP
#include "smtk/SharedPtr.h"
#include "smtk/common/UUID.h"