// ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- void WriteStlFile::readFilterParameters(AbstractFilterParametersReader* reader, int index) { reader->openFilterGroup(this, index); setSurfaceMeshFacePhasesArrayPath(reader->readDataArrayPath("SurfaceMeshFacePhasesArrayPath", getSurfaceMeshFacePhasesArrayPath() ) ); setSurfaceMeshFaceLabelsArrayPath(reader->readDataArrayPath("SurfaceMeshFaceLabelsArrayPath", getSurfaceMeshFaceLabelsArrayPath() ) ); setOutputStlDirectory( reader->readString( "OutputStlDirectory", getOutputStlDirectory() ) ); setOutputStlPrefix( reader->readString( "OutputStlPrefix", getOutputStlPrefix() ) ); reader->closeFilterGroup(); }
// ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- void WriteStlFile::execute() { int32_t err = 0; setErrorCondition(0); dataCheck(); if(getErrorCondition() < 0) { return; } // Make sure any directory path is also available as the user may have just typed // in a path without actually creating the full path QDir stlDir(getOutputStlDirectory()); if (!stlDir.mkpath(".")) { QString ss = QObject::tr("Error creating parent path '%1'").arg(getOutputStlDirectory()); notifyErrorMessage(getHumanLabel(), ss, -1); setErrorCondition(-1); return; } TriangleGeom::Pointer triangleGeom = getDataContainerArray()->getDataContainer(getSurfaceMeshFaceLabelsArrayPath().getDataContainerName())->getGeometryAs<TriangleGeom>(); float* nodes = triangleGeom->getVertexPointer(0); int64_t* triangles = triangleGeom->getTriPointer(0); int64_t nTriangles = triangleGeom->getNumberOfTris(); if (nTriangles > std::numeric_limits<int32_t>::max()) { QString ss = QObject::tr("The number of triangles is %1, but the STL specification only supports triangle counts up to %2").arg(nTriangles).arg(std::numeric_limits<int32_t>::max()); notifyErrorMessage(getHumanLabel(), ss, -1); setErrorCondition(-1); return; } // Store all the unique Spins QMap<int32_t, int32_t> uniqueGrainIdtoPhase; if (m_GroupByPhase == true) { for (int64_t i = 0; i < nTriangles; i++) { uniqueGrainIdtoPhase.insert(m_SurfaceMeshFaceLabels[i * 2], m_SurfaceMeshFacePhases[i * 2]); uniqueGrainIdtoPhase.insert(m_SurfaceMeshFaceLabels[i * 2 + 1], m_SurfaceMeshFacePhases[i * 2 + 1]); } } else { for (int64_t i = 0; i < nTriangles; i++) { uniqueGrainIdtoPhase.insert(m_SurfaceMeshFaceLabels[i * 2], 0); uniqueGrainIdtoPhase.insert(m_SurfaceMeshFaceLabels[i * 2 + 1], 0); } } unsigned char data[50]; float* normal = (float*)data; float* vert1 = (float*)(data + 12); float* vert2 = (float*)(data + 24); float* vert3 = (float*)(data + 36); uint16_t* attrByteCount = (uint16_t*)(data + 48); *attrByteCount = 0; size_t totalWritten = 0; float u[3] = { 0.0f, 0.0f, 0.0f }, w[3] = { 0.0f, 0.0f, 0.0f }; float length = 0.0f; int32_t spin = 0; int32_t triCount = 0; //Loop over the unique Spins for (QMap<int32_t, int32_t>::iterator spinIter = uniqueGrainIdtoPhase.begin(); spinIter != uniqueGrainIdtoPhase.end(); ++spinIter ) { spin = spinIter.key(); // Generate the output file name QString filename = getOutputStlDirectory() + "/" + getOutputStlPrefix(); if (m_GroupByPhase == true) { filename = filename + QString("Ensemble_") + QString::number(spinIter.value()) + QString("_"); } filename = filename + QString("Feature_") + QString::number(spin) + ".stl"; FILE* f = fopen(filename.toLatin1().data(), "wb"); { QString ss = QObject::tr("Writing STL for Feature Id %1").arg(spin); notifyStatusMessage(getMessagePrefix(), getHumanLabel(), ss); } QString header = "DREAM3D Generated For Feature ID " + QString::number(spin); if (m_GroupByPhase == true) { header = header + " Phase " + QString::number(spinIter.value()); } err = writeHeader(f, header, 0); if (err < 0) { } triCount = 0; // Reset this to Zero. Increment for every triangle written // Loop over all the triangles for this spin for (int64_t t = 0; t < nTriangles; ++t) { // Get the true indices of the 3 nodes int64_t nId0 = triangles[t * 3]; int64_t nId1 = triangles[t * 3 + 1]; int64_t nId2 = triangles[t * 3 + 2]; vert1[0] = static_cast<float>(nodes[nId0 * 3]); vert1[1] = static_cast<float>(nodes[nId0 * 3 + 1]); vert1[2] = static_cast<float>(nodes[nId0 * 3 + 2]); if (m_SurfaceMeshFaceLabels[t * 2] == spin) { //winding = 0; // 0 = Write it using forward spin } else if (m_SurfaceMeshFaceLabels[t * 2 + 1] == spin) { //winding = 1; // Write it using backward spin // Switch the 2 node indices int64_t temp = nId1; nId1 = nId2; nId2 = temp; } else { continue; // We do not match either spin so move to the next triangle } vert2[0] = static_cast<float>(nodes[nId1 * 3]); vert2[1] = static_cast<float>(nodes[nId1 * 3 + 1]); vert2[2] = static_cast<float>(nodes[nId1 * 3 + 2]); vert3[0] = static_cast<float>(nodes[nId2 * 3]); vert3[1] = static_cast<float>(nodes[nId2 * 3 + 1]); vert3[2] = static_cast<float>(nodes[nId2 * 3 + 2]); // Compute the normal u[0] = vert2[0] - vert1[0]; u[1] = vert2[1] - vert1[1]; u[2] = vert2[2] - vert1[2]; w[0] = vert3[0] - vert1[0]; w[1] = vert3[1] - vert1[1]; w[2] = vert3[2] - vert1[2]; normal[0] = u[1] * w[2] - u[2] * w[1]; normal[1] = u[2] * w[0] - u[0] * w[2]; normal[2] = u[0] * w[1] - u[1] * w[0]; length = sqrtf(normal[0] * normal[0] + normal[1] * normal[1] + normal[2] * normal[2]); normal[0] = normal[0] / length; normal[1] = normal[1] / length; normal[2] = normal[2] / length; totalWritten = fwrite(data, 1, 50, f); if (totalWritten != 50) { QString ss = QObject::tr("Error Writing STL File. Not enough elements written for Feature Id %1. Wrote %2 of 50.").arg(spin).arg(totalWritten); notifyErrorMessage(getHumanLabel(), ss, -1201); } triCount++; } fclose(f); err = writeNumTrianglesToFile(filename, triCount); } setErrorCondition(0); notifyStatusMessage(getHumanLabel(), "Complete"); return; }
// ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- void WriteStlFile::setupFilterParameters() { FilterParameterVector parameters; parameters.push_back(OutputPathFilterParameter::New("Output STL Directory", "OutputStlDirectory", getOutputStlDirectory(), FilterParameter::Parameter)); parameters.push_back(StringFilterParameter::New("STL File Prefix", "OutputStlPrefix", getOutputStlPrefix(), FilterParameter::Parameter)); //QStringList linkedProps("SurfaceMeshFacePhasesArrayPath"); //parameters.push_back(LinkedBooleanFilterParameter::New("Group Files by Ensemble", "GroupByPhase", getGroupByPhase(), linkedProps, FilterParameter::Parameter)); parameters.push_back(SeparatorFilterParameter::New("Face Data", FilterParameter::RequiredArray)); parameters.push_back(DataArraySelectionFilterParameter::New("Face Labels", "SurfaceMeshFaceLabelsArrayPath", getSurfaceMeshFaceLabelsArrayPath(), FilterParameter::RequiredArray)); //parameters.push_back(DataArraySelectionFilterParameter::New("Face Phases", "SurfaceMeshFacePhasesArrayPath", getSurfaceMeshFacePhasesArrayPath(), FilterParameter::RequiredArray)); setFilterParameters(parameters); }
// ----------------------------------------------------------------------------- // // ----------------------------------------------------------------------------- void WriteStlFile::setupFilterParameters() { FilterParameterVector parameters; parameters.push_back(OutputPathFilterParameter::New("Output STL Directory", "OutputStlDirectory", getOutputStlDirectory(), FilterParameter::Parameter)); parameters.push_back(StringFilterParameter::New("STL File Prefix", "OutputStlPrefix", getOutputStlPrefix(), FilterParameter::Parameter)); //QStringList linkedProps("SurfaceMeshFacePhasesArrayPath"); //parameters.push_back(LinkedBooleanFilterParameter::New("Group Files by Ensemble", "GroupByPhase", getGroupByPhase(), linkedProps, FilterParameter::Parameter)); parameters.push_back(SeparatorFilterParameter::New("Face Data", FilterParameter::RequiredArray)); { DataArraySelectionFilterParameter::RequirementType req = DataArraySelectionFilterParameter::CreateRequirement(SIMPL::TypeNames::Int32, 2, SIMPL::AttributeMatrixType::Face, SIMPL::GeometryType::TriangleGeometry); parameters.push_back(DataArraySelectionFilterParameter::New("Face Labels", "SurfaceMeshFaceLabelsArrayPath", getSurfaceMeshFaceLabelsArrayPath(), FilterParameter::RequiredArray, req)); } //parameters.push_back(DataArraySelectionFilterParameter::New("Face Phases", "SurfaceMeshFacePhasesArrayPath", getSurfaceMeshFacePhasesArrayPath(), FilterParameter::RequiredArray)); setFilterParameters(parameters); }