https://mooseframework.inl.gov
Loading...
Searching...
No Matches
ImageMesh.C
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://mooseframework.inl.gov
3//*
4//* All rights reserved, see COPYRIGHT for full restrictions
5//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6//*
7//* Licensed under LGPL 2.1, please see LICENSE for details
8//* https://www.gnu.org/licenses/lgpl-2.1.html
9
10#include "ImageMesh.h"
11#include "pcrecpp.h"
12#include "MooseApp.h"
13#include "MooseTypes.h"
14#include "libmesh/cell_hex8.h"
15#include "libmesh/face_quad4.h"
16
17#include <cstdlib> // std::system, mkstemp
18#include <fstream>
19
20#include "libmesh/mesh_generation.h"
21#include "libmesh/unstructured_mesh.h"
22
24
27{
30 params.addClassDescription("Generated mesh with the aspect ratio of a given image stack.");
31
32 // Add ImageMesh-specific params
33 params.addParam<bool>(
34 "scale_to_one", true, "Whether or not to scale the image so its max dimension is 1");
35 params.addRangeCheckedParam<Real>("cells_per_pixel",
36 1.0,
37 "cells_per_pixel<=1.0",
38 "The number of mesh cells per pixel, must be <=1 ");
39
40 return params;
41}
42
44 : GeneratedMesh(parameters),
45 FileRangeBuilder(parameters),
46 _scale_to_one(getParam<bool>("scale_to_one")),
47 _cells_per_pixel(getParam<Real>("cells_per_pixel"))
48{
49 // Failure is not an option
50 errorCheck();
51}
52
54 : GeneratedMesh(other_mesh),
55 FileRangeBuilder(other_mesh.parameters()),
56 _scale_to_one(getParam<bool>("scale_to_one")),
57 _cells_per_pixel(getParam<Real>("cells_per_pixel"))
58{
59}
60
61std::unique_ptr<MooseMesh>
63{
64 return _app.getFactory().copyConstruct(*this);
65}
66
67void
69{
70 // A list of filenames of length 1 means we are building a 2D mesh
71 if (_filenames.size() == 1)
73
74 else
76}
77
78void
79ImageMesh::buildMesh3D(const std::vector<std::string> & filenames)
80{
81 // If the user gave us a "stack" with 0 or 1 files in it, we can't
82 // really create a 3D Mesh from that
83 if (filenames.size() <= 1)
84 mooseError("ImageMesh error: Cannot create a 3D ImageMesh from an image stack with ",
85 filenames.size(),
86 " images.");
87
88 // For each file in the stack, process it using the 'file' command.
89 // We want to be sure that all the images in the stack are the same
90 // size, for example...
91 int xpixels = 0, ypixels = 0, zpixels = filenames.size();
92
93 // Take pixel info from the first image in the stack to determine the aspect ratio
94 GetPixelInfo(filenames[0], xpixels, ypixels);
95
96 // TODO: Check that all images are the same aspect ratio and have
97 // the same number of pixels? ImageFunction does not currently do
98 // this...
99 // for (const auto & filename : filenames)
100 // {
101 // // Extract the number of pixels from the image using the file command
102 // GetPixelInfo(filename, xpixels, ypixels);
103 //
104 // // Moose::out << "Image " << filename << " has size: " << xpixels << " by " << ypixels <<
105 // std::endl;
106 // }
107
108 // Use the number of x and y pixels and the number of images to
109 // determine the the x, y, and z dimensions of the mesh. We assume
110 // that there is 1 pixel in the z-direction for each image in the
111 // stack.
112
113 // Set the maximum dimension to 1.0 while scaling the other
114 // directions to maintain the aspect ratio.
115 _xmax = xpixels;
116 _ymax = ypixels;
117 _zmax = zpixels;
118
119 if (_scale_to_one)
120 {
121 Real max = std::max(std::max(_xmax, _ymax), _zmax);
122 _xmax /= max;
123 _ymax /= max;
124 _zmax /= max;
125 }
126
127 // Compute the number of cells in the x and y direction based on
128 // the user's cells_per_pixel parameter. Note: we use ints here
129 // because the GeneratedMesh params object uses ints for these...
130 _nx = static_cast<int>(_cells_per_pixel * xpixels);
131 _ny = static_cast<int>(_cells_per_pixel * ypixels);
132 _nz = static_cast<int>(_cells_per_pixel * zpixels);
133
134 // Actually build the Mesh
135 MeshTools::Generation::build_cube(dynamic_cast<UnstructuredMesh &>(getMesh()),
136 _nx,
137 _ny,
138 _nz,
139 /*xmin=*/0.,
140 /*xmax=*/_xmax,
141 /*ymin=*/0.,
142 /*ymax=*/_ymax,
143 /*zmin=*/0.,
144 /*zmax=*/_zmax,
145 HEX8);
146}
147
148void
149ImageMesh::buildMesh2D(const std::string & filename)
150{
151 int xpixels = 0, ypixels = 0;
152
153 // Extract the number of pixels from the image using the file command
154 GetPixelInfo(filename, xpixels, ypixels);
155
156 // Set the maximum dimension to 1.0 while scaling the other
157 // direction to maintain the aspect ratio.
158 _xmax = xpixels;
159 _ymax = ypixels;
160
161 if (_scale_to_one)
162 {
163 Real max = std::max(_xmax, _ymax);
164 _xmax /= max;
165 _ymax /= max;
166 }
167
168 // Compute the number of cells in the x and y direction based on
169 // the user's cells_per_pixel parameter. Note: we use ints here
170 // because the GeneratedMesh params object uses ints for these...
171 _nx = static_cast<int>(_cells_per_pixel * xpixels);
172 _ny = static_cast<int>(_cells_per_pixel * ypixels);
173
174 // Actually build the Mesh
175 MeshTools::Generation::build_square(dynamic_cast<UnstructuredMesh &>(getMesh()),
176 _nx,
177 _ny,
178 /*xmin=*/0.,
179 /*xmax=*/_xmax,
180 /*ymin=*/0.,
181 /*ymax=*/_ymax,
182 QUAD4);
183}
184
185void
186ImageMesh::GetPixelInfo(std::string filename, int & xpixels, int & ypixels)
187{
188 // For reporting possible error messages
189 std::string error_message = "";
190
191 // A template for creating a temporary file.
192 char temp_file[] = "file_command_output.XXXXXX";
193
194 // Use a do-loop so we can break out under various error conditions
195 // while still cleaning up temporary files. Basically use goto
196 // statements without actually using them.
197 do
198 {
199 // mkstemp is not in namespace std for whatever reason...
200 int fd = mkstemp(temp_file);
201
202 // If mkstemp fails, we failed.
203 if (fd == -1)
204 {
205 error_message = "Error creating temporary file in ImageMesh::buildMesh()";
206 break;
207 }
208
209 // Construct the command string
210 std::ostringstream command;
211 command << "file " << filename << " 2>/dev/null 1>" << temp_file;
212
213 // Make the system call, catch the return code
214 int exit_status = std::system(command.str().c_str());
215
216 // If the system command returned a non-zero status, we failed.
217 if (exit_status != 0)
218 {
219 error_message = "Error calling 'file' command in ImageMesh::buildMesh()";
220 break;
221 }
222
223 // Open the file which contains the result of the system command
224 std::ifstream fin(temp_file);
225
226 // Read the contents of the output file into a string
227 std::string command_result;
228 std::getline(fin, command_result);
229
230 // A regular expression which matches "NNN x NNN" , i.e. any number
231 // of digits, a space, an 'x', a space, and any number of digits.
232 // The parentheses define capture groups which are stored into the
233 // xsize and ysize integers.
234 // Here's an example string:
235 // sixteenth_image001_cropped3_closing_298.png: PNG image data, 115 x 99, 16-bit/color RGB,
236 // non-interlaced
237 xpixels = 0, ypixels = 0;
238 pcrecpp::RE re("(\\d+) x (\\d+)");
239 re.PartialMatch(command_result, &xpixels, &ypixels);
240
241 // Detect failure of the regex
242 if ((xpixels == 0) || (ypixels == 0))
243 {
244 error_message = "Regex failed to find a match in " + command_result;
245 break;
246 }
247 } while (false);
248
249 // Remove the temporary file. This will still work even if the file was never created...
250 std::remove(temp_file);
251
252 // Report and exit if there was an error
253 if (error_message != "")
254 mooseError(error_message);
255}
registerMooseObject("MooseApp", ImageMesh)
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
std::unique_ptr< T > copyConstruct(const T &object)
Copy constructs the object object.
Definition Factory.h:358
To be called in the validParams functions of classes that need to operate on ranges of files.
const std::vector< std::string > & filenames()
static InputParameters validParams()
std::vector< std::string > _filenames
Mesh generated from parameters.
unsigned int _nz
unsigned int _nx
Number of elements in x, y, z direction.
static InputParameters validParams()
unsigned int _ny
A 2D GeneratedMesh where xmin, xmax, etc.
Definition ImageMesh.h:19
virtual void buildMesh() override
Must be overridden by child classes.
Definition ImageMesh.C:68
const Real & _cells_per_pixel
A number <= 1.0 which determines the number of cells in the mesh per pixel in each direction.
Definition ImageMesh.h:61
ImageMesh(const InputParameters &parameters)
Definition ImageMesh.C:43
virtual std::unique_ptr< MooseMesh > safeClone() const override
A safer version of the clone() method that hands back an allocated object wrapped in a smart pointer.
Definition ImageMesh.C:62
void buildMesh2D(const std::string &filename)
buildMesh() calls this helper function to build 2D ImageMeshes.
Definition ImageMesh.C:149
const bool _scale_to_one
If true, forces the maximum width (height) of the mesh to be 1.0 while retaining the original aspect ...
Definition ImageMesh.h:51
void buildMesh3D(const std::vector< std::string > &filenames)
buildMesh() calls this helper function to build 3D ImageMeshes from stacks of images.
Definition ImageMesh.C:79
static InputParameters validParams()
Definition ImageMesh.C:26
void GetPixelInfo(std::string filename, int &xpixels, int &ypixels)
Process a single image with the 'file' command to find out the number of pixels in the x and y direct...
Definition ImageMesh.C:186
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system.
void addParam(const std::string &name, const S &value, const std::string &doc_string)
These methods add an optional parameter and a documentation string to the InputParameters object.
void addClassDescription(const std::string &doc_string)
This method adds a description of the class that will be displayed in the input file syntax dump.
void addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
Factory & getFactory()
Retrieve a writable reference to the Factory associated with this App.
Definition MooseApp.h:407
MeshBase & getMesh()
Accessor for the underlying libMesh Mesh object.
Definition MooseMesh.C:3549
MooseApp & _app
The MOOSE application this is associated with.
Definition MooseBase.h:375
int mkstemp(char *tmpl)