/*========================================================================= Program: ParaView Module: vtkSMTransferFunctionPresets.cxx Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.paraview.org/HTML/Copyright.html 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 "vtkSMTransferFunctionPresets.h" #include "vtkSMTransferFunctionPresetsBuiltin.h" #include "vtkNew.h" #include "vtkObjectFactory.h" #include "vtkSMSettings.h" #include "vtkSMTrace.h" #include "vtkSMTransferFunctionProxy.h" #include "vtkTuple.h" #include "vtk_jsoncpp.h" #include "vtksys/SystemTools.hxx" #include #include #include #include class vtkSMTransferFunctionPresets::vtkInternals { public: vtkInternals() : Modified(false), CustomPresetsLoaded(false) { } ~vtkInternals() { if (this->Modified) { assert(this->CustomPresetsLoaded); if (vtkSMSettings* settings = vtkSMSettings::GetInstance()) { std::ostringstream stream; stream << "[\n"; bool not_first = false; for (std::vector::const_iterator iter = this->CustomPresets.begin(); iter != this->CustomPresets.end(); ++iter) { if (not_first) { stream << ",\n"; } not_first = true; stream << iter->toStyledString().c_str(); } stream << "]"; settings->SetSetting("TransferFuctionPresets.CustomPresets", stream.str()); } } } const std::vector& GetPresets() { if (this->Presets.empty()) { this->LoadBuiltinPresets(); this->LoadCustomPresets(); this->Presets.insert(this->Presets.end(), this->BuiltinPresets.begin(), this->BuiltinPresets.end()); this->Presets.insert(this->Presets.end(), this->CustomPresets.begin(), this->CustomPresets.end()); } return this->Presets; } bool RemovePreset(unsigned int index) { this->GetPresets(); if (index >= static_cast(this->Presets.size()) || index < static_cast(this->BuiltinPresets.size())) { return false; } this->Presets.erase(this->Presets.begin() + index); index = (index - static_cast(this->BuiltinPresets.size())); this->Modified = true; assert(this->CustomPresets.size() > index); this->CustomPresets.erase(this->CustomPresets.begin() + index); return true; } void AddPreset(const char* name, const Json::Value& value) { this->LoadCustomPresets(); this->CustomPresets.push_back(value); this->CustomPresets.back()["Name"] = name; this->Presets.clear(); this->Modified = true; } bool IsPresetBuiltin(unsigned int index) { this->LoadBuiltinPresets(); return index < static_cast(this->BuiltinPresets.size()); } bool RenamePreset(unsigned int index, const char* newname) { if (newname && newname[0]) { const std::vector &presets = this->GetPresets(); if (index < static_cast(presets.size()) && index >= static_cast(this->BuiltinPresets.size())) { index = (index - static_cast(this->BuiltinPresets.size())); assert(this->CustomPresets.size() > index); this->CustomPresets[index]["Name"] = newname; this->Presets.clear(); this->Modified = true; return true; } } return false; } bool ImportPresets(const char* filename) { Json::Reader reader; Json::Value root; ifstream file; file.open(filename); if (!file) { vtkGenericWarningMacro("Failed to open file: " << filename); return false; } if (!reader.parse(file, root)) { vtkGenericWarningMacro("File is not is a format suitable for presets: " << filename); return false; } if (!root.isArray()) { vtkGenericWarningMacro("File may not contain presets: " << filename); return false; } return this->ImportPresets(root); } bool ImportPresets(const Json::Value& root) { this->LoadCustomPresets(); this->CustomPresets.insert(this->CustomPresets.end(), root.begin(), root.end()); this->Modified = true; this->Presets.clear(); return true; } private: std::vector BuiltinPresets; std::vector CustomPresets; std::vector Presets; bool Modified; bool CustomPresetsLoaded; void LoadBuiltinPresets() { if (this->BuiltinPresets.empty() == false) { return; } char* rawJSON = vtkSMTransferFunctionPresetsColorMapsJSON(); Json::Reader reader; Json::Value value; if (!reader.parse(std::string(rawJSON), value)) { vtkGenericWarningMacro( << "Failed to parse builtin transfer function presets: " << reader.getFormattedErrorMessages().c_str()); } delete [] rawJSON; this->BuiltinPresets.insert(this->BuiltinPresets.end(), value.begin(), value.end()); } void LoadCustomPresets() { if (this->CustomPresetsLoaded) { return; } this->CustomPresetsLoaded = true; const char* const settingsKey = "TransferFuctionPresets.CustomPresets"; vtkSMSettings* settings = vtkSMSettings::GetInstance(); if (settings == NULL || !settings->HasSetting(settingsKey)) { return; } std::string presetJSON = settings->GetSettingAsString(settingsKey, ""); Json::Reader reader; Json::Value value; if (!presetJSON.empty() && !reader.parse(presetJSON, value)) { vtkGenericWarningMacro( << "Failed to parse custom transfer function presets: " << reader.getFormattedErrorMessages().c_str()); } this->CustomPresets.insert(this->CustomPresets.end(), value.begin(), value.end()); } }; vtkStandardNewMacro(vtkSMTransferFunctionPresets); //---------------------------------------------------------------------------- vtkSMTransferFunctionPresets::vtkSMTransferFunctionPresets() : Internals(new vtkSMTransferFunctionPresets::vtkInternals()) { } //---------------------------------------------------------------------------- vtkSMTransferFunctionPresets::~vtkSMTransferFunctionPresets() { delete this->Internals; this->Internals = NULL; } //---------------------------------------------------------------------------- vtkStdString vtkSMTransferFunctionPresets::GetPresetAsString(unsigned int index) { const std::vector &presets = this->Internals->GetPresets(); return index < static_cast(presets.size())? presets[index].toStyledString() : vtkStdString(); } //---------------------------------------------------------------------------- const Json::Value& vtkSMTransferFunctionPresets::GetPreset(unsigned int index) { static Json::Value nullValue; const std::vector &presets = this->Internals->GetPresets(); return index < static_cast(presets.size())? presets[index] : nullValue; } //---------------------------------------------------------------------------- const Json::Value& vtkSMTransferFunctionPresets::GetFirstPresetWithName( const char* name) { static Json::Value nullValue; if (name == NULL) { return nullValue; } const std::vector &presets = this->Internals->GetPresets(); for (std::vector::const_iterator iter = presets.begin(); iter != presets.end(); ++iter) { if (iter->get("Name", Json::Value()).asString() == name) { return (*iter); } } return nullValue; } //---------------------------------------------------------------------------- vtkStdString vtkSMTransferFunctionPresets::GetPresetName(unsigned int index) { const std::vector &presets = this->Internals->GetPresets(); return index < static_cast(presets.size())? presets[index]["Name"].asString() : vtkStdString(); } //---------------------------------------------------------------------------- bool vtkSMTransferFunctionPresets::RenamePreset(unsigned int index, const char* newname) { return this->Internals->RenamePreset(index, newname); } //---------------------------------------------------------------------------- bool vtkSMTransferFunctionPresets::AddPreset( const char* name, const vtkStdString& preset) { if (!name) { vtkErrorMacro("Invalid 'name' specified."); return false; } Json::Value value; Json::Reader reader; if (!reader.parse(preset, value)) { vtkErrorMacro("Invalid preset string."); vtkGenericWarningMacro( << "Failed to parse builtin transfer function presets: " << reader.getFormattedErrorMessages().c_str()); return false; } this->Internals->AddPreset(name, value); return true; } //---------------------------------------------------------------------------- bool vtkSMTransferFunctionPresets::AddPreset( const char* name, const Json::Value& preset) { this->Internals->AddPreset(name, preset); return true; } //---------------------------------------------------------------------------- vtkStdString vtkSMTransferFunctionPresets::AddUniquePreset( const Json::Value& preset, const char* prefix/*=NULL*/) { prefix = prefix? prefix : "Preset"; std::set names; const std::vector &presets = this->Internals->GetPresets(); for (std::vector::const_iterator iter = presets.begin(); iter != presets.end(); ++iter) { names.insert(iter->get("Name", Json::Value()).asString()); } std::string name = prefix; std::string separator = name.size() > 0? " " : ""; int suffix = 0; while (names.find(name) != names.end()) { std::ostringstream stream; stream << prefix << separator.c_str() << suffix; name = stream.str(); suffix++; if (suffix > 1000) { vtkErrorMacro("Giving up. Cannot find a unique name. Please provide a good prefix."); return vtkStdString(); } } this->AddPreset(name.c_str(), preset); return name; } //---------------------------------------------------------------------------- bool vtkSMTransferFunctionPresets::RemovePreset(unsigned int index) { return this->Internals->RemovePreset(index); } //---------------------------------------------------------------------------- unsigned int vtkSMTransferFunctionPresets::GetNumberOfPresets() { return static_cast(this->Internals->GetPresets().size()); } //---------------------------------------------------------------------------- bool vtkSMTransferFunctionPresets::GetPresetHasOpacities(const Json::Value& preset) { return (!preset.empty() && preset.isMember("Points")); } //---------------------------------------------------------------------------- bool vtkSMTransferFunctionPresets::GetPresetHasIndexedColors(const Json::Value& preset) { return (!preset.empty() && preset.isMember("IndexedColors")); } //---------------------------------------------------------------------------- bool vtkSMTransferFunctionPresets::GetPresetHasAnnotations(const Json::Value& preset) { return (!preset.empty() && preset.isMember("Annotations")); } //---------------------------------------------------------------------------- bool vtkSMTransferFunctionPresets::IsPresetBuiltin(unsigned int index) { if (index >= this->GetNumberOfPresets()) { vtkWarningMacro("Invalid 'index' specified:" << index); return false; } return this->Internals->IsPresetBuiltin(index); } //---------------------------------------------------------------------------- bool vtkSMTransferFunctionPresets::ImportPresets(const char* filename) { if (!filename) { vtkErrorMacro("Invalid filename specified."); return false; } SM_SCOPED_TRACE(CallFunction) .arg("ImportPresets") .arg("filename", filename); if (vtksys::SystemTools::LowerCase( vtksys::SystemTools::GetFilenameLastExtension(filename)) == ".xml") { ifstream in(filename); if (in) { std::ostringstream contents; contents << in.rdbuf(); in.close(); return this->ImportPresets( vtkSMTransferFunctionProxy::ConvertMultipleLegacyColorMapXMLToJSON( contents.str().c_str())); } else { vtkErrorMacro("Failed to open file: " << filename); return false; } } else { return this->Internals->ImportPresets(filename); } } //---------------------------------------------------------------------------- bool vtkSMTransferFunctionPresets::ImportPresets(const Json::Value& presets) { return this->Internals->ImportPresets(presets); } //---------------------------------------------------------------------------- void vtkSMTransferFunctionPresets::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); }