38 const Property PROP_DIMENSIONS = {
"dimensions", std::array<int32_t, 3>({{0, 0, 0}}), {
"Dimensions"}};
39 const Property PROP_SPACING = {
"spacing", std::array<double, 3>({{1, 1, 1}}), {
"Spacing"}};
40 const Property PROP_TYPE = {
"type",
42 core::enumNames<core::DataType>(),
50 template <
size_t M,
typename T>
51 std::string to_string(
const glm::vec<M, T>& vec)
53 std::stringstream stream;
59 std::array<T, 3> parseArray3(
const std::string& str, std::function<T(std::string)> conv)
63 throw std::runtime_error(
"Not exactly 3 values for mhd array");
64 return {{conv(v[0]), conv(v[1]), conv(v[2])}};
67 std::map<std::string, std::string> parseMHD(
const std::string& filename)
69 std::ifstream infile(filename);
71 throw std::runtime_error(
"Could not open file " + filename);
81 std::map<std::string, std::string> result;
84 while (std::getline(infile, line))
88 throw std::runtime_error(
"Could not parse line " + std::to_string(ctr));
101 DataType dataTypeFromMET(
const std::string& type)
103 if (type ==
"MET_FLOAT")
105 else if (type ==
"MET_DOUBLE")
107 else if (type ==
"MET_UCHAR")
109 else if (type ==
"MET_USHORT")
111 else if (type ==
"MET_UINT")
113 else if (type ==
"MET_CHAR")
115 else if (type ==
"MET_SHORT")
117 else if (type ==
"MET_INT")
120 throw std::runtime_error(
"Unknown data type " + type);
128 return {std::numeric_limits<uint8_t>::min(), std::numeric_limits<uint8_t>::max()};
130 return {std::numeric_limits<uint16_t>::min(), std::numeric_limits<uint16_t>::max()};
132 return {std::numeric_limits<uint32_t>::min() / 100, std::numeric_limits<uint32_t>::max() / 100};
134 return {std::numeric_limits<int8_t>::min(), std::numeric_limits<int8_t>::max()};
136 return {std::numeric_limits<int16_t>::min(), std::numeric_limits<int16_t>::max()};
138 return {std::numeric_limits<int32_t>::min() / 100, std::numeric_limits<int32_t>::max() / 100};
154 return extension ==
"raw";
160 return _loadVolume(blob.name, callback, properties,
161 [&blob](
auto volume) { volume->mapData(std::move(blob.data)); });
167 return _loadVolume(storage, callback, properties, [storage](
auto volume) {
volume->mapData(storage); });
176 properties.
merge(propertiesTmp);
180 const auto dimensions =
toGlmVec(properties.
getProperty<std::array<int32_t, 3>>(PROP_DIMENSIONS.name));
181 const auto spacing =
toGlmVec(properties.
getProperty<std::array<double, 3>>(PROP_SPACING.name));
182 const auto type = stringToEnum<DataType>(properties.
getProperty<std::string>(PROP_TYPE.name));
184 if (glm::compMul(dimensions) == 0)
185 throw std::runtime_error(
"Volume dimensions are empty");
187 auto dataRange = dataRangeFromType(type);
189 auto volume = model->createSharedDataVolume(dimensions, spacing, type);
190 volume->setDataRange(dataRange);
196 model->addVolume(VOLUME_MATERIAL_ID, volume);
200 dataRange =
volume->getDataRange();
201 auto modelDescriptor = std::make_shared<ModelDescriptor>(
202 std::move(model), filename,
204 {
"Dimensions", std::to_string(dimensions.x) +
"," + std::to_string(dimensions.y) +
"," +
205 std::to_string(dimensions.z)},
207 std::to_string(spacing.x) +
"," + std::to_string(spacing.y) +
"," + std::to_string(spacing.z)},
208 {
"Data range", std::to_string(dataRange.x) +
"," + std::to_string(dataRange.y)}});
209 modelDescriptor->setTransformation(transformation);
210 return modelDescriptor;
240 return extension ==
"mhd";
246 throw std::runtime_error(
"Volume loading from blob is not supported");
252 std::string volumeFile = storage;
253 const auto mhd = parseMHD(storage);
256 for (
const auto key : {
"ObjectType",
"DimSize",
"ElementSpacing",
"ElementType",
"ElementDataFile"})
257 if (mhd.find(key) == mhd.end())
258 throw std::runtime_error(
"Missing key " + std::string(key));
260 if (mhd.at(
"ObjectType") !=
"Image")
261 throw std::runtime_error(
"Wrong object type for mhd file");
263 const auto dimensions = parseArray3<int32_t>(mhd.at(
"DimSize"), [](
const auto& s) { return stoi(s); });
264 const auto spacing = parseArray3<double>(mhd.at(
"ElementSpacing"), [](
const auto& s) { return stod(s); });
265 const auto type = dataTypeFromMET(mhd.at(
"ElementType"));
267 fs::path path = mhd.at(
"ElementDataFile");
268 if (!path.is_absolute())
270 auto basePath = fs::path(storage).parent_path();
271 path = fs::canonical(basePath / path);
273 volumeFile = path.string();
276 properties.
setProperty({PROP_DIMENSIONS.name, dimensions, PROP_DIMENSIONS.metaData});
277 properties.
setProperty({PROP_SPACING.name, spacing, PROP_SPACING.metaData});
void updateProgress(const std::string &message, const float fraction) const
ModelDescriptorPtr importFromBlob(Blob &&blob, const LoaderProgress &callback, const PropertyMap &properties) const final
bool isSupported(const std::string &storage, const std::string &extension) const final
ModelDescriptorPtr importFromStorage(const std::string &storage, const LoaderProgress &callback, const PropertyMap &properties) const final
MHDVolumeLoader(Scene &scene)
std::vector< std::string > getSupportedStorage() const final
std::string getName() const final
void setProperty(const Property &newProperty)
T getProperty(const std::string &name, T valIfNotFound) const
void merge(const PropertyMap &input)
PropertyMap getProperties() const final
ModelDescriptorPtr importFromBlob(Blob &&blob, const LoaderProgress &callback, const PropertyMap &properties) const final
std::vector< std::string > getSupportedStorage() const final
std::string getName() const final
RawVolumeLoader(Scene &scene)
bool isSupported(const std::string &storage, const std::string &extension) const final
ModelDescriptorPtr importFromStorage(const std::string &storage, const LoaderProgress &callback, const PropertyMap &properties) const final
Scene object This object contains collections of geometries, materials and light sources that are use...
virtual PLATFORM_API ModelPtr createModel() const =0
Factory method to create an engine-specific model.
void trim(std::string &s)
std::vector< std::string > split(const std::string &s, char delim)
std::string enumToString(const EnumT v)
std::map< std::string, std::string > ModelMetadata
std::shared_ptr< SharedDataVolume > SharedDataVolumePtr
std::shared_ptr< ModelDescriptor > ModelDescriptorPtr
glm::vec< M, T > toGlmVec(const std::array< T, M > &input)