...

Commits (3)
This diff is collapsed.
 ... ... @@ -75,22 +75,108 @@ Two-dimensional systems Depending on the selected dimensionality of the input simulation cell, the atomic strain calculation is either performed in 2D or 3D mode. In 3D mode, all 9 components of the atomic deformation gradient tensor are calculated from the relative motion vectors of neighboring particles using a least-squares fit. In 2D mode, only 4 independent components are calculated: 3D mode 2D mode Deformation gradient F Fxx Fxy Fxz Fyx Fyy Fyz Fzx Fzy Fzz Fxx Fxy 0 Fyx Fyy 0 0 0 1 More on the micromechanical quantities The atomic strain calculation uses finite-strain theory. Accordingly, strain is measured using the The atomic strain calculation in OVITO is based on finite-strain theory. Accordingly, strain is measured using the Green-Lagrangian strain tensor E=1/2(FTF-I). On the basis of this symmetric strain tensor, the modifier also calculates the von Mises local shear invariant and the volumetric (hydrostatic) part of the strain tensor and outputs these scalar quantities as particle properties named Shear Strain and Volumetric Strain, respectively. The former is a good measure for shear deformations in arbitrary directions. along arbitrary directions. 3D mode 2D mode Shear strain [Exy2 + Exz2 + Eyz2 + 1/6 ((Exx - Eyy)2 + (Exx - Ezz)2 + (Eyy - Ezz)2)] 1/2 [Exy2 + 1/2 (Exx - Eyy)2] 1/2 Volumetric strain (Exx + Eyy + Ezz) / 3 (Exx + Eyy) / 2 The deformation gradient and the strain tensor both can only describe material deformations that are locally affine. In fact, the atomic deformation gradient tensor is computed such that it best describes only the affine component of the true deformation, which may actually be non-affine within the spherical sampling volumes. Falk & Langer (see reference below) have proposed a measure to quantify the deviation of the true deformation of the particle system from the affine approximation that the local deformation quantify the deviation of the true deformation from the affine approximation that the atomic deformation gradient represents. This measure, the non-affine squared displacement (D2min), is basically the residual of the least-squares fit through which the deformation gradient is calculated. It may be used as a diagnostic for identifying local irreversible shear transformations in amorphous solids, for example. ... ... @@ -100,7 +186,7 @@ Falk and Langer, which consists of summing up the squared differences between the actual displacements of neighbors and the computed affine approximation. In the current implementation, this sum does not get divided by the number of neighbors within the cutoff range. Thus, the calculated D2min value for a particle will depend on the number of neighbors that are included in the selected cutoff volume and will naturally rise value for a particle is not normalized and will depend on the number of neighbors that are included in the selected cutoff volume. That means D2min values will naturally rise if you increase the cutoff radius. ... ... @@ -110,8 +196,8 @@ U is symmetric positive definite. The local rotation R is encoded as a quaternion R=(X, Y, Z, W) and is output by the modifier as a particle property named Rotation. From this, the angle of rotation (in radians) for each particle can subsequently be obtained as theta=2*acos(Rotation.W), e.g., using the Compute Property modifier. obtained as theta=2*acos(Rotation.W) using e.g. the Compute Property modifier. ... ...
 ... ... @@ -57,8 +57,8 @@ public: public: /// Constructor. ArrowPrimitive(Shape shape, ShadingMode shadingMode, RenderingQuality renderingQuality) : _shape(shape), _shadingMode(shadingMode), _renderingQuality(renderingQuality) {} ArrowPrimitive(Shape shape, ShadingMode shadingMode, RenderingQuality renderingQuality, bool translucentElements) : _shape(shape), _shadingMode(shadingMode), _renderingQuality(renderingQuality), _translucentElements(translucentElements) {} /// \brief Allocates a geometry buffer with the given number of elements. virtual void startSetElements(int elementCount) = 0; ... ... @@ -89,6 +89,9 @@ public: /// \brief Returns the selected element shape. Shape shape() const { return _shape; } /// \brief Returns whether elements are displayed as semi-transparent if their alpha color value is smaller than one. bool translucentElements() const { return _translucentElements; } private: /// Controls the shading. ... ... @@ -100,6 +103,9 @@ private: /// The shape of the elements. Shape _shape; /// Indicates whether some of the elements may be semi-transparent. /// If false, the alpha color value is ignored. bool _translucentElements; }; OVITO_END_INLINE_NAMESPACE ... ...
 ... ... @@ -133,7 +133,7 @@ private: /// Controls the shape of particles. ParticleShape _particleShape; /// Determines whether particles may be semi-transparent. /// Indicates whether some of the particles may be semi-transparent. /// If false, the alpha color value is ignored. bool _translucentParticles; }; ... ... @@ -147,5 +147,3 @@ Q_DECLARE_METATYPE(Ovito::ParticlePrimitive::ParticleShape); Q_DECLARE_TYPEINFO(Ovito::ParticlePrimitive::ShadingMode, Q_PRIMITIVE_TYPE); Q_DECLARE_TYPEINFO(Ovito::ParticlePrimitive::RenderingQuality, Q_PRIMITIVE_TYPE); Q_DECLARE_TYPEINFO(Ovito::ParticlePrimitive::ParticleShape, Q_PRIMITIVE_TYPE);
 ... ... @@ -168,7 +168,8 @@ public: /// Requests a new arrow geometry buffer from the renderer. virtual std::shared_ptr createArrowPrimitive(ArrowPrimitive::Shape shape, ArrowPrimitive::ShadingMode shadingMode = ArrowPrimitive::NormalShading, ArrowPrimitive::RenderingQuality renderingQuality = ArrowPrimitive::MediumQuality) = 0; ArrowPrimitive::RenderingQuality renderingQuality = ArrowPrimitive::MediumQuality, bool translucentElements = false) = 0; /// Requests a new triangle mesh geometry buffer from the renderer. virtual std::shared_ptr createMeshPrimitive() = 0; ... ...
 ... ... @@ -45,8 +45,7 @@ public: public: /// Constructor. DefaultArrowPrimitive(ArrowPrimitive::Shape shape, ShadingMode shadingMode, RenderingQuality renderingQuality) : ArrowPrimitive(shape, shadingMode, renderingQuality) {} using ArrowPrimitive::ArrowPrimitive; /// \brief Allocates a geometry buffer with the given number of elements. virtual void startSetElements(int elementCount) override { ... ...
 ... ... @@ -35,7 +35,7 @@ class OVITO_CORE_EXPORT DefaultImagePrimitive : public ImagePrimitive public: /// Constructor. DefaultImagePrimitive() {} using ImagePrimitive::ImagePrimitive; /// \brief Returns true if the geometry buffer is filled and can be rendered with the given renderer. virtual bool isValid(SceneRenderer* renderer) override; ... ...
 ... ... @@ -35,7 +35,7 @@ class OVITO_CORE_EXPORT DefaultLinePrimitive : public LinePrimitive public: /// Constructor. DefaultLinePrimitive() {} using LinePrimitive::LinePrimitive; /// \brief Allocates a geometry buffer with the given number of vertices. virtual void setVertexCount(int vertexCount, FloatType lineWidth) override { ... ...
 ... ... @@ -35,7 +35,7 @@ class OVITO_CORE_EXPORT DefaultMarkerPrimitive : public MarkerPrimitive public: /// Constructor. DefaultMarkerPrimitive(MarkerShape shape) : MarkerPrimitive(shape) {} using MarkerPrimitive::MarkerPrimitive; /// \brief Allocates a geometry buffer with the given number of markers. virtual void setCount(int markerCount) override { ... ...
 ... ... @@ -36,7 +36,7 @@ class OVITO_CORE_EXPORT DefaultMeshPrimitive : public MeshPrimitive public: /// Constructor. DefaultMeshPrimitive() {} using MeshPrimitive::MeshPrimitive; /// Sets the mesh to be stored in this buffer object. virtual void setMesh(const TriMesh& mesh, const ColorA& meshColor) override { ... ...
 ... ... @@ -35,8 +35,7 @@ class OVITO_CORE_EXPORT DefaultParticlePrimitive : public ParticlePrimitive public: /// Constructor. DefaultParticlePrimitive(ShadingMode shadingMode, RenderingQuality renderingQuality, ParticleShape shape, bool translucentParticles) : ParticlePrimitive(shadingMode, renderingQuality, shape, translucentParticles) {} using ParticlePrimitive::ParticlePrimitive; /// \brief Allocates a geometry buffer with the given number of particles. virtual void setSize(int particleCount) override { ... ...
 ... ... @@ -35,7 +35,7 @@ class OVITO_CORE_EXPORT DefaultTextPrimitive : public TextPrimitive public: /// Constructor. DefaultTextPrimitive() {} using TextPrimitive::TextPrimitive; /// \brief Returns true if the geometry buffer is filled and can be rendered with the given renderer. virtual bool isValid(SceneRenderer* renderer) override; ... ...
 ... ... @@ -92,8 +92,9 @@ public: virtual std::shared_ptr createArrowPrimitive( ArrowPrimitive::Shape shape, ArrowPrimitive::ShadingMode shadingMode, ArrowPrimitive::RenderingQuality renderingQuality) override { return std::make_shared(shape, shadingMode, renderingQuality); ArrowPrimitive::RenderingQuality renderingQuality, bool translucentElements) override { return std::make_shared(shape, shadingMode, renderingQuality, translucentElements); } /// Requests a new triangle mesh buffer from the renderer. ... ...
 ... ... @@ -442,7 +442,7 @@ void PickOrbitCenterMode::renderOverlay3D(Viewport* vp, ViewportSceneRenderer* r if(!renderer->isBoundingBoxPass()) { // Create line buffer. if(!_orbitCenterMarker || !_orbitCenterMarker->isValid(renderer)) { _orbitCenterMarker = renderer->createArrowPrimitive(ArrowPrimitive::CylinderShape, ArrowPrimitive::NormalShading, ArrowPrimitive::HighQuality); _orbitCenterMarker = renderer->createArrowPrimitive(ArrowPrimitive::CylinderShape, ArrowPrimitive::NormalShading, ArrowPrimitive::HighQuality, false); _orbitCenterMarker->startSetElements(3); _orbitCenterMarker->setElement(0, Point3(-1,0,0), Vector3(2,0,0), ColorA(1,0,0), FloatType(0.05)); _orbitCenterMarker->setElement(1, Point3(0,-1,0), Vector3(0,2,0), ColorA(0,1,0), FloatType(0.05)); ... ...
 ... ... @@ -28,8 +28,8 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Rendering) OVITO_BEGIN_INLINE_NAM /****************************************************************************** * Constructor. ******************************************************************************/ OpenGLArrowPrimitive::OpenGLArrowPrimitive(OpenGLSceneRenderer* renderer, ArrowPrimitive::Shape shape, ShadingMode shadingMode, RenderingQuality renderingQuality) : ArrowPrimitive(shape, shadingMode, renderingQuality), OpenGLArrowPrimitive::OpenGLArrowPrimitive(OpenGLSceneRenderer* renderer, ArrowPrimitive::Shape shape, ShadingMode shadingMode, RenderingQuality renderingQuality, bool translucentElements) : ArrowPrimitive(shape, shadingMode, renderingQuality, translucentElements), _contextGroup(QOpenGLContextGroup::currentContextGroup()), _elementCount(-1), _cylinderSegments(16), _verticesPerElement(0), _mappedVerticesWithNormals(nullptr), _mappedVerticesWithElementInfo(nullptr), ... ... @@ -556,8 +556,22 @@ void OpenGLArrowPrimitive::render(SceneRenderer* renderer) if(_elementCount <= 0 || !vpRenderer) return; // If object is translucent, don't render it during the first rendering pass. // Queue primitive so that it gets rendered during the second pass. if(!renderer->isPicking() && translucentElements() && vpRenderer->translucentPass() == false) { vpRenderer->registerTranslucentPrimitive(shared_from_this()); return; } vpRenderer->rebindVAO(); // Activate blend mode when rendering translucent elements. if(!vpRenderer->isPicking() && translucentElements()) { vpRenderer->glEnable(GL_BLEND); vpRenderer->glBlendEquation(GL_FUNC_ADD); vpRenderer->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE_MINUS_DST_COLOR, GL_ONE); } if(shadingMode() == NormalShading) { if(renderingQuality() == HighQuality && shape() == CylinderShape) renderWithElementInfo(vpRenderer); ... ... @@ -568,6 +582,10 @@ void OpenGLArrowPrimitive::render(SceneRenderer* renderer) renderWithElementInfo(vpRenderer); } OVITO_REPORT_OPENGL_ERRORS(); // Deactivate blend mode after rendering translucent elements. if(!vpRenderer->isPicking() && translucentElements()) vpRenderer->glDisable(GL_BLEND); } /****************************************************************************** ... ...
 ... ... @@ -31,12 +31,12 @@ namespace Ovito { OVITO_BEGIN_INLINE_NAMESPACE(Rendering) OVITO_BEGIN_INLINE_NAM /** * \brief Buffer object that stores a set of arrows to be rendered in the viewports. */ class OpenGLArrowPrimitive : public ArrowPrimitive class OpenGLArrowPrimitive : public ArrowPrimitive, public std::enable_shared_from_this { public: /// Constructor. OpenGLArrowPrimitive(OpenGLSceneRenderer* renderer, ArrowPrimitive::Shape shape, ShadingMode shadingMode, RenderingQuality renderingQuality); OpenGLArrowPrimitive(OpenGLSceneRenderer* renderer, ArrowPrimitive::Shape shape, ShadingMode shadingMode, RenderingQuality renderingQuality, bool translucentElements); /// \brief Allocates a geometry buffer with the given number of elements. virtual void startSetElements(int elementCount) override; ... ...
 ... ... @@ -469,11 +469,12 @@ std::shared_ptr OpenGLSceneRenderer::createImagePrimitive() ******************************************************************************/ std::shared_ptr OpenGLSceneRenderer::createArrowPrimitive(ArrowPrimitive::Shape shape, ArrowPrimitive::ShadingMode shadingMode, ArrowPrimitive::RenderingQuality renderingQuality) ArrowPrimitive::RenderingQuality renderingQuality, bool translucentElements) { OVITO_ASSERT(!isBoundingBoxPass()); makeContextCurrent(); return std::make_shared(this, shape, shadingMode, renderingQuality); return std::make_shared(this, shape, shadingMode, renderingQuality, translucentElements); } /****************************************************************************** ... ...
 ... ... @@ -94,7 +94,8 @@ public: /// Requests a new arrow geometry buffer from the renderer. virtual std::shared_ptr createArrowPrimitive(ArrowPrimitive::Shape shape, ArrowPrimitive::ShadingMode shadingMode, ArrowPrimitive::RenderingQuality renderingQuality) override; ArrowPrimitive::RenderingQuality renderingQuality, bool translucentElements) override; /// Requests a new triangle mesh buffer from the renderer. virtual std::shared_ptr createMeshPrimitive() override; ... ...
 ... ... @@ -85,14 +85,18 @@ void DislocationAnalysisModifierEditor::createUI(const RolloutInsertionParameter sublayout->setSpacing(4); sublayout->setColumnStretch(0, 1); // Color by type BooleanParameterUI* colorByTypeUI = new BooleanParameterUI(this, PROPERTY_FIELD(StructureIdentificationModifier::colorByType)); sublayout->addWidget(colorByTypeUI->checkBox(), 0, 0); BooleanParameterUI* onlySelectedParticlesUI = new BooleanParameterUI(this, PROPERTY_FIELD(StructureIdentificationModifier::onlySelectedParticles)); sublayout->addWidget(onlySelectedParticlesUI->checkBox(), 0, 0); sublayout->addWidget(onlySelectedParticlesUI->checkBox(), 1, 0); BooleanParameterUI* outputInterfaceMeshUI = new BooleanParameterUI(this, PROPERTY_FIELD(DislocationAnalysisModifier::outputInterfaceMesh)); sublayout->addWidget(outputInterfaceMeshUI->checkBox(), 1, 0); sublayout->addWidget(outputInterfaceMeshUI->checkBox(), 2, 0); BooleanParameterUI* onlyPerfectDislocationsUI = new BooleanParameterUI(this, PROPERTY_FIELD(DislocationAnalysisModifier::onlyPerfectDislocations)); sublayout->addWidget(onlyPerfectDislocationsUI->checkBox(), 2, 0); sublayout->addWidget(onlyPerfectDislocationsUI->checkBox(), 3, 0); // Status label. layout->addWidget(statusLabel()); ... ... @@ -159,8 +163,6 @@ void DislocationAnalysisModifierEditor::createUI(const RolloutInsertionParameter DislocationTypeListParameterUI::DislocationTypeListParameterUI(QObject* parent) : RefTargetListParameterUI(parent, PROPERTY_FIELD(StructurePattern::burgersVectorFamilies)) { connect(tableWidget(220), &QTableWidget::doubleClicked, this, &DislocationTypeListParameterUI::onDoubleClickDislocationType); tableWidget()->setAutoScroll(false); } ... ... @@ -242,4 +244,3 @@ void DislocationTypeListParameterUI::onDoubleClickDislocationType(const QModelIn } // End of namespace } // End of namespace } // End of namespace
 ... ... @@ -193,6 +193,14 @@ PYBIND11_MODULE(CrystalAnalysis, m) "large Burgers circuits are needed to identify dissociated dislocations with a wide core. " "\n\n" ":Default: False\n") .def_property("color_by_type", &DislocationAnalysisModifier::colorByType, &DislocationAnalysisModifier::setColorByType, "Controls whether the modifier assigns a color to each particle based on the identified structure type. " "\n\n" ":Default: ``True``\n") .def_property("only_selected", &DislocationAnalysisModifier::onlySelectedParticles, &DislocationAnalysisModifier::setOnlySelectedParticles, "Lets the modifier perform the analysis only for selected particles. Particles that are not selected will be treated as if they did not exist." "\n\n" ":Default: ``False``\n") .def_property("output_interface_mesh", &DislocationAnalysisModifier::outputInterfaceMesh, &DislocationAnalysisModifier::setOutputInterfaceMesh) ; ... ...
 ... ... @@ -47,6 +47,10 @@ void BondAngleAnalysisModifierEditor::createUI(const RolloutInsertionParameters& BooleanParameterUI* onlySelectedParticlesUI = new BooleanParameterUI(this, PROPERTY_FIELD(StructureIdentificationModifier::onlySelectedParticles)); layout1->addWidget(onlySelectedParticlesUI->checkBox()); // Color by type BooleanParameterUI* colorByTypeUI = new BooleanParameterUI(this, PROPERTY_FIELD(StructureIdentificationModifier::colorByType)); layout1->addWidget(colorByTypeUI->checkBox()); // Status label. layout1->addSpacing(10); layout1->addWidget(statusLabel()); ... ...
 ... ... @@ -77,6 +77,10 @@ void CommonNeighborAnalysisModifierEditor::createUI(const RolloutInsertionParame BooleanParameterUI* onlySelectedParticlesUI = new BooleanParameterUI(this, PROPERTY_FIELD(StructureIdentificationModifier::onlySelectedParticles)); layout1->addWidget(onlySelectedParticlesUI->checkBox()); // Color by type BooleanParameterUI* colorByTypeUI = new BooleanParameterUI(this, PROPERTY_FIELD(StructureIdentificationModifier::colorByType)); layout1->addWidget(colorByTypeUI->checkBox()); // Status label. layout1->addSpacing(10); layout1->addWidget(statusLabel()); ... ...
 ... ... @@ -47,6 +47,10 @@ void IdentifyDiamondModifierEditor::createUI(const RolloutInsertionParameters& r BooleanParameterUI* onlySelectedParticlesUI = new BooleanParameterUI(this, PROPERTY_FIELD(StructureIdentificationModifier::onlySelectedParticles)); layout1->addWidget(onlySelectedParticlesUI->checkBox()); // Color by type BooleanParameterUI* colorByTypeUI = new BooleanParameterUI(this, PROPERTY_FIELD(StructureIdentificationModifier::colorByType)); layout1->addWidget(colorByTypeUI->checkBox()); // Status label. layout1->addWidget(statusLabel()); ... ...
 ... ... @@ -86,6 +86,10 @@ void PolyhedralTemplateMatchingModifierEditor::createUI(const RolloutInsertionPa sublayout->addWidget(outputOrderingTypesUI->checkBox()); outputOrderingTypesUI->checkBox()->setText(tr("Ordering types")); // Color by type BooleanParameterUI* colorByTypeUI = new BooleanParameterUI(this, PROPERTY_FIELD(StructureIdentificationModifier::colorByType)); sublayout->addWidget(colorByTypeUI->checkBox()); StructureListParameterUI* structureTypesPUI = new StructureListParameterUI(this, true); layout1->addSpacing(10); layout1->addWidget(structureTypesPUI->tableWidget()); ... ...
 ... ... @@ -116,12 +116,13 @@ std::vector ParticleInputHelper::inputBondColors(TimePoint time, TimeInte } // Query half-bond colors from vis element. std::vector halfBondColors = bondsVis->halfBondColors( std::vector halfBondColors = bondsVis->halfBondColors( inputParticleCount(), inputStandardProperty(BondProperty::TopologyProperty), inputStandardProperty(BondProperty::ColorProperty), inputStandardProperty(BondProperty::TypeProperty), inputStandardProperty(BondProperty::SelectionProperty), nullptr, // No transparency needed here particleVis, inputStandardProperty(ParticleProperty::ColorProperty), inputStandardProperty(ParticleProperty::TypeProperty)); ... ... @@ -131,7 +132,7 @@ std::vector ParticleInputHelper::inputBondColors(TimePoint time, TimeInte std::vector colors(inputBondCount()); auto ci = halfBondColors.cbegin(); for(Color& co : colors) { co = *ci; co = Color(ci->r(), ci->g(), ci->b()); ci += 2; } return colors; ... ...
 ... ... @@ -33,15 +33,18 @@ IMPLEMENT_OVITO_CLASS(StructureIdentificationModifier); IMPLEMENT_OVITO_CLASS(StructureIdentificationModifierApplication); DEFINE_REFERENCE_FIELD(StructureIdentificationModifier, structureTypes); DEFINE_PROPERTY_FIELD(StructureIdentificationModifier, onlySelectedParticles); DEFINE_PROPERTY_FIELD(StructureIdentificationModifier, colorByType); SET_PROPERTY_FIELD_LABEL(StructureIdentificationModifier, structureTypes, "Structure types"); SET_PROPERTY_FIELD_LABEL(StructureIdentificationModifier, onlySelectedParticles, "Use only selected particles"); SET_PROPERTY_FIELD_LABEL(StructureIdentificationModifier, colorByType, "Color particles by type"); SET_MODIFIER_APPLICATION_TYPE(StructureIdentificationModifier, StructureIdentificationModifierApplication); /****************************************************************************** * Constructs the modifier object. ******************************************************************************/ StructureIdentificationModifier::StructureIdentificationModifier(DataSet* dataset) : AsynchronousModifier(dataset), _onlySelectedParticles(false) _onlySelectedParticles(false), _colorByType(true) { } ... ... @@ -123,28 +126,40 @@ PipelineFlowState StructureIdentificationModifier::StructureIdentificationEngine // Attach structure types to output particle property. structureProperty->setElementTypes(modifier->structureTypes()); // Build structure type-to-color map. std::vector structureTypeColors(modifier->structureTypes().size()); if(modifier->colorByType()) { // Build structure type-to-color map. std::vector structureTypeColors(modifier->structureTypes().size()); for(ElementType* stype : modifier->structureTypes()) { OVITO_ASSERT(stype->id() >= 0); if(stype->id() >= (int)structureTypeColors.size()) { structureTypeColors.resize(stype->id() + 1); } structureTypeColors[stype->id()] = stype->color(); } // Assign colors to particles based on their structure type. ParticleProperty* colorProperty = poh.outputStandardProperty(ParticleProperty::ColorProperty); const int* s = structureProperty->constDataInt(); for(Color& c : colorProperty->colorRange()) { if(*s >= 0 && *s < structureTypeColors.size()) { c = structureTypeColors[*s]; } else c.setWhite(); ++s; } } // Count the number of identified particles of each type. std::vector typeCounters(modifier->structureTypes().size(), 0); for(ElementType* stype : modifier->structureTypes()) { OVITO_ASSERT(stype->id() >= 0); if(stype->id() >= (int)structureTypeColors.size()) { structureTypeColors.resize(stype->id() + 1); if(stype->id() >= (int)typeCounters.size()) typeCounters.resize(stype->id() + 1, 0); } structureTypeColors[stype->id()] = stype->color(); } // Assign colors to particles based on their structure type. ParticleProperty* colorProperty = poh.outputStandardProperty(ParticleProperty::ColorProperty); const int* s = structureProperty->constDataInt(); for(Color& c : colorProperty->colorRange()) { if(*s >= 0 && *s < structureTypeColors.size()) { c = structureTypeColors[*s]; typeCounters[*s]++; } else c.setWhite(); ++s; for(int t : structureProperty->constIntRange()) { if(t >= 0 && t < typeCounters.size()) typeCounters[t]++; } // Store the per-type counts in the ModifierApplication. ... ...
 ... ... @@ -118,6 +118,14 @@ public: /// Constructor. StructureIdentificationModifier(DataSet* dataset); /// This method indicates whether cached computation results of the modifier should be discarded whenever /// a parameter of the modifier changes. virtual bool discardResultsOnModifierChange(const PropertyFieldEvent& event) const override { // Avoid a recomputation from scratch if the color-by-type option is being changed. if(event.field() == &PROPERTY_FIELD(colorByType)) return false; return AsynchronousModifier::discardResultsOnModifierChange(event); } protected: /// Saves the class' contents to the given stream. ... ... @@ -142,6 +150,9 @@ private: /// Controls whether analysis should take into account only selected particles. DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, onlySelectedParticles, setOnlySelectedParticles); /// Controls whether the modifier colors particles based on their type. DECLARE_MODIFIABLE_PROPERTY_FIELD(bool, colorByType, setColorByType); }; ... ...
 ... ... @@ -286,15 +286,27 @@ void AtomicStrainModifier::AtomicStrainEngine::computeStrain(size_t particleInde // Calculate von Mises shear strain. double xydiff = strain.xx() - strain.yy(); double xzdiff = strain.xx() - strain.zz(); double yzdiff = strain.yy() - strain.zz(); double shearStrain = sqrt(strain.xy()*strain.xy() + strain.xz()*strain.xz() + strain.yz()*strain.yz() + (xydiff*xydiff + xzdiff*xzdiff + yzdiff*yzdiff) / 6.0); double shearStrain; if(!cell().is2D()) { double xzdiff = strain.xx() - strain.zz(); double yzdiff = strain.yy() - strain.zz(); shearStrain = sqrt(strain.xy()*strain.xy() + strain.xz()*strain.xz() + strain.yz()*strain.yz() + (xydiff*xydiff + xzdiff*xzdiff + yzdiff*yzdiff) / 6.0); } else { shearStrain = sqrt(strain.xy()*strain.xy() + (xydiff*xydiff) / 2.0); } OVITO_ASSERT(std::isfinite(shearStrain)); shearStrains()->setFloat(particleIndex, (FloatType)shearStrain); // Calculate volumetric component. double volumetricStrain = (strain(0,0) + strain(1,1) + strain(2,2)) / 3.0; double volumetricStrain; if(!cell().is2D()) { volumetricStrain = (strain(0,0) + strain(1,1) + strain(2,2)) / 3.0; } else { volumetricStrain = (strain(0,0) + strain(1,1)) / 2.0; } OVITO_ASSERT(std::isfinite(volumetricStrain)); volumetricStrains()->setFloat(particleIndex, (FloatType)volumetricStrain); ... ...
 ... ... @@ -68,6 +68,7 @@ PropertyPtr BondProperty::OOMetaClass::createStandardStorage(size_t bondsCount, stride = sizeof(int); break; case LengthProperty: case TransparencyProperty: dataType = PropertyStorage::Float; componentCount = 1; stride = sizeof(FloatType); ... ... @@ -149,6 +150,7 @@ void BondProperty::OOMetaClass::initialize() registerStandardProperty(LengthProperty, tr("Length"), PropertyStorage::Float, emptyList); registerStandardProperty(TopologyProperty, tr("Topology"), PropertyStorage::Int64, abList); registerStandardProperty(PeriodicImageProperty, tr("Periodic Image"), PropertyStorage::Int, xyzList); registerStandardProperty(TransparencyProperty, tr("Transparency"), PropertyStorage::Float, emptyList); } } // End of namespace ... ...
 ... ... @@ -76,6 +76,7 @@ public: LengthProperty = PropertyStorage::FirstSpecificProperty, TopologyProperty, PeriodicImageProperty, TransparencyProperty }; public: ... ...
 ... ... @@ -141,6 +141,7 @@ void BondsVis::render(TimePoint time, DataObject* dataObject, const PipelineFlow BondProperty* bondTypeProperty = BondProperty::findInState(flowState, BondProperty::TypeProperty); BondProperty* bondColorProperty = BondProperty::findInState(flowState, BondProperty::ColorProperty); BondProperty* bondSelectionProperty = BondProperty::findInState(flowState, BondProperty::SelectionProperty); BondProperty* transparencyProperty = BondProperty::findInState(flowState, BondProperty::TransparencyProperty); if(!useParticleColors()) { particleColorProperty = nullptr; particleTypeProperty = nullptr; ... ... @@ -163,6 +164,7 @@ void BondsVis::render(TimePoint time, DataObject* dataObject, const PipelineFlow VersionedDataObjectRef, // Bond color property + revision number VersionedDataObjectRef, // Bond type property + revision number VersionedDataObjectRef, // Bond selection property + revision number VersionedDataObjectRef, // Bond transparency + revision number VersionedDataObjectRef, // Simulation cell + revision number FloatType, // Bond width Color, // Bond color ... ... @@ -180,6 +182,7 @@ void BondsVis::render(TimePoint time, DataObject* dataObject, const PipelineFlow bondColorProperty, bondTypeProperty, bondSelectionProperty, transparencyProperty, simulationCell, bondWidth(), bondColor(), ... ... @@ -195,7 +198,7 @@ void BondsVis::render(TimePoint time, DataObject* dataObject, const PipelineFlow if(bondTopologyProperty && positionProperty && bondRadius > 0) { // Create bond geometry buffer. arrowPrimitive = renderer->createArrowPrimitive(ArrowPrimitive::CylinderShape, shadingMode(), renderingQuality()); arrowPrimitive = renderer->createArrowPrimitive(ArrowPrimitive::CylinderShape, shadingMode(), renderingQuality(), transparencyProperty != nullptr); arrowPrimitive->startSetElements((int)bondTopologyProperty->size() * 2); // Obtain particle vis element. ... ... @@ -208,8 +211,8 @@ void BondsVis::render(TimePoint time, DataObject* dataObject, const PipelineFlow } // Determine half-bond colors. std::vector colors = halfBondColors(positionProperty->size(), bondTopologyProperty, bondColorProperty, bondTypeProperty, bondSelectionProperty, std::vector colors = halfBondColors(positionProperty->size(), bondTopologyProperty, bondColorProperty, bondTypeProperty, bondSelectionProperty, transparencyProperty, particleVis, particleColorProperty, particleTypeProperty); OVITO_ASSERT(colors.size() == arrowPrimitive->elementCount()); ... ... @@ -229,12 +232,12 @@ void BondsVis::render(TimePoint time, DataObject* dataObject, const PipelineFlow for(size_t k = 0; k < 3; k++) if(int d = bondPeriodicImageProperty->getIntComponent(bondIndex, k)) vec += cell.column(k) * (FloatType)d; } arrowPrimitive->setElement(elementIndex++, positions[index1], vec * FloatType( 0.5), (ColorA)*color++, bondRadius); arrowPrimitive->setElement(elementIndex++, positions[index2], vec * FloatType(-0.5), (ColorA)*color++, bondRadius); arrowPrimitive->setElement(elementIndex++, positions[index1], vec * FloatType( 0.5), *color++, bondRadius); arrowPrimitive->setElement(elementIndex++, positions[index2], vec * FloatType(-0.5), *color++, bondRadius); } else { arrowPrimitive->setElement(elementIndex++, Point3::Origin(), Vector3::Zero(), (ColorA)*color++, 0); arrowPrimitive->setElement(elementIndex++, Point3::Origin(), Vector3::Zero(), (ColorA)*color++, 0); arrowPrimitive->setElement(elementIndex++, Point3::Origin(), Vector3::Zero(), *color++, 0); arrowPrimitive->setElement(elementIndex++, Point3::Origin(), Vector3::Zero(), *color++, 0); } } ... ... @@ -263,22 +266,24 @@ void BondsVis::render(TimePoint time, DataObject* dataObject, const PipelineFlow * Returns an array with two colors per full bond, because the two half-bonds * may have different colors. ******************************************************************************/ std::vector BondsVis::halfBondColors(size_t particleCount, BondProperty* topologyProperty, BondProperty* bondColorProperty, BondProperty* bondTypeProperty, BondProperty* bondSelectionProperty, std::vector BondsVis::halfBondColors(size_t particleCount, BondProperty* topologyProperty, BondProperty* bondColorProperty, BondProperty* bondTypeProperty, BondProperty* bondSelectionProperty, BondProperty* transparencyProperty, ParticlesVis* particleDisplay, ParticleProperty* particleColorProperty, ParticleProperty* particleTypeProperty) { OVITO_ASSERT(topologyProperty != nullptr && topologyProperty->type() == BondProperty::TopologyProperty); OVITO_ASSERT(bondColorProperty == nullptr || bondColorProperty->type() == BondProperty::ColorProperty); OVITO_ASSERT(bondTypeProperty == nullptr || bondTypeProperty->type() == BondProperty::TypeProperty); OVITO_ASSERT(bondSelectionProperty == nullptr || bondSelectionProperty->type() == BondProperty::SelectionProperty); OVITO_ASSERT(transparencyProperty == nullptr || transparencyProperty->type() == BondProperty::TransparencyProperty); std::vector output(topologyProperty->size() * 2); std::vector output(topologyProperty->size() * 2); ColorA defaultColor = (ColorA)bondColor(); if(bondColorProperty && bondColorProperty->size() * 2 == output.size()) { // Take bond colors directly from the color property. auto bc = output.begin(); for(const Color& c : bondColorProperty->constColorRange()) { *bc++ = c; *bc++ = c; *bc++ = (ColorA)c; *bc++ = (ColorA)c; } } else if(useParticleColors() && particleDisplay != nullptr) { ... ... @@ -288,29 +293,28 @@ std::vector BondsVis::halfBondColors(size_t particleCount, BondProperty* auto bond = topologyProperty->constDataInt64(); for(auto bc = output.begin(); bc != output.end(); bond += 2) { if(bond[0] < particleCount && bond[1] < particleCount) { *bc++ = particleColors[bond[0]]; *bc++ = particleColors[bond[1]]; *bc++ = (ColorA)particleColors[bond[0]]; *bc++ = (ColorA)particleColors[bond[1]]; } else { *bc++ = bondColor(); *bc++ = bondColor(); *bc++ = defaultColor; *bc++ = defaultColor; } } } else { Color defaultColor = bondColor(); if(bondTypeProperty && bondTypeProperty->size() * 2 == output.size()) { // Assign colors based on bond types. // Generate a lookup map for bond type colors. const std::map colorMap = bondTypeProperty->typeColorMap(); std::array colorArray; const std::map& colorMap = bondTypeProperty->typeColorMap(); std::array colorArray; // Check if all type IDs are within a small, non-negative range. // If yes, we can use an array lookup strategy. Otherwise we have to use a dictionary lookup strategy, which is slower. if(std::all_of(colorMap.begin(), colorMap.end(), [&colorArray](const std::map::value_type& i) { return i.first >= 0 && i.first < (int)colorArray.size(); })) { [&colorArray](const std::map::value_type& i) { return i.first >= 0 && i.first < (int)colorArray.size(); })) { colorArray.fill(defaultColor); for(const auto& entry : colorMap) colorArray[entry.first] = entry.second; colorArray[entry.first] = (ColorA)entry.second; // Fill color array. const int* t = bondTypeProperty->constDataInt(); for(auto c = output.begin(); c != output.end(); ++t) { ... ... @@ -330,8 +334,8 @@ std::vector BondsVis::halfBondColors(size_t particleCount, BondProperty* for(auto c = output.begin(); c != output.end(); ++t) { auto it = colorMap.find(*t); if(it != colorMap.end()) { *c++ = it->second; *c++ = it->second; *c++ = (ColorA)it->second; *c++ = (ColorA)it->second; } else { *c++ = defaultColor; ... ... @@ -346,9 +350,18 @@ std::vector BondsVis::halfBondColors(size_t particleCount, BondProperty* } } // Apply transparency values. if(transparencyProperty && transparencyProperty->size() * 2 == output.size()) { auto c = output.begin(); for(FloatType t : transparencyProperty->constFloatRange()) { c->a() = t; ++c; c->a() = t; ++c; } } // Highlight selected bonds. if(bondSelectionProperty && bondSelectionProperty->size() * 2 == output.size()) { const Color selColor = selectionBondColor(); const ColorA selColor = (ColorA)selectionBondColor(); const int* t = bondSelectionProperty->constDataInt(); for(auto c = output.begin(); c != output.end(); ++t) { if(*t) { ... ...
 ... ... @@ -56,8 +56,8 @@ public: /// Determines the display colors of half-bonds. /// Returns an array with two colors per full bond, because the two half-bonds may have different colors. std::vector halfBondColors(size_t particleCount, BondProperty* topologyProperty, BondProperty* bondColorProperty, BondProperty* bondTypeProperty, BondProperty* bondSelectionProperty, std::vector halfBondColors(size_t particleCount, BondProperty* topologyProperty, BondProperty* bondColorProperty, BondProperty* bondTypeProperty, BondProperty* bondSelectionProperty, BondProperty* transparencyProperty, ParticlesVis* particleDisplay, ParticleProperty* particleColorProperty, ParticleProperty* particleTypeProperty); public: ... ...
 ... ... @@ -367,6 +367,10 @@ void defineModifiersSubmodule(py::module m) " * ``Color`` (:py:class:`~ovito.data.ParticleProperty`):\n" " The modifier assigns a color to each particle according to its identified structure type. " "\n") .def_property("color_by_type", &BondAngleAnalysisModifier::colorByType, &BondAngleAnalysisModifier::setColorByType, "Controls whether the modifier assigns a color to each particle based on the identified structure type. " "\n\n" ":Default: ``True``\n") ; expose_subobject_list(BondAngleAnalysisModifier_py, std::mem_fn(&StructureIdentificationModifier::structureTypes), "structures", "BondAngleAnalysisStructureTypeList", "A list of :py:class:`~ovito.data.ParticleType` instances managed by this modifier, one for each supported structure type. " ... ... @@ -435,6 +439,10 @@ void defineModifiersSubmodule(py::module m) "Lets the modifier perform the analysis only for selected particles. Particles that are not selected will be treated as if they did not exist." "\n\n" ":Default: ``False``\n") .def_property("color_by_type", &CommonNeighborAnalysisModifier::colorByType, &CommonNeighborAnalysisModifier::setColorByType, "Controls whether the modifier assigns a color to each particle based on the identified structure type. " "\n\n" ":Default: ``True``\n") ; expose_subobject_list(CommonNeighborAnalysisModifier_py, std::mem_fn(&StructureIdentificationModifier::structureTypes), "structures", "CommonNeighborAnalysisStructureTypeList", "A list of :py:class:`~ovito.data.ParticleType` instances managed by this modifier, one for each supported structure type. " ... ... @@ -500,6 +508,10 @@ void defineModifiersSubmodule(py::module m) "Lets the modifier perform the analysis only for selected particles. Particles that are not selected will be treated as if they did not exist." "\n\n" ":Default: ``False``\n") .def_property("color_by_type", &IdentifyDiamondModifier::colorByType, &IdentifyDiamondModifier::setColorByType, "Controls whether the modifier assigns a color to each particle based on the identified structure type. " "\n\n" ":Default: ``True``\n") ; expose_subobject_list(IdentifyDiamondModifier_py, std::mem_fn(&StructureIdentificationModifier::structureTypes), "structures", "IdentifyDiamondStructureTypeList", "A list of :py:class:`~ovito.data.ParticleType` instances managed by this modifier, one for each supported structure type. " ... ... @@ -1159,6 +1171,10 @@ void defineModifiersSubmodule(py::module m) "and will all be assigned to the \"Other\" structure category. " "\n\n" ":Default: ``False``\n") .def_property("color_by_type", &PolyhedralTemplateMatchingModifier::colorByType, &PolyhedralTemplateMatchingModifier::setColorByType, "Controls whether the modifier assigns a color to each particle based on the identified structure type. " "\n\n" ":Default: ``True``\n") .def_property("output_rmsd", &PolyhedralTemplateMatchingModifier::outputRmsd, &PolyhedralTemplateMatchingModifier::setOutputRmsd, "Boolean flag that controls whether the modifier outputs the computed per-particle RMSD values as a new particle property named ``RMSD``." "\n\n" ... ...
 ... ... @@ -542,6 +542,7 @@ PYBIND11_MODULE(Particles, m) "``BondProperty.Type.Length`` :guilabel:`Length` float \n" "``BondProperty.Type.Topology`` :guilabel:`Topology` int (2x) \n" "``BondProperty.Type.PeriodicImage`` :guilabel:`Periodic Image` int (3x) \n" "``BondProperty.Type.Transparency`` :guilabel:`Transparency` float \n" "======================================================= =================================================== ==========\n" ) ; ... ... @@ -561,6 +562,7 @@ PYBIND11_MODULE(Particles, m) .value("Length", BondProperty::LengthProperty) .value("Topology", BondProperty::TopologyProperty) .value("PeriodicImage", BondProperty::PeriodicImageProperty) .value("Transparency", BondProperty::TransparencyProperty) ; ovito_class(m, ... ...
 ... ... @@ -232,10 +232,10 @@ bool TachyonRenderer::renderFrame(FrameBuffer* frameBuffer, StereoRenderingTask // Use only the number of parallel rendering threads allowed by the user. scene->numthreads = Application::instance()->idealThreadCount(); /* if certain key aspects of the scene parameters have been changed */ /* since the last frame rendered, or when rendering the scene the */ /* first time, various setup, initialization and memory allocation */ /* routines need to be run in order to prepare for rendering. */ // If certain key aspects of the scene parameters have been changed // since the last frame rendered, or when rendering the scene the // first time, various setup, initialization and memory allocation // routines need to be run in order to prepare for rendering. if(scene->scenecheck) rendercheck(scene); ... ...