From 8b76fbb408f8eedab24195655c45c891af01eaab Mon Sep 17 00:00:00 2001 From: cathook Date: Wed, 24 Sep 2014 13:37:42 +0800 Subject: Big change, detail see README. --- meowpp/!readme.asciidoc | 20 - meowpp/Usage.h | 478 ------------ meowpp/colors/!readme.asciidoc | 78 -- meowpp/colors/Color3_Space.h | 148 ---- meowpp/colors/HSL_Space.h | 195 ----- meowpp/colors/HSV_Space.h | 195 ----- meowpp/colors/RGB_Space.h | 182 ----- meowpp/colors/YUV_Space.h | 138 ---- meowpp/debug/assert.h | 76 ++ meowpp/dsa/!readme.asciidoc | 57 -- meowpp/dsa/BinaryIndexTree.h | 102 --- meowpp/dsa/DisjointSet.h | 135 ---- meowpp/dsa/HashTable.h | 217 ------ meowpp/dsa/KD_Tree.h | 303 -------- meowpp/dsa/MergeableHeap.h | 168 ----- meowpp/dsa/SegmentTree.h | 194 ----- meowpp/dsa/SplayTree.h | 1151 ----------------------------- meowpp/dsa/VP_Tree.h | 337 --------- meowpp/geo/!readme.asciidoc | 12 - meowpp/geo/Vectors.h | 505 ------------- meowpp/gra/Bitmap.h | 437 ----------- meowpp/gra/BitmapDescript.h | 51 -- meowpp/gra/BundleAdjustment.h | 105 --- meowpp/gra/BundleAdjustment_LM.h | 376 ---------- meowpp/gra/Camera.h | 261 ------- meowpp/gra/Eye.h | 174 ----- meowpp/gra/FeaturePoint.h | 262 ------- meowpp/gra/FeaturePointsDetector.h | 25 - meowpp/gra/FeaturePointsDetector_Harris.h | 365 --------- meowpp/gra/FeaturePointsMatch.h | 46 -- meowpp/gra/FeaturePointsMatch_K_Match.h | 180 ----- meowpp/gra/IdentityPoints.h | 392 ---------- meowpp/gra/Photo.h | 446 ----------- meowpp/gra/ViewPort.h | 19 - meowpp/gra/WatchBall.h | 252 ------- meowpp/math/!readme.asciidoc | 73 -- meowpp/math/LinearTransformation.h | 110 --- meowpp/math/LinearTransformations.h | 404 ---------- meowpp/math/Matrix.h | 536 -------------- meowpp/math/Transformation.h | 237 ------ meowpp/math/Transformations.h | 550 -------------- meowpp/math/Vector.h | 267 ------- meowpp/math/methods.h | 230 ------ meowpp/math/utility.h | 157 ---- meowpp/oo/!readme.asciidoc | 32 - meowpp/oo/ObjArray.h | 168 ----- meowpp/oo/ObjBase.h | 99 --- meowpp/oo/ObjDictionary.h | 167 ----- meowpp/oo/ObjProperties.h | 55 -- meowpp/oo/ObjSelector.h | 214 ------ meowpp/oo/ObjTypes.h | 201 ----- meowpp/self.h | 346 --------- meowpp/utility.h | 204 ----- meowpp/utility/factory.h | 383 ++++++++++ meowpp/utility/object.h | 154 ++++ meowpp/utility/operation.h | 80 ++ meowpp/utility/pointer.h | 174 +++++ meowpp/utility/self.h | 244 ++++++ meowpp/utility/state.h | 108 +++ 59 files changed, 1219 insertions(+), 12056 deletions(-) delete mode 100644 meowpp/!readme.asciidoc delete mode 100644 meowpp/Usage.h delete mode 100644 meowpp/colors/!readme.asciidoc delete mode 100644 meowpp/colors/Color3_Space.h delete mode 100644 meowpp/colors/HSL_Space.h delete mode 100644 meowpp/colors/HSV_Space.h delete mode 100644 meowpp/colors/RGB_Space.h delete mode 100644 meowpp/colors/YUV_Space.h create mode 100644 meowpp/debug/assert.h delete mode 100644 meowpp/dsa/!readme.asciidoc delete mode 100644 meowpp/dsa/BinaryIndexTree.h delete mode 100644 meowpp/dsa/DisjointSet.h delete mode 100644 meowpp/dsa/HashTable.h delete mode 100644 meowpp/dsa/KD_Tree.h delete mode 100644 meowpp/dsa/MergeableHeap.h delete mode 100644 meowpp/dsa/SegmentTree.h delete mode 100644 meowpp/dsa/SplayTree.h delete mode 100644 meowpp/dsa/VP_Tree.h delete mode 100644 meowpp/geo/!readme.asciidoc delete mode 100644 meowpp/geo/Vectors.h delete mode 100644 meowpp/gra/Bitmap.h delete mode 100644 meowpp/gra/BitmapDescript.h delete mode 100644 meowpp/gra/BundleAdjustment.h delete mode 100644 meowpp/gra/BundleAdjustment_LM.h delete mode 100644 meowpp/gra/Camera.h delete mode 100644 meowpp/gra/Eye.h delete mode 100644 meowpp/gra/FeaturePoint.h delete mode 100644 meowpp/gra/FeaturePointsDetector.h delete mode 100644 meowpp/gra/FeaturePointsDetector_Harris.h delete mode 100644 meowpp/gra/FeaturePointsMatch.h delete mode 100644 meowpp/gra/FeaturePointsMatch_K_Match.h delete mode 100644 meowpp/gra/IdentityPoints.h delete mode 100644 meowpp/gra/Photo.h delete mode 100644 meowpp/gra/ViewPort.h delete mode 100644 meowpp/gra/WatchBall.h delete mode 100644 meowpp/math/!readme.asciidoc delete mode 100644 meowpp/math/LinearTransformation.h delete mode 100644 meowpp/math/LinearTransformations.h delete mode 100644 meowpp/math/Matrix.h delete mode 100644 meowpp/math/Transformation.h delete mode 100644 meowpp/math/Transformations.h delete mode 100644 meowpp/math/Vector.h delete mode 100644 meowpp/math/methods.h delete mode 100644 meowpp/math/utility.h delete mode 100644 meowpp/oo/!readme.asciidoc delete mode 100644 meowpp/oo/ObjArray.h delete mode 100644 meowpp/oo/ObjBase.h delete mode 100644 meowpp/oo/ObjDictionary.h delete mode 100644 meowpp/oo/ObjProperties.h delete mode 100644 meowpp/oo/ObjSelector.h delete mode 100644 meowpp/oo/ObjTypes.h delete mode 100644 meowpp/self.h delete mode 100644 meowpp/utility.h create mode 100644 meowpp/utility/factory.h create mode 100644 meowpp/utility/object.h create mode 100644 meowpp/utility/operation.h create mode 100644 meowpp/utility/pointer.h create mode 100644 meowpp/utility/self.h create mode 100644 meowpp/utility/state.h (limited to 'meowpp') diff --git a/meowpp/!readme.asciidoc b/meowpp/!readme.asciidoc deleted file mode 100644 index 0d9f0d8..0000000 --- a/meowpp/!readme.asciidoc +++ /dev/null @@ -1,20 +0,0 @@ - -meow for *C++ templates* - - -===== Self.h - -包含一個具有 *Copy On Write* 技術的 'class' 而且有實作 *by reference* , -基本上就是改良C\+\+原本的 reference 機制, 原本的 reference 只能在宣告的時候 -指定參照指向的變數, -而這邊則可以動態改變 - - -===== Usage.h - -方便user製作還算精美的 *usage document* 並且利用 `getopt()` 實作讀入參數與分析 - -===== utility.h - -一些不知道要歸類到哪的小functions - diff --git a/meowpp/Usage.h b/meowpp/Usage.h deleted file mode 100644 index d2becef..0000000 --- a/meowpp/Usage.h +++ /dev/null @@ -1,478 +0,0 @@ -#ifndef MEOW_USAGE_H__ -#define MEOW_USAGE_H__ - -#include "utility.h" - -#include - -#include -#include -#include -#include - -namespace meow { -/*! - * @brief 管理參數設置, 自訂usage document, 分析argc, argv - * - * \b Usage 是用來分析argc, argv和輸出usage document的class. \n - * argc, argv的部份, 有以下規則 - * - \b -c 其中 \a c 可以代換成一個字符, 這種選像可能是 \b 有設置 或 \b 沒設置 - * - \b -c \a value 附加一個 \a value , 這種選項可以是 \b 選擇性 或 - * \b 必要的 , 另外可以給定value的預設值以及哪些value是可接受 - * - \a value 其他, 一律視為 \b process \b arguments - * - * @author cathook - */ -class Usage { -private: - typedef std::string String; - typedef std::vector Strings; - //! 存 (value, description) - class Value { - private: - String value_; - String description_; - public: - Value() { } - Value(String const& value, String const& description) { - value_ = value; - description_ = stringReplace(description, "", value); - } - String usage() const { - return stringPrintf("%8s%s : %s\n", - " ", value_.c_str(), description_.c_str()); - } - String value() const { - return value_; - } - bool operator==(Value const& b) const { - return (value_ == b.value_); - } - }; - typedef std::vector Values; - //! 存 option, 其中可能有value可能沒有 - class Option { - private: - Strings values_; - Values values_accept_; - String value_default_; - String value_type_; - String description_; - bool has_value_; - bool has_setup_; - bool must_setup_; - public: - Option() { - } - Option(String const& description) { - has_setup_ = false; - has_value_ = false; - description_ = description; - must_setup_ = false; - } - Option(String const& description, - String const& type, - String const& default_value, - bool must) { - has_setup_ = false; - has_value_ = true; - description_ = description; - value_type_ = type; - value_default_ = default_value; - must_setup_ = must; - } - Strings const& values() const { - return values_; - } - String value(size_t index) const { - if (!has_value_) return ""; - if (!has_setup_ || index >= values_.size()) return value_default_; - return values_[index]; - } - ssize_t valueAdd(String const& value) { - if (!has_value_) { - has_setup_ = true; - return 0; - } - if (values_accept_.size() > 0 && - std::find(values_accept_.begin(), values_accept_.end(), - Value(value, "")) == values_accept_.end()) - return -1; - values_.push_back(value); - has_setup_ = true; - return values_.size() - 1; - } - bool valueAcceptAdd(String const& value, String const& description) { - if (!has_value_) return false; - if (std::find(values_accept_.begin(), values_accept_.end(), - Value(value, "")) == values_accept_.end()) { - values_accept_.push_back(Value(value, description)); - } - return true; - } - bool valueAcceptChk(String const& value) { - if (!has_value_) return false; - return (values_accept_.empty() || - std::find(values_accept_.begin(), values_accept_.end(), - Value(value, "")) != values_accept_.end()); - } - bool hasSetup() const{ return has_setup_; } - bool hasValue() const{ return has_value_; } - bool chkSetup() const{ return !(must_setup_ && !has_setup_); } - - String usage(String opt, bool detail) const { - String ret(stringPrintf("%s%s ", (opt.size()>1 ? "--":"-"), opt.c_str())); - if (!detail) { - if (has_value_) ret += value_type_; - if (!must_setup_) ret = "[" + ret + "]"; - } - else { - if (has_value_) { - ret += value_type_ + " "; - String default_string(""); - if (value_default_ != "") - default_string = "defalut='" + value_default_ + "'"; - String optional_string(""); - if (!must_setup_) - optional_string = "optional"; - String tmp; - if (default_string.size() + optional_string.size() > 0) { - if (default_string.size() > 0 && optional_string.size() > 0) { - ret += "(" + optional_string + ", " + default_string + ")"; - } - else { - ret += "(" + optional_string + default_string + ")"; - } - } - } - ret += "\n"; - String accept_string; - for (size_t i = 0; i < values_accept_.size(); i++) { - if (i > 0) - accept_string += (i + 1 < values_accept_.size() ? ", " : " or "); - accept_string += "'" + values_accept_[i].value() + "'"; - } - if (accept_string.size() == 0) accept_string = "... (anything)"; - ret += " " + stringReplace(stringReplace(description_, - "", - value_type_), - "", - accept_string) + "\n"; - for (size_t i = 0; i < values_accept_.size(); i++) { - ret += values_accept_[i].usage(); - } - ret += "\n"; - } - return ret; - } - }; - typedef std::map Options; - typedef Options:: iterator OptionsIterator; - typedef Options::const_iterator OptionsIteratorK; - - String name_; - Options options_; - Strings usage_begin_; - Strings usage_end_; - Strings proc_arguments_; -public: - /*! - * @brief constructor - * - * 所有說明文字中 \a \ 都會被代換成空字串 - */ - Usage() { - } - - /*! - * @brief constructor - * - * 所有說明文字中 \a "" 都會被代換成空字串 \b name - */ - Usage(String const& name) { - name_ = name; - } - - - /*! - * @brief constructor - * - * 將另一個usage原封不動的複製過來 - */ - Usage(Usage const& usage) { - name_ = usage.name_; - options_ = usage.options_; - usage_begin_ = usage.usage_begin_; - usage_end_ = usage.usage_end_; - proc_arguments_ = usage.proc_arguments_; - } - - /*! - * @brief 將另一個usage的設置匯入 - * - * @param [in] usage 另一個usage - * @return \c true/false 表示 \b 是否成功 - */ - bool import(Usage const& usage) { - for (OptionsIteratorK - it = usage.options_.begin(); it != usage.options_.end(); ++it) { - if (options_.find(it->first) != options_.end()) - return false; - } - for (OptionsIteratorK - it = usage.options_.begin(); it != usage.options_.end(); ++it) { - options_.insert(std::pair(it->first, it->second)); - } - for (size_t i = 0; i < usage.usage_begin_.size(); ++i) - usage_begin_.push_back(usage.usage_begin_[i]); - for (size_t i = 0; i < usage.usage_end_.size(); ++i) - usage_end_.push_back(usage.usage_end_[i]); - return true; - } - - /*! - * @brief 將另一個usage的選項設置加進來 - * - * @param [in] usage 另一個usage - * @return \c true/false 表 \b 是否成功 - */ - bool update(Usage const& usage) { - for (OptionsIteratorK - it = usage.options_.begin(); it != usage.options_.end(); ++it) { - OptionsIterator my = options_.find(it->first); - if (my == options_.end()) continue; - for (size_t i = 0, I = it->second.values().size(); i < I; ++i) { - my->second.valueAdd(it->second.value(i)); - } - } - return true; - } - - /*! - * @brief 新增一個沒有額外選項的選項 - * - * @param [in] opt 指定字符 - * @param [in] des 即description, 用來解釋這個選項的意義用的 - * @return \c true/false 表 \b 是否成功 - */ - bool optionAdd(String opt, String const& des) { - if (options_.find(opt) != options_.end()) return false; - options_.insert(std::pair(opt, Option(des))); - return true; - } - - /*! - * @brief 新增一個有額外選項的選項 - * - * @param [in] opt 指定字符 - * @param [in] des 即description, 用來解釋這個選項的意義用的 - * @param [in] val_type 表示額外選項的型態, 寫在USAGE裡面給人看用的 - * @param [in] val_default 預設值, 若為空字串則當作沒有預設值 - * @param [in] must 表示是否一定要設定 - * @return \c true/false 表 \b 是否成功 - */ - bool optionAdd(String opt, String const& des, - String const& val_type, - String const& val_default, - bool must) { - if (options_.find(opt) != options_.end()) return false; - options_.insert(std::pair( - opt, Option(des, val_type, val_default, must))); - return true; - } - - /*! - * @brief 針對-(opt)新增一個可接受的額外選項 - * - * @param [in] opt 指定字符 - * @param [in] val 額外選項 - * @param [in] des 關於此額外選項的說明 - * @return \c true/false 表 \b 是否成功 - */ - bool optionValueAcceptAdd(String opt, String const& val, String const& des) { - OptionsIterator o = options_.find(opt); - if (o == options_.end()) return false; - return o->second.valueAcceptAdd(val, des); - } - - /*! - * @brief 回傳是否有設定此選項 - * - * @param [in] opt 指定字符 - * @return \c true/false 表 \b 是否有設定此選項 - */ - bool hasOptionSetup(String opt) const { - OptionsIteratorK o = options_.find(opt); - return (o != options_.end() && o->second.hasSetup()); - } - - /*! - * @brief 回傳參數 \b -(opt) 被設置幾次 - * - * @param [in] opt 指定字符 - * @return 回傳次數 - */ - size_t optionValuesSize(String opt) const { - OptionsIteratorK o = options_.find(opt); - if (o == options_.end()) return 0; - return o->second.values().size(); - } - - /*! - * @brief 回傳參數 \b -(opt) 的第 \b index 個額外選項 - * - * @param [in] opt 指定字符 - * @param [in] index 第幾個 - * @return 回傳參數 \b -(opt) 的第 \b index 個額外選項 - */ - String optionValue(String opt, size_t index) const { - OptionsIteratorK o = options_.find(opt); - if (o == options_.end()) return String(); - return o->second.value(index); - } - - /*! - * @brief 取得有幾個process arguments - * - * @return 有幾個process arguments - */ - size_t procArgsSize() const { - return proc_arguments_.size(); - } - - /*! - * @brief 取得第i個process argument - * - * @param [in] index 第幾個 - * @return 回傳第 \a index 個 \b process \b argument - */ - String procArg(size_t index) const { - if (index >= proc_arguments_.size()) { - return String(); - } - return proc_arguments_[index]; - } - - /*! - * @brief 取得process arguments array - * - * @return 一個 \c std::vector , 包含所有 \b Process \b arguments - */ - Strings const& procArgs() const{ - return proc_arguments_; - } - - /*! - * @brief 新增一段usage document於每個選項逐條說明之前 - * - * @param [in] des 要新增的usage document - */ - void usageBeginAdd(String const& des) { - usage_begin_.push_back(stringReplace(des, "", name_)); - } - - /*! - * @brief 新增一段usage document於每個選項逐條說明之後 - * - * @param [in] des 要新增的usage document - */ - void usageEndAdd(String const& des) { - usage_end_.push_back(stringReplace(des, "", name_)); - } - - /*! - * @brief 回傳usage string - * - * @return \b usage \b string - */ - String usage() const { - Usage::String out = stringPrintf("USAGE\n %s", name_.c_str()); - for (OptionsIteratorK - it = options_.begin(); it != options_.end(); ++it) - out += " " + it->second.usage(it->first, false); - out += "\n\nDESCRIPTION\n"; - for (size_t i = 0; i < usage_begin_.size(); ++i) { - out += " " + usage_begin_[i] + "\n\n"; - } - for (OptionsIteratorK - it = options_.begin(); it != options_.end(); ++it) { - out += it->second.usage(it->first, true); - } - for (size_t i = 0; i < usage_end_.size(); ++i) { - out += " " + usage_end_[i] + "\n\n"; - } - return out; - } - - /*! - * @brief 給定argc, argv, 將各參數設置 - * @param [in] argc,argv - * @param [out] errmsg 將錯誤訊息寫到這裡 - * (若給定NULL pointer, 則會把錯誤訊息忽略) - * @return \c true/false \b 成功與否 (否的話代表有錯誤的設定值在其中) - */ - bool arguments(int argc, char** argv, String* errmsg) { - String zzz; - String& err = (errmsg == NULL ? zzz : *errmsg); - for (int i = 0; i < argc; ++i) { - if (argv[i][0] == '-') { - String opt; - if (argv[i][1] == '-') { // long option - if (argv[i][2] == '\0' || argv[i][3] == '\0') { - err = stringPrintf("Invalid option '%s'", argv[i]); - return false; - } - opt = String(argv[i] + 2); - } - else { // short option - if (argv[i][1] == '\0' || argv[i][2] != '\0') { - err = stringPrintf("Invalid option '%s'", argv[i]); - return false; - } - opt = String(argv[i] + 1); - } - OptionsIterator o = options_.find(opt); - if (o == options_.end()) { - err = stringPrintf("Unknown option '%s'", argv[i]); - return false; - } - if (o->second.hasValue()) { - if (i + 1 >= argc) { - err = stringPrintf("Option '%s' need a value", argv[i]); - return false; - } - if (o->second.valueAdd(argv[i + 1]) < 0) { - err = stringPrintf("Invalid value '%s' of options '%s'", - argv[i + 1], argv[i]); - return false; - } - ++i; - } - else { - o->second.valueAdd(""); - } - } - else { - if (i == 0) { - // TODO: remember who am I - } - else { - proc_arguments_.push_back(String(argv[i] + (argv[i][0]=='\\' ? 1:0))); - } - } - } - for (OptionsIteratorK it = options_.begin(); it != options_.end(); ++it) { - if (it->second.chkSetup() == false) { - err += stringPrintf("No specify argument to '%s%s'\n", - (it->first.size() > 1 ? "--" : "-"), - it->first.c_str()); - return false; - } - } - return true; - } -}; - -} // meow - -#endif // MEOW_USAGE_H__ diff --git a/meowpp/colors/!readme.asciidoc b/meowpp/colors/!readme.asciidoc deleted file mode 100644 index 28b097a..0000000 --- a/meowpp/colors/!readme.asciidoc +++ /dev/null @@ -1,78 +0,0 @@ - - -一些 *color space* 以及這些space的 *transformate function* 都放在這資料夾下 - -[NOTE] -目前transformation function的準確率還很低, 有待以後加強 - -===== Color3_Space.h - -`class Color3_Space` *Channel Number = 3* 的 Color Space 的共通 *Base class* - -===== RGB_Space.h - -Channel分別是 - -* Red -* Green -* Blue - -.Classes -* `meow::RGBi_Space` 用 'int' 存資料, 每個channel數值合法範圍是 *0~255* -* `meow::RGBf_Space` 用 'double' 存資料, 每個channel數值合法範圍是 *0.0~1.0* - -.Functions -* `meow::colorTransformation(in, *out)` for -** RGBi_Space <--> RGBf_Space - -===== YUV_Space.h - -Channel分別是 - -* Y 明度 -* U 色度 -* V 濃度 - -.Classes -* `meow::YUVf_Space` 用 'double' 存資料, 每個channel數值合法範圍是 *0~1.0* - -.Functions -* `meow::colorTransformation(in, *out)` for -** YUVf_Space <--> RGBi_Space -** YUVf_Space <--> RGBf_Space - -===== HSL_Space.h - -Channel分別是 - -* H 色調 -* S 飽和度 -* L 亮度 - -.Classes -* `meow::HSLf_Space` 用 'double' 存資料, 每個channel數值合法範圍是 *0~1.0* - -.Functions -* `meow::colorTransformation(in, *out)` for -** HSLf_Space <--> RGBi_Space -** HSLf_Space <--> RGBf_Space -** HSLf_Space <--> YUVf_Space - -===== HSV_Space.h - -Channel分別是 - -* H 色調 -* S 飽和度 -* V 亮度 - -.Classes -* `meow::HSVf_Space` 用 'double' 存資料, 每個channel數值合法範圍是 *0~1.0* - -.Functions -* `meow::colorTransformation(in, *out)` for -** HSVf_Space <--> RGBi_Space -** HSVf_Space <--> RGBf_Space -** HSVf_Space <--> YUVf_Space -** HSVf_Space <--> HSLf_Space - diff --git a/meowpp/colors/Color3_Space.h b/meowpp/colors/Color3_Space.h deleted file mode 100644 index 80a6b32..0000000 --- a/meowpp/colors/Color3_Space.h +++ /dev/null @@ -1,148 +0,0 @@ -#ifndef colors_Color3_Space_H__ -#define colors_Color3_Space_H__ - -#include "../geo/Vectors.h" -#include "../math/Matrix.h" -#include "../math/utility.h" - -#include - -namespace meow { - -/*! - * @brief Base class of color space with 3 channels. - * - * @author cat_leopard - */ -template -class Color3_Space { -protected: - Vector3D min_; - Vector3D max_; - Vector3D val_; - - /*! - * @brief Constructor - * - * @param [in] min_bound Minimum value of each channels. - * @param [in] max_bound Maximum value of each channels. - * @param [in] init_value Initial value of each channels. - */ - Color3_Space(Vector3D const& min_bound, - Vector3D const& max_bound, - Vector3D const& init_value): - min_(min_bound), max_(max_bound), val_(init_value) { - } - - /*! - * @brief Copy constructor - * - * @param [in] b Data to copy from. - */ - Color3_Space(Color3_Space const& b): - min_(b.min_), max_(b.max_), val_(b.val_) { - } - - /*! - * @brief Copy method - * - * We copy the value only, not include \c min_bound and \c max_bound. - * - * @param [in] b Value to copy from. - * @return \c *this - */ - Color3_Space& copyFrom(Color3_Space const& b) { - val_ = b.val_; - return *this; - } -public: - //! @brief Destructor - virtual ~Color3_Space() { } - - //! @brief minimum bound of each channels. - Vector3D const& minV() const { - return min_; - } - - //! @brief maximum bound of each channels. - Vector3D const& maxV() const { - return max_; - } - - //! @brief value of each channels. - Vector3D const& valV() const { - return val_; - } - - /*! - * @brief Set the value of each channels. - * - * @param [in] vv new value - * @return new value - */ - Vector3D const& valV(Vector3D const& vv) { - val_ = vv; - return val(); - } - - //! @brief Get the non-constant reference of each channels. - Vector3D& valVGet() { - return val_; - } - - /*! - * @brief Return the minimum of the \c i -th channel. - * - * @param [in] id index of the channel. - * @return new value - */ - T const& min(size_t id) const { return minV()(id); } - - /*! - * @brief Return the maximum of the \c i -th channel. - * - * @param [in] id index of the channel. - * @return new value - */ - T const& max(size_t id) const { - return maxV()(id); - } - - /*! - * @brief Return the value of the \c i -th channel. - * - * @param [in] id index of the channel. - * @return new value - */ - T const& val(size_t id) const { - return valV()(id); - } - - /*! - * @brief Set the value of \c i -th channel. - * - * @param [in] i index of the channel - * @param [in] c new value - */ - T const& val(size_t i, T const& c) { - if (i == 0) val_.x(c); - else if (i == 1) val_.y(c); - else if (i == 2) val_.z(c); - return val(i); - } - - /*! - * @brief Get the non-constant reference of value of the \c i -th channel. - * - * @param [in] id index of the channel - */ - T& valGet(size_t id) { - if (id == 0) return valVGet().xGet(); - else if (id == 1) return valVGet().yGet(); - else return valVGet().zGet(); - } -}; - -} // meow - -#endif // colors_Color3_Space_H__ diff --git a/meowpp/colors/HSL_Space.h b/meowpp/colors/HSL_Space.h deleted file mode 100644 index 8041575..0000000 --- a/meowpp/colors/HSL_Space.h +++ /dev/null @@ -1,195 +0,0 @@ -#ifndef colors_HSL_Space_H__ -#define colors_HSL_Space_H__ - -#include "Color3_Space.h" -#include "RGB_Space.h" -#include "YUV_Space.h" - -#include "../geo/Vectors.h" -#include "../math/utility.h" - -#include - -namespace meow { - -/*! - * @brief 以浮點數\b Y(亮度), \b U(色度), \b V(濃度) 三個值所組成的色彩空間 - * - * 其中範圍都介於0.0~1.0之間 - * - * @author cat_leopard - */ -class HSLf_Space: public Color3_Space { -public: - HSLf_Space(): Color3_Space(Vector3D( 0.0, 0.0, 0.0), - Vector3D(PI * 2.0, 1.0, 1.0), - Vector3D( 0.0, 0.0, 0.0)) { - } - HSLf_Space(double c): Color3_Space(Vector3D( 0.0, 0.0, 0.0), - Vector3D(PI*2.0, 1.0, 1.0), - Vector3D( c, c, c)) - { } - HSLf_Space(Vector3D const& v): - Color3_Space(Vector3D(0.0, 0.0, 0.0), - Vector3D(1.0, 1.0, 1.0), - Vector3D(v)) { - } - HSLf_Space(HSL_Space const& b): Color3_Space(b) { - } - ~HSLf_Space() { - } - double const& hslMin(size_t i) const { return min(i); } - double const& hMin( ) const { return min(0); } - double const& sMin( ) const { return min(1); } - double const& lMin( ) const { return min(2); } - double const& hslMax(size_t i) const { return max(i); } - double const& hMax( ) const { return max(0); } - double const& sMax( ) const { return max(1); } - double const& lMax( ) const { return max(2); } - double const& hsl(size_t i) const { return val(i); } - double const& h( ) const { return hsl(0); } - double const& s( ) const { return hsl(1); } - double const& l( ) const { return hsl(2); } - double const& hsl(size_t i, double c) { return val(i, c); } - double const& h( double c) { return hsl(0, c); } - double const& s( double c) { return hsl(1, c); } - double const& l( double c) { return hsl(2, c); } - double& hslGet(size_t i) { return valGet(i); } - double& hGet( ) { return hslGet(0); } - double& sGet( ) { return hslGet(1); } - double& lGet( ) { return hslGet(2); } - HSLf_Space& operator=(HSLf_Space const& b) { - copyFrom(b); - return *this; - } - HSLf_Space operator+(HSLf_Space const& b) const { - return HSLf_Space(val_ + b.val_); - } - HSLf_Space operator-(HSLf_Space const& b) const { - return HSLf_Space(val_ - b.val_); - } - HSLf_Space operator*(double const& c) const { - return HSLf_Space(val_ * c); - } - HSLf_Space operator/(double const& c) const { - return HSLf_Space(val_ / c); - } - double operator*(HSLf_Space const& b) const { - return val_ * b.val_; - } -}; - -/*! - * @brief \c HSLf_Space to \c HSLf_Space - */ -inline void colorTransformate(HSLf_Space const& in, HSLf_Space* out) { - *out = in; -} - -/*! - * @brief \c RGBf_Space to \c HSLf_Space - */ -inline void colorTransformate(RGBf_Space const& rgb, HSLf_Space* hsl) { - double r = normalize(rgb.rMin(), rgb.rMax(), rgb.r()); - double g = normalize(rgb.gMin(), rgb.gMax(), rgb.g()); - double b = normalize(rgb.bMin(), rgb.bMax(), rgb.b()); - double mx = std::max(std::max(r, g), b); - double mn = std::min(std::min(r, g), b); - double h, s, l; - if (mx == mn ) h = 0; - else if(mx == r && g >= b) h = PI/3.0 * (g-b) / (mx-mn); - else if(mx == r && g < b) h = PI/3.0 * (g-b) / (mx-mn) + PI * 2.0; - else if(mx == g ) h = PI/3.0 * (b-r) / (mx-mn) + PI/3.0*2.0; - else h = PI/3.0 * (r-g) / (mx-mn) + PI/3.0*4.0; - l = 0.5 * (mx + mn); - if (l == 0 || mx == mn) s = 0; - else if(l < 0.5 ) s = (mx - mn) / (2.0 * l); - else s = (mx - mn) / (2 - 2.0 * l); - hsl->h(h); - hsl->s(s); - hsl->l(l); -} - -/*! - * @brief \c YUVf_Space to \c HSLf_Space - */ -inline void colorTransformate(YUVf_Space const& yuv, HSLf_Space* hsl) { - RGBf_Space tmp; - colorTransformate(yuv, &tmp); - colorTransformate(tmp, hsl); -} - -/*! - * @brief \c HSLf_Space to \c RGBf_Space - */ -inline void colorTransformate(HSLf_Space const& hsl, RGBf_Space* rgb) { - double h = normalize(hsl.hMin(), hsl.hMax(), hsl.h()); - double s = normalize(hsl.sMin(), hsl.sMax(), hsl.s()); - double l = normalize(hsl.lMin(), hsl.lMax(), hsl.l()); - if(s == 0){ - rgb->r(denormalize(rgb->rMin(), rgb->rMax(), l)); - rgb->g(denormalize(rgb->gMin(), rgb->gMax(), l)); - rgb->b(denormalize(rgb->bMin(), rgb->bMax(), l)); - return ; - } - double q = (l < 0.5 ? (l * (1 + s)) : (l + s - (l * s))); - double p = 2 * l - q; - double t_r = h + 1.0 / 3.0; - double t_g = h; - double t_b = h - 1.0 / 3.0; - if(t_r < 0) t_r = t_r + 1.0; - if(t_r > 1) t_r = t_r - 1.0; - if(t_g < 0) t_g = t_g + 1.0; - if(t_g > 1) t_g = t_g - 1.0; - if(t_b < 0) t_b = t_b + 1.0; - if(t_b > 1) t_b = t_b - 1.0; - double r, g, b; - if (t_r < 1.0 / 6.0) r = p + (q - p) * 6 * t_r; - else if(t_r < 0.5 ) r = q; - else if(t_r < 2.0 / 3.0) r = p + (q - p) * 6 * (2.0 / 3.0 - t_r); - else r = p; - if (t_g < 1.0 / 6.0) g = p + (q - p) * 6 * t_g; - else if(t_g < 0.5 ) g = q; - else if(t_g < 2.0 / 3.0) g = p + (q - p) * 6 * (2.0 / 3.0 - t_g); - else g = p; - if (t_b < 1.0 / 6.0) b = p + (q - p) * 6 * t_b; - else if(t_b < 0.5 ) b = q; - else if(t_b < 2.0 / 3.0) b = p + (q - p) * 6 * (2.0 / 3.0 - t_b); - else b = p; - rgb->r(denormalize(rgb->rMin(), rgb->rMax(), r)); - rgb->g(denormalize(rgb->gMin(), rgb->gMax(), g)); - rgb->b(denormalize(rgb->bMin(), rgb->bMax(), b)); -} - -/*! - * @brief \c HSLf_Space to \c YUVf_Space - */ -inline void colorTransformate(HSLf_Space const& hsl, YUVf_Space* yuv) { - RGBf_Space tmp; - colorTransformate(hsl, &tmp); - colorTransformate(tmp, yuv); -} - -/*! - * @brief \c HSLf_Space to \c RGBi_Space - */ -inline void colorTransformate(HSLf_Space const& hsl, RGBi_Space* rgb) { - RGBf_Space tmp; - colorTransformate(hsl, &tmp); - rgb->copyFrom(tmp); -} - - -/*! - * @brief \c RGBi_Space to \c HSLf_Space - */ -inline void colorTransformate(RGBi_Space const& rgb, HSLf_Space* hsl) { - RGBf_Space tmp; - tmp.copyFrom(rgb); - colorTransformate(rgb, hsl); -} - -} // meow - - -#endif // colors_HSL_Space_H__ diff --git a/meowpp/colors/HSV_Space.h b/meowpp/colors/HSV_Space.h deleted file mode 100644 index 4a5d24e..0000000 --- a/meowpp/colors/HSV_Space.h +++ /dev/null @@ -1,195 +0,0 @@ -#ifndef colors_HSV_Space_H__ -#define colors_HSV_Space_H__ - -#include "Color3_Space.h" -#include "../geo/Vectors.h" - -#include "RGB_Space.h" -#include "YUV_Space.h" -#include "HSL_Space.h" -#include "../math/utility.h" - -#include - -namespace meow { - -/*! - * @brief 以浮點數\b Y(亮度), \b U(色度), \b V(濃度) 三個值所組成的色彩空間 - * - * 其中範圍都介於0.0~1.0之間 - * - * @author cat_leopard - */ -class HSVf_Space: public Color3_Space { -public: - HSVf_Space(): Color3_Space(Vector3D( 0.0, 0.0, 0.0), - Vector3D(PI*2.0, 1.0, 1.0), - Vector3D( 0.0, 0.0, 0.0)) { - } - HSVf_Space(double c): Color3_Space(Vector3D( 0.0, 0.0, 0.0), - Vector3D(PI*2.0, 1.0, 1.0), - Vector3D( c, c, c)) - { } - HSVf_Space(Vector3D const& v): - Color3_Space(Vector3D(0.0, 0.0, 0.0), - Vector3D(1.0, 1.0, 1.0), - Vector3D(v)) { - } - HSVf_Space(HSV_Space const& b): Color3_Space(b) { - } - ~HSVf_Space() { - } - double const& hsvMin(size_t i) const { return min(i); } - double const& hMin( ) const { return min(0); } - double const& sMin( ) const { return min(1); } - double const& vMin( ) const { return min(2); } - double const& hsvMax(size_t i) const { return max(i); } - double const& hMax( ) const { return max(0); } - double const& sMax( ) const { return max(1); } - double const& vMax( ) const { return max(2); } - double const& hsv(size_t i) const { return val(i); } - double const& h( ) const { return hsv(0); } - double const& s( ) const { return hsv(1); } - double const& v( ) const { return hsv(2); } - double const& hsv(size_t i, double c) { return val(i, c); } - double const& h( double c) { return hsv(0, c); } - double const& s( double c) { return hsv(1, c); } - double const& v( double c) { return hsv(2, c); } - double& hsvGet(size_t i) { return valGet(i); } - double& hGet( ) { return hsvGet(0); } - double& sGet( ) { return hsvGet(1); } - double& vGet( ) { return hsvGet(2); } - HSVf_Space& operator=(HSVf_Space const& b) { - copyFrom(b); - return *this; - } - HSVf_Space operator+(HSVf_Space const& b) const { - return HSVf_Space(val_ + b.val_); - } - HSVf_Space operator-(HSVf_Space const& b) const { - return HSVf_Space(val_ - b.val_); - } - HSVf_Space operator*(double const& c) const { - return HSVf_Space(val_ * c); - } - HSVf_Space operator/(double const& c) const { - return HSVf_Space(val_ / c); - } - double operator*(HSVf_Space const& b) const { - return val_ * b.val_; - } -}; - -/*! - * @brief \c HSVf_Space to \c HSVf_Space - */ -inline void colorTransformate(HSVf_Space const& in, HSVf_Space* out) { - *out = in; -} - -/*! - * @brief \c RGBf_Space to \c HSVf_Space - */ -inline void colorTransformate(RGBf_Space const& rgb, HSVf_Space* hsv) { - double r = normalize(rgb.rMin(), rgb.rMax(), rgb.r()); - double g = normalize(rgb.gMin(), rgb.gMax(), rgb.g()); - double b = normalize(rgb.bMin(), rgb.bMax(), rgb.b()); - double mx = std::max(std::max(r, g), b); - double mn = std::min(std::min(r, g), b); - double h, s, v; - if (mx == mn ) h = 0; - else if(mx == r && g >= b) h = PI/3.0 * (g-b) / (mx-mn); - else if(mx == r && g < b) h = PI/3.0 * (g-b) / (mx-mn) + PI * 2.0; - else if(mx == g ) h = PI/3.0 * (b-r) / (mx-mn) + PI/3.0*2.0; - else h = PI/3.0 * (r-g) / (mx-mn) + PI/3.0*4.0; - if(mx == 0) s = 0; - else s = 1 - mn / mx; - v = mx; - hsv->h(h); - hsv->s(s); - hsv->v(v); -} - -/*! - * @brief \c YUVf_Space to \c HSVf_Space - */ -inline void colorTransformate(YUVf_Space const& yuv, HSVf_Space* hsv) { - RGBf_Space tmp; - colorTransformate( yuv, &tmp); - colorTransformate(*tmp, hsv); -} - -/*! - * @brief \c HSLf_Space to \c HSVf_Space - */ -inline void colorTransformate(HSLf_Space const& hsl, HSVf_Space* hsv) { - RGBf_Space tmp; - colorTransformate( hsl, &tmp); - colorTransformate(*tmp, hsv); -} - -/*! - * @brief \c HSVf_Space to \c RGBf_Space - */ -inline void colorTransformate(HSVf_Space const& hsv, RGBf_Space* rgb) { - double h = normalize(hsv.hMin(), hsv.hMax(), hsv.h()) * 360; - double s = normalize(hsv.sMin(), hsv.sMax(), hsv.s()); - double v = normalize(hsv.vMin(), hsv.vMax(), hsv.v()); - int hi = (int)h / 60 % 6; - double f = h / 60.0 - hi; - double p = v * (1 - s); - double q = v * (1 - f * s); - double t = v * (1 - (1 - f) * s); - double r, g, b; - if (hi == 0){ r = v; g = t; b = p; } - else if(hi == 1){ r = q; g = v; b = p; } - else if(hi == 2){ r = p; g = v; b = t; } - else if(hi == 3){ r = p; g = q; b = v; } - else if(hi == 4){ r = t; g = p; b = v; } - else { r = v; g = p; b = q; } - rgb->r(denormalize(rgb->rMin(), rgb->rMax(), r)); - rgb->g(denormalize(rgb->gMin(), rgb->gMax(), g)); - rgb->b(denormalize(rgb->bMin(), rgb->bMax(), b)); -} - -/*! - * @brief \c HSVf_Space to \c YUVf_Space - */ -inline void colorTransformate(HSVf_Space const& hsv, YUVf_Space* yuv) { - RGBf_Space tmp; - colorTransformate( hsv, &tmp); - colorTransformate(*tmp, yuv); -} - -/*! - * @brief \c HSVf_Space to \c HSLf_Space - */ -inline void colorTransformate(HSVf_Space const& hsv, HSLf_Space* hsl) { - RGBf_Space tmp; - colorTransformate( hsv, &tmp); - colorTransformate(*tmp, hsl); -} - -/*! - * @brief \c HSVf_Space to \c RGBi_Space - */ -inline void colorTransformate(HSVf_Space const& hsv, RGBi_Space* rgb) { - RGBf_Space tmp; - colorTransformate(hsv, &tmp); - rgb->copyFrom(tmp); -} - - -/*! - * @brief \c RGBi_Space to \c HSVf_Space - */ -inline void colorTransformate(RGBi_Space const& rgb, HSVf_Space* hsv) { - RGBf_Space tmp; - tmp.copyFrom(rgb); - colorTransformate(rgb, hsv); -} - -} // meow - - -#endif // colors_HSV_Space_H__ diff --git a/meowpp/colors/RGB_Space.h b/meowpp/colors/RGB_Space.h deleted file mode 100644 index 2faac27..0000000 --- a/meowpp/colors/RGB_Space.h +++ /dev/null @@ -1,182 +0,0 @@ -#ifndef colors_RGB_Space_H__ -#define colors_RGB_Space_H__ - -#include "Color3_Space.h" -#include "../geo/Vectors.h" -#include "../math/utility.h" - -#include - -namespace meow { - -/*! - * @brief 以整數 \b Red, \b Green, \b Blue 三個值所組成的色彩空間 - * - * 其中範圍都介於0~255之間 - * - * @author cat_leopard - */ -class RGBi_Space: public Color3_Space { -public: - RGBi_Space(): Color3_Space(Vector3D( 0, 0, 0), - Vector3D(255, 255, 255), - Vector3D( 0, 0, 0)) { - } - RGBi_Space(int c): Color3_Space(Vector3D( 0, 0, 0), - Vector3D(255, 255, 255), - Vector3D( c, c, c)) { - } - RGBi_Space(Vector3D const& v): - Color3_Space(Vector3D( 0, 0, 0), - Vector3D(255, 255, 255), - Vector3D(v)) { - } - RGBi_Space(RGBi_Space const& b): Color3_Space(b) { - } - ~RGBi_Space() { - } - int const& rgbMin(size_t i) const { return min(i); } - int const& rMin( ) const { return min(0); } - int const& gMin( ) const { return min(1); } - int const& bMin( ) const { return min(2); } - int const& rgbMax(size_t i) const { return max(i); } - int const& rMax( ) const { return max(0); } - int const& gMax( ) const { return max(1); } - int const& bMax( ) const { return max(2); } - int const& rgb(size_t i) const { return val(i); } - int const& r( ) const { return rgb(0); } - int const& g( ) const { return rgb(1); } - int const& b( ) const { return rgb(2); } - int const& rgb(size_t i, int c) { return val(i, c); } - int const& r( int c) { return rgb(0, c); } - int const& g( int c) { return rgb(1, c); } - int const& b( int c) { return rgb(2, c); } - int& rgbGet(size_t i) { return valGet(i); } - int& rGet( ) { return rgbGet(0); } - int& gGet( ) { return rgbGet(1); } - int& bGet( ) { return rgbGet(2); } - RGBi_Space& operator=(RGBi_Space const& b) { - copyFrom(b); - return *this; - } - RGBi_Space operator+(RGBi_Space const& b) const { - return RGBi_Space(val_ + b.val_); - } - RGBi_Space operator-(RGBi_Space const& b) const { - return RGBi_Space(val_ - b.val_); - } - RGBi_Space operator*(int c) const { - return RGBi_Space(val_ * c); - } - RGBi_Space operator/(int c) const { - return RGBi_Space(val_ / c); - } - int operator*(RGBi_Space const& b) const { - return val_ * b.val_; - } -}; - -/*! - * @brief 以浮點數\b Red, \b Green, \b Blue 三個值所組成的色彩空間 - * - * 其中範圍都介於0.0~1.0之間 - * - * @author cat_leopard - */ -class RGBf_Space: public Color3_Space { -public: - RGBf_Space(): Color3_Space(Vector3D(0.0, 0.0, 0.0), - Vector3D(1.0, 1.0, 1.0), - Vector3D(0.0, 0.0, 0.0)) { - } - RGBf_Space(double c): Color3_Space(Vector3D(0.0, 0.0, 0.0), - Vector3D(1.0, 1.0, 1.0), - Vector3D( c, c, c)) { - } - RGBf_Space(Vector3D const& v): - Color3_Space(Vector3D(0.0, 0.0, 0.0), - Vector3D(1.0, 1.0, 1.0), - Vector3D(v)) { - } - RGBf_Space(RGBf_Space const& b): Color3_Space(b) { - } - ~RGBf_Space() { - } - double const& rgbMin(size_t i) const { return min(i); } - double const& rMin( ) const { return min(0); } - double const& gMin( ) const { return min(1); } - double const& bMin( ) const { return min(2); } - double const& rgbMax(size_t i) const { return max(i); } - double const& rMax( ) const { return max(0); } - double const& gMax( ) const { return max(1); } - double const& bMax( ) const { return max(2); } - double const& rgb(size_t i) const { return val(i); } - double const& r( ) const { return rgb(0); } - double const& g( ) const { return rgb(1); } - double const& b( ) const { return rgb(2); } - double const& rgb(size_t i, double c) { return val(i, c); } - double const& r( double c) { return rgb(0, c); } - double const& g( double c) { return rgb(1, c); } - double const& b( double c) { return rgb(2, c); } - double& rgbGet(size_t i) { return valGet(i); } - double& rGet( ) { return rgbGet(0); } - double& gGet( ) { return rgbGet(1); } - double& bGet( ) { return rgbGet(2); } - RGBf_Space& operator=(RGBf_Space const& b) { - copyFrom(b); - return *this; - } - RGBf_Space operator+(RGBf_Space const& b) const { - return RGBf_Space(val_ + b.val_); - } - RGBf_Space operator-(RGBf_Space const& b) const { - return RGBf_Space(val_ - b.val_); - } - RGBf_Space operator*(double const& c) const { - return RGBf_Space(val_ * c); - } - RGBf_Space operator/(double const& c) const { - return RGBf_Space(val_ / c); - } - double operator*(RGBf_Space const& b) const { - return val_ * b.val_; - } -}; - -/*! - * @brief \c RGBf_Space to \c RGBf_Space - */ -inline void colorTransformate(RGBf_Space const& in, RGBf_Space* out) { - *out = in; -} - -/*! - * @brief \c RGBi_Space to \c RGBi_Space - */ -inline void colorTransformate(RGBi_Space const& in, RGBi_Space* out) { - *out = in; -} - -/*! - * @brief \c RGBi_Space to \c RGBf_Space - */ -inline void colorTransformate(RGBi_Space const& a, RGBf_Space* b) { - for (size_t i = 0; i < 3; ++i) { - b->rgb(i, ratioMapping(a.rgbMin(i), a.rgbMax(i), a.rgb(i), - b->rgbMin(i), b->rgbMax(i))); - } -} - -/*! - * @brief \c RGBf_Space to \c RGBi_Space - */ -inline void colorTransformate(RGBf_Space const& a, RGBi_Space* b) { - for (size_t i = 0; i < 3; ++i) { - b->rgb(i, ratioMapping(a.rgbMin(i), a.rgbMax(i), a.rgb(i), - b->rgbMin(i), b->rgbMax(i))); - } -} - -} // meow - -#endif // colors_RGB_Space_H__ diff --git a/meowpp/colors/YUV_Space.h b/meowpp/colors/YUV_Space.h deleted file mode 100644 index e5df6a2..0000000 --- a/meowpp/colors/YUV_Space.h +++ /dev/null @@ -1,138 +0,0 @@ -#ifndef colors_YUV_Space_H__ -#define colors_YUV_Space_H__ - -#include "Color3_Space.h" -#include "../geo/Vectors.h" - -#include "RGB_Space.h" -#include "../math/utility.h" - -#include - -namespace meow { - -/*! - * @brief 以浮點數\b Y(亮度), \b U(色度), \b V(濃度) 三個值所組成的色彩空間 - * - * 其中範圍都介於0.0~1.0之間 - * - * @author cat_leopard - */ -class YUVf_Space: public Color3_Space { -public: - YUVf_Space(): Color3_Space(Vector3D(0.0, 0.0, 0.0), - Vector3D(1.0, 1.0, 1.0), - Vector3D(0.0, 0.0, 0.0)) { - } - YUVf_Space(double c): Color3_Space(Vector3D(0.0, 0.0, 0.0), - Vector3D(1.0, 1.0, 1.0), - Vector3D( c, c, c)) { - } - YUVf_Space(Vector3D const& v): - Color3_Space(Vector3D(0.0, 0.0, 0.0), - Vector3D(1.0, 1.0, 1.0), - Vector3D(v)) { - } - YUVf_Space(YUV_Space const& b): Color3_Space(b) { - } - ~YUVf_Space() { - } - double const& yuvMin(size_t i) const { return min(i); } - double const& yMin( ) const { return min(0); } - double const& uMin( ) const { return min(1); } - double const& vMin( ) const { return min(2); } - double const& yuvMax(size_t i) const { return max(i); } - double const& yMax( ) const { return max(0); } - double const& uMax( ) const { return max(1); } - double const& vMax( ) const { return max(2); } - double const& yuv(size_t i) const { return val(i); } - double const& y( ) const { return yuv(0); } - double const& u( ) const { return yuv(1); } - double const& v( ) const { return yuv(2); } - double const& yuv(size_t i, double c) { return val(i, c); } - double const& y( double c) { return yuv(0, c); } - double const& u( double c) { return yuv(1, c); } - double const& v( double c) { return yuv(2, c); } - double& yuvGet(size_t i) { return valGet(i); } - double& yGet( ) { return yuvGet(0); } - double& uGet( ) { return yuvGet(1); } - double& vGet( ) { return yuvGet(2); } - YUVf_Space& operator=(YUVf_Space const& b) { - copyFrom(b); - return *this; - } - YUVf_Space operator+(YUVf_Space const& b) const { - return YUVf_Space(val_ + b.val_); - } - YUVf_Space operator-(YUVf_Space const& b) const { - return YUVf_Space(val_ - b.val_); - } - YUVf_Space operator*(double const& c) const { - return YUVf_Space(val_ * c); - } - YUVf_Space operator/(double const& c) const { - return YUVf_Space(val_ / c); - } - double operator*(YUVf_Space const& b) const { - return val_ * b.val_; - } -}; - -/*! - * @brief \c YUVf_Space to \c YUVf_Space - */ -inline void colorTransformate(YUVf_Space const& in, YUVf_Space* out) { - *out = in; -} - -/*! - * @brief \c RGBf_Space to \c YUVf_Space - */ -inline void colorTransformate(RGBf_Space const& rgb, YUVf_Space* yuv) { - double r = normalize(rgb.rMin(), rgb.rMax(), rgb.r()); - double g = normalize(rgb.gMin(), rgb.gMax(), rgb.g()); - double b = normalize(rgb.bMin(), rgb.bMax(), rgb.b()); - double y = 0.299 * r + 0.587 * g + 0.114 * b; - double u = -0.169 * r - 0.331 * g + 0.500 * b + 0.5; - double v = 0.500 * r - 0.419 * g - 0.081 * b + 0.5; - yuv->y(denormalize(yuv->yMin(), yuv->yMax(), y)); - yuv->u(denormalize(yuv->uMin(), yuv->uMax(), u)); - yuv->v(denormalize(yuv->vMin(), yuv->vMax(), v)); -} - -/*! - * @brief \c YUVf_Space to \c RGBf_Space - */ -inline void colorTransformate(YUVf_Space const& yuv, RGBf_Space* rgb) { - double y = normalize(yuv.yMin(),yuv.yMax(),yuv.y()); - double u = normalize(yuv.uMin(),yuv.uMax(),yuv.u()); - double v = normalize(yuv.vMin(),yuv.vMax(),yuv.v()); - double r = y - 0.00093 * (u - 0.5) + 1.401687 * (v - 0.5); - double g = y - 0.34370 * (u - 0.5) - 0.714170 * (v - 0.5); - double b = y + 1.77216 * (u - 0.5) - 0.000990 * (v - 0.5); - rgb->r(denormalize(rgb->rMin(), rgb->rMax(), r)); - rgb->g(denormalize(rgb->gMin(), rgb->gMax(), g)); - rgb->b(denormalize(rgb->bMin(), rgb->bMax(), b)); -} - -/*! - * @brief \c RGBi_Space to \c YUVf_Space - */ -inline void colorTransformate(RGBi_Space const& rgb, YUVf_Space* yuv) { - RGBf_Space tmp; - tmp.copyFrom(rgb); - colorTransformate(tmp, yuv); -} - -/*! - * @brief \c YUVf_Space to \c RGBi_Space - */ -inline void colorTransformate(YUVf_Space const& yuv, RGBi_Space* rgb) { - RGBf_Space tmp; - colorTransformate(yuv, &tmp); - rgb->copyFrom(tmp); -} - -} // meow - -#endif // colors_YUV_H__ diff --git a/meowpp/debug/assert.h b/meowpp/debug/assert.h new file mode 100644 index 0000000..30659b7 --- /dev/null +++ b/meowpp/debug/assert.h @@ -0,0 +1,76 @@ +/*! + * @file assert.h + * @brief Contains assert macro for meowpp's debugging tools. + * + * You can use + * @code{.cpp} + * #define MEOWPP_NODEBUG + * @endcode + * to remove all the debugging code. + * + * @author cathook + */ + +#ifndef __MEOWPP_ASSERT_H__ +#define __MEOWPP_ASSERT_H__ + +#include +#include + + +namespace meow { + + +/*! + * @def Assert + * @brief A macro for assert whether a expression is failed or not. + * @param expr The expression to be tested. + * @param ... Error information to be printed to stderr when the expr is failed. + * + * When expression is failed, it will call `fprintf(stderr, ...)` to print out + * the message follows by calling `abort()` to halt the program. + * + * @note You can use + * @code{.cpp} + * #define MEOWPP_TESTING + * @endcode + * to tell this macro calls `test::abort()` instead of normal `abort()` + * function. + */ + + +#ifndef MEOWPP_NODEBUG + +#define MEOWPP_STRINGIFY(x) #x +#define MEOWPP_TOSTRING(x) MEOWPP_STRINGIFY(x) + +#ifndef MEOWPP_DEBUG_ASSERT_TESTING + +#define Assert(expr,...) \ + while (((expr) || \ + (fprintf(stderr, "Assertion error at " \ + __FILE__ ":" MEOWPP_TOSTRING(__LINE__) \ + " >>>" __VA_ARGS__), \ + abort(), false)) && false) + +#else // MEOWPP_DEBUG_ASSERT_TESTING + +#define Assert(expr,...) \ + while (((expr) || \ + (fprintf(stderr, "Assertion error at " \ + __FILE__ ":" MEOWPP_TOSTRING(__LINE__) \ + " >>> " __VA_ARGS__), \ + test::abort(), false)) && false) + +#endif // MEOWPP_DEBUG_ASSERT_TESTING + +#else // MEOWPP_NODEBUG + +#define Assert(expr,...) \ + while (false) + +#endif // MEOWPP_NODEBUG + +} // meow + +#endif // __MEOWPP_ASSERT_H__ diff --git a/meowpp/dsa/!readme.asciidoc b/meowpp/dsa/!readme.asciidoc deleted file mode 100644 index d6eb3d7..0000000 --- a/meowpp/dsa/!readme.asciidoc +++ /dev/null @@ -1,57 +0,0 @@ - - -包含一些資料結構 - -===== BinaryIndexTree.h - -極度簡化的 *SegmentTree* 已無區間更新的操作. - -.Classes -* `meow::BinaryIndexTree` - -===== DisjointSet.h - -用來維護一堆互斥集的資訊. - -.Classes -* `meow::DisjointSet` - -===== HashTable.h - -就是傳說中的HashTable - -.Classes -* `meow::HashTableList` - -===== KD_Tree.h - -查詢第k近鄰居用的 - -.Classes -* `meow::KD_Tree` - -===== MergeableHeap.h - -可合併Heap - -.Classes -* `meow::MergeableHeap` - -===== SegmentTree.h - -線段樹 -.Classes -* `meow::SegmentTree` - -===== SplayTree.h - -伸展樹, 比一般平衡樹稍強的東東 -* `meow::SplayTree` -* `meow::SplayTree_Range` - -===== VP_Tree.h - -查詢第k近鄰居用的 - -.Classes -* `meow::VP_Tree` diff --git a/meowpp/dsa/BinaryIndexTree.h b/meowpp/dsa/BinaryIndexTree.h deleted file mode 100644 index 1d2d9e8..0000000 --- a/meowpp/dsa/BinaryIndexTree.h +++ /dev/null @@ -1,102 +0,0 @@ -#ifndef dsa_BinaryIndexTree_H__ -#define dsa_BinaryIndexTree_H__ - -#include - -#include -#include - -namespace meow { - -template -/*! - * @brief 極度簡化的 \c SegmentTree 已無區間更新的操作 - * - * 一般來說只能用在維護區間總和, 維護區間最大值只有在特殊情況才可以, 即 - * \b 針對每個元素, \b 每次update() \b 的值一定會大於等於原本的值 . - * 若要用區間最大值 , 則 \a Value 的 \c operator+ 要寫成 \c std::max(...) - * - * @author cat_leopard - */ -class BinaryIndexTree { -private: - std::vector array_; -public: - /*! - * @brief constructor - */ - BinaryIndexTree() { - } - - /*! - * @brief constructor - * - * @param [in] size 要維護的區間大小 \b [0,size) - * @param [in] value 預設值 - */ - BinaryIndexTree(size_t size, Value const& value): - array_(size, value) { - } - - /*! - * @brief constructor - * - * 將另一個 \c BinaryIndexTree 原封不動的複製過來 - * @param [in] tree2 另外一個 \c BinaryIndexTree - */ - BinaryIndexTree(BinaryIndexTree const& tree2): - array_(tree2.array_) { - } - - /*! - * @brief 將資料洗掉, 重設 - * - * 時間複雜度\b O(N) - * - * @param [in] size 要維護的區間大小 \b [0,size) - * @param [in] init 預設值 - * @return 無 - */ - void reset(size_t size, Value const& init) { - array_.clear(); - array_.resize(size, init); - } - - /*! - * @brief 將array中第 \a index (從零算起)個element多加上指定的值 - * - * 時間複雜度\b O(logN) - * - * @param [in] index 指定的index - * @param [in] value 指定的值 - * @return 無 - */ - void update(size_t index, Value const& value) { - index++; - for ( ; index <= array_.size(); index += (index & -index)) { - array_[index - 1] = array_[index - 1] + value; - } - } - - - /*! - * @brief 詢問 \a 0~index 的區間值 - * - * 時間複雜度\b O(logN) - * - * @param [in] index 指定的index - * @return 區間值 - */ - Value query(ssize_t index) const { - index = std::min(index + 1, (ssize_t)array_.size()); - Value ret(0); - for ( ; 0 < index; index -= (index & -index)) { - ret = ret + array_[index - 1]; - } - return ret; - } -}; - -} // meow - -#endif // dsa_BinaryIndexTree_H__ diff --git a/meowpp/dsa/DisjointSet.h b/meowpp/dsa/DisjointSet.h deleted file mode 100644 index 1711d7d..0000000 --- a/meowpp/dsa/DisjointSet.h +++ /dev/null @@ -1,135 +0,0 @@ -#ifndef dsa_DisjointSet_H__ -#define dsa_DisjointSet_H__ - -#include -#include -#include - -namespace meow { -/*! - * @brief 用來維護一堆互斥集的資訊 - * - * DisjointSet 是個 \b 輕量級Data \b Dtructure, 用來維護一堆互斥集的資訊. \n - * 相關資料可參考 - * - * 演算法筆記 - * - * - * @note - * - 時間複雜度 \b 非常快 表示它真的算的超級快, 可以視為常數時間 - * - 預設值所有 \a number 所在的集合的編號就是 \a number 本身, - * 即沒有任兩個數在同一個set裡面 - * - * @author cat_leopard - */ -class DisjointSet { -private: - size_t n_; - std::vector father_; - std::vector depth_; - // - size_t root_(size_t now) { - if (father_[now] == now) return now; - return (father_[now] = root_(father_[now])); - } - - size_t merge_(size_t a, size_t b) { - a = root_(a); - b = root_(b); - if (a == b) return a; - if (depth_[a] > depth_[b]) { - father_[b] = a; - return a; - } - else { - father_[a] = b; - if (depth_[a] == depth_[b]) depth_[b]++; - return b; - } - } -public: - /*! - *@brief constructor - */ - DisjointSet(): n_(0) { - } - - /*! - *@brief constructor - * - *@param [in] n elements數 - */ - DisjointSet(size_t n) { - reset(n); - } - - /*! - *@brief constructor - * - *將另一個 \c DisjointSet 原封不動的複製過來 - * - *@param [in] dsj 另一個 \c DisjointSet - */ - DisjointSet(DisjointSet const& dsj): - n_(dsj.n_), father_(dsj.father_), depth_(dsj.depth_) { - } - - /*! - *@brief 回傳指定的number所在的 \b 集合的編號 - * - *時間複雜度 \b 超級快 - * - *@param [in] a 指定的number - *@return 集合的編號 - */ - size_t root(size_t a) const { - return ((DisjointSet*)this)->root_(a); - } - - - /*! - *@brief 回傳總element數 - * - *@return 總element數 - */ - size_t size() const { - return n_; - } - - /*! - *@brief 重設 - * - *清空, 並且設定總集合大小為 \a n - * - *@param [in] n 重新設定的集合大小 \a n - *@return 無 - */ - void reset(size_t n) { - n_ = n; - father_.resize(n); - depth_ .resize(n); - for (size_t i = 0; i < n; i++) { - father_[i] = i; - depth_ [i] = 1; - } - } - - /*! - * @brief 合併 - * - * 將 \a number1 所在的集合 跟 \b number2 所在的集合 \b 合併, - * 並回傳合併後新的集合的編號. \n - * 時間複雜度\b 非常快 - * - * @param [in] a 即上述\a number1 - * @param [in] b 即上述\a number2 - * @return 新的編號 - */ - size_t merge(size_t a, size_t b) { - return merge_(a, b); - } -}; - -} // meow - -#endif // dsa_DisjointSet_H__ diff --git a/meowpp/dsa/HashTable.h b/meowpp/dsa/HashTable.h deleted file mode 100644 index ed97d6d..0000000 --- a/meowpp/dsa/HashTable.h +++ /dev/null @@ -1,217 +0,0 @@ -#ifndef dsa_HashTable_H__ -#define dsa_HashTable_H__ - -#include -#include - -namespace meow { - -/*! - * @brief 一個當key相撞時會用list解決的hash_table - * - * @author cat_leopard - */ -template -class HashTableList { -private: - std::vector > table_; - HashFunc func_; -public: - /*! - * @brief constructor - */ - HashTableList() { - } - - /*! - * @brief constructor - * - * 設定table size, hash function - */ - HashTableList(size_t size, HashFunc const& func): table_(size), func_(func) { - } - - /*! - * @brief destructor - */ - ~HashTableList() { - } - - /*! - * @brief copy - */ - HashTableList& copyFrom(HashTableList const& b) { - table_ = b.table_; - func_ = b.func_; - return *this; - } - - /*! - * @brief 清除資料 - */ - void clear() { - for (size_t i = 0, I = table_.size(); i < I; i++) { - table_[i].clear(); - } - } - - /*! - * @brief 清除資料, 指定新的size與hash function - */ - void reset(size_t size, HashFunc const& func) { - table_.clear(); - table_.resize(std::max(size, 1u)); - func_ = func; - } - - /*! - * @brief 回傳table size - */ - size_t tableSize() const { - return table_.size(); - } - - /*! - * @brief 回傳目前有多少element在其中 - */ - size_t size() const { - size_t ret = 0; - for (size_t i = 0, I = table_.size(); i < I; i++) { - ret += table_[i].size(); - } - return ret; - } - - /*! - * @brief 回傳hash function - */ - HashFunc const& func() const { - return func_; - } - - /*! - * @brief 加入新的element - */ - bool add(Data const& e) { - size_t index = func_(e) % size(); - table_[index].push_back(e); - return true; - } - - /*! - * @brief 把給定的HashTableList中所有的element全加進來 - */ - bool add(HashTableList const& h) { - for (size_t i = 0, I = h.table_.size(); i < I; i++) { - for (std::list::const_iterator - it = h.table_[index].begin(); it != h.table_[index].end(); ++it) { - insert(*it); - } - } - return true; - } - - /*! - * @brief 刪除element - */ - bool del(Data const& e) { - size_t index = func_(e) % size(); - for (std::list::const_iterator - it = table_[index].begin(); it != table_[index].end(); ++it) { - if ((*it) == e) { - table_[index].erase(i); - return true; - } - } - return false; - } - - /*! - * @brief 刪除有出現在給定的的HashTableList中的element - */ - bool del(HashTableList const& h) { - if (size() > h.size()) { - for (size_t i = 0, I = h.table_.size(); i < I; i++) { - for (std::list::const_iterator - it = h.table_[index].begin(); it != h.table_[index].end(); ++it) { - erase(*it); - } - } - } - else { - for (size_t i = 0, I = table_.size(); i < I; i++) { - for (std::list::const_iterator - it = table_[index].begin(); it != table_[index].end(); ) { - if (h.exist(*it)) { - table_[index].erase(it); - } - else { - ++it; - } - } - } - } - return true; - } - - /*! - * @brief 查看某element是否已經擁有 - */ - bool exist(Data const& e) const { - size_t index = func_(e) % size(); - for (std::list::const_iterator - it = table_[index].begin(); it != table_[index].end(); ++it) { - if ((*it) == e) - return true; - } - return false; - } - - /*! - * @brief 回傳所有存下來的資料 - */ - std::vector all() const { - std::vector ret; - for (size_t i = 0, I = table_.size(); i < I; i++) { - for (std::list::const_iterator - it = table_[i].begin(); it != table_[i].end(); ++it) { - ret.push_back(*it); - } - } - return ret; - } - - /*! - * @brief 回傳所有存下來且key為index的資料 - */ - std::vector all(size_t index) const { - index %= table_.size(); - std::vector ret; - for (std::list::const_iterator - it = table_[index].begin(); it != table_[index].end(); ++it) { - ret.push_back(*it); - } - return ret; - } - - //! @brief same as \c copyFrom(h) - HashTableList& operator=(HashTableList const& h) { - return copyFrom(h); - } - - //! @brief same as \c add(h) - HashTableList& operator+=(HashTableList const& h) { - add(h); - return *this; - } - - //! @brief same as \c del(h) - HashTableList& operator-=(HashTableList const& h) { - del(h); - return *this; - } -}; - -} // meow - -#endif // dsa_HashTable_H__ diff --git a/meowpp/dsa/KD_Tree.h b/meowpp/dsa/KD_Tree.h deleted file mode 100644 index e5a51dc..0000000 --- a/meowpp/dsa/KD_Tree.h +++ /dev/null @@ -1,303 +0,0 @@ -#ifndef dsa_KD_Tree_H__ -#define dsa_KD_Tree_H__ - -#include "../utility.h" -#include "../math/utility.h" - -#include - -#include -#include -#include - -namespace meow { - -/*! - * @brief \c k-dimension tree - * - * 全名k-dimension tree, 用來維護由\b N個K維度向量所成的集合, - * 並可於該set中查找 \b 前i個離給定向量最接近的向量 - * - * Template Class Operators Request - * -------------------------------- - * - * |const?|Typename|Operator | Parameters |Return Type | Description | - * |-----:|:------:|----------:|:-------------|:----------:|:------------------| - * |const |Vector |operator[] |(size_t \c n) |Scalar | 取得第 `n` 維度量 | - * |const |Vector |operator< |(Vector \c v) |bool | 權重比較 | - * |const |Scalar |operator* |(Scalar \c s) |Scalar | 相乘 | - * |const |Scalar |operator+ |(Scalar \c s) |Scalar | 相加 | - * |const |Scalar |operator- |(Scalar \c s) |Scalar | 相差 | - * |const |Scalar |operator< |(Scalar \c s) |bool | 大小比較 | - * - * @note: - * 此資料結構只有在 N >> 2 K 時才比較有優勢, - * 當 K 逐漸變大時, 所花時間會跟暴搜沒兩樣 - * - * @author cat_leopard - */ -template -class KD_Tree { -private: - struct Node { - Vector vector_; - ssize_t lChild_; - ssize_t rChild_; - - Node(Vector v, ssize_t l, ssize_t r): vector_(v), lChild_(l), rChild_(r){ - } - }; - typedef std::vector Nodes; - - class Sorter { - private: - Nodes const* nodes_; - size_t cmp_; - public: - Sorter(Nodes const* nodes, size_t cmp): - nodes_(nodes), cmp_(cmp){ - } - bool operator()(size_t const& a, size_t const& b) const{ - if ((*nodes_)[a].vector_[cmp_] != (*nodes_)[b].vector_[cmp_]) { - return ((*nodes_)[a].vector_[cmp_] < (*nodes_)[b].vector_[cmp_]); - } - return ((*nodes_)[a].vector_ < (*nodes_)[b].vector_); - } - }; - struct Answer { - ssize_t index_; - Scalar dist2_; - // - Answer(ssize_t index, Scalar dist2): - index_(index), dist2_(dist2) { - } - Answer(Answer const& answer2): - index_(answer2.index_), dist2_(answer2.dist2_) { - } - }; - class AnswerCompare { - private: - Nodes const* nodes_; - bool cmpValue_; - public: - AnswerCompare(Nodes const* nodes, bool cmpValue): - nodes_(nodes), cmpValue_(cmpValue) { - } - bool operator()(Answer const& a, Answer const& b) const { - if (cmpValue_ == true && a.dist2_ == b.dist2_) { - return ((*nodes_)[a.index_].vector_ < (*nodes_)[b.index_].vector_); - } - return (a.dist2_ < b.dist2_); - } - }; - typedef std::vector AnswerV; - typedef std::priority_queue Answers; - // - const ssize_t kNIL_; - // - Nodes nodes_; - size_t root_; - bool needRebuild_; - size_t dimension_; - // - Scalar distance2(Vector const& v1, Vector const& v2) const { - Scalar ret(0); - for(size_t i = 0; i < dimension_; i++){ - ret += squ(v1[i] - v2[i]); - } - return ret; - } - // - void query(Vector const& v, - size_t nearestNumber, - AnswerCompare const& answerCompare, - ssize_t index, - int depth, - std::vector& dist2Vector, - Scalar dist2Minimum, - Answers *out) const { - if (index == kNIL_) return ; - size_t cmp = depth % dimension_; - ssize_t this_side, that_side; - if (!(nodes_[index].vector_[cmp] < v[cmp])) { - this_side = nodes_[index].lChild_; - that_side = nodes_[index].rChild_; - }else{ - this_side = nodes_[index].rChild_; - that_side = nodes_[index].lChild_; - } - query(v, nearestNumber, answerCompare, - this_side, depth + 1, - dist2Vector, dist2Minimum, - out); - Answer my_ans(index, distance2(nodes_[index].vector_, v)); - if (out->size() < nearestNumber || answerCompare(my_ans, out->top())) { - out->push(my_ans); - if (out->size() > nearestNumber) out->pop(); - } - Scalar dist2_old(dist2Vector[cmp]); - dist2Vector[cmp] = squ(nodes_[index].vector_[cmp] - v[cmp]); - Scalar dist2Minimum2(dist2Minimum + dist2Vector[cmp] - dist2_old); - if (out->size() < nearestNumber || !(out->top().dist2_ < dist2Minimum)) { - query(v, nearestNumber, answerCompare, - that_side, depth + 1, - dist2Vector, dist2Minimum2, - out); - } - dist2Vector[cmp] = dist2_old; - } - ssize_t build(ssize_t beg, - ssize_t end, - std::vector* orders, - int depth) { - if (beg > end) return kNIL_; - size_t tmp_order = dimension_; - size_t which_side = dimension_ + 1; - ssize_t mid = (beg + end) / 2; - size_t cmp = depth % dimension_; - for (ssize_t i = beg; i <= mid; i++) { - orders[which_side][orders[cmp][i]] = 0; - } - for (ssize_t i = mid + 1; i <= end; i++) { - orders[which_side][orders[cmp][i]] = 1; - } - for (size_t i = 0; i < dimension_; i++) { - if (i == cmp) continue; - size_t left = beg, right = mid + 1; - for (int j = beg; j <= end; j++) { - size_t ask = orders[i][j]; - if(ask == orders[cmp][mid]) { - orders[tmp_order][mid] = ask; - } - else if(orders[which_side][ask] == 1) { - orders[tmp_order][right++] = ask; - } - else { - orders[tmp_order][left++] = ask; - } - } - for (int j = beg; j <= end; j++) { - orders[i][j] = orders[tmp_order][j]; - } - } - nodes_[orders[cmp][mid]].lChild_ = build(beg, mid - 1, orders, depth + 1); - nodes_[orders[cmp][mid]].rChild_ = build(mid + 1, end, orders, depth + 1); - return orders[cmp][mid]; - } -public: - //! Custom Type: Vectors is \c std::vector - typedef typename std::vector Vectors; - - //! @brief constructor, with dimension = 1 - KD_Tree(): kNIL_(-1), root_(kNIL_), needRebuild_(false), dimension_(1) { - } - - //! @brief constructor, given dimension - KD_Tree(size_t dimension): - kNIL_(-1), root_(kNIL_), needRebuild_(false), dimension_(dimension) { - } - - //! @brief destructor - ~KD_Tree() { - } - - /*! - * @brief 將給定的Vector加到set中 - */ - void insert(Vector const& v) { - nodes_.push_back(Node(v, kNIL_, kNIL_)); - needRebuild_ = true; - } - - /*! - * @brief 將給定的Vector從set移除 - */ - bool erase(Vector const& v) { - for (size_t i = 0, I = nodes_.size(); i < I; i++) { - if (nodes_[i] == v) { - if (i != I - 1) { - std::swap(nodes_[i], nodes_[I - 1]); - } - needRebuild_ = true; - return true; - } - } - return false; - } - - /*! - * @brief 檢查至今是否有 insert/erase 被呼叫來決定是否 \c rebuild() - */ - void build(){ - if (needRebuild_) { - forceBuild(); - } - } - - /*! - * @brief 重新建樹 - */ - void forceBuild() { - std::vector *orders = new std::vector[dimension_ + 2]; - for (size_t j = 0; j < dimension_ + 2; j++) { - orders[j].resize(nodes_.size()); - } - for (size_t j = 0; j < dimension_; j++) { - for (size_t i = 0, I = nodes_.size(); i < I; i++) { - orders[j][i] = i; - } - std::sort(orders[j].begin(), orders[j].end(), Sorter(&nodes_, j)); - } - root_ = build(0, (ssize_t)nodes_.size() - 1, orders, 0); - delete [] orders; - needRebuild_ = false; - } - - /*! - * @brief 查找 - * - * 於set中找尋距離指定向量前 \c i 近的向量, 並依照由近而遠的順序排序. - * 如果有兩個向量\c v1,v2 距離一樣, 且 \c cmp 為\c true , 則直接依照 - * \c v1build(); - AnswerCompare answer_compare(&nodes_, compareWholeVector); - Answers answer_set(answer_compare); - std::vector tmp(dimension_, 0); - query(v, nearestNumber, - answer_compare, - root_, 0, - tmp, Scalar(0), - &answer_set); - Vectors ret(answer_set.size()); - for (int i = (ssize_t)answer_set.size() - 1; i >= 0; i--) { - ret[i] = nodes_[answer_set.top().index_].vector_; - answer_set.pop(); - } - return ret; - } - - /*! - * @brief 清空所有資料 - */ - void clear() { - root_ = kNIL_; - nodes_.clear(); - needRebuild_ = false; - } - - /*! - * @brief 清空所有資料並重新給定維度 - */ - void reset(size_t dimension) { - clear(); - dimension_ = dimension; - } -}; - -} // meow - -#endif // dsa_KD_Tree_H__ diff --git a/meowpp/dsa/MergeableHeap.h b/meowpp/dsa/MergeableHeap.h deleted file mode 100644 index 91b8d8b..0000000 --- a/meowpp/dsa/MergeableHeap.h +++ /dev/null @@ -1,168 +0,0 @@ -#ifndef dsa_MergeableHeap_H__ -#define dsa_MergeableHeap_H__ - -#include -#include - -namespace meow { - -/*! - * @brief - * - * 一個用 \b 左偏樹 實作的 \c Maximum-Heap , 除了原本heap有的功能外, - * 還支援 \c merge 功能 - * - * Template Class Operators Request - * -------------------------------- - * - * |const?|Typename|Operator | Parameters |Return Type | Description | - * |-----:|:------:|----------:|:-------------|:----------:|:------------------| - * |const |Element |operator< |(Element \c b)|bool | 大小比較 | - * - * @note: - * 假設現在有兩個MergeableHeap \c A 和 \c B, 則: - * - 執行 \c A.merge(&B) 後 \c B 會變成空的 - * - 執行 \c B.moveTo(&A) 後 \c B 會變成空的, \c A 原本擁有的資料也會覆蓋掉 - * - * @author cat_leopard - */ -template -class MergeableHeap { // maximum-heap -private: - struct Node { - Element value_; - Node* lChild_; - Node* rChild_; - size_t weight_; - Node(Element const& value): - value_(value), lChild_(NULL), rChild_(NULL), weight_(1){ - } - }; - - Node* root_; - - void clear(Node* node) { - if (node != NULL) { - clear(node->lChild_); - clear(node->rChild_); - delete node; - } - } - Node* dup(Node* node) { - if (node == NULL) return NULL; - Node* ret = new Node(node->value_); - ret->lChild_ = dup(node->lChild_); - ret->rChild_ = dup(node->rChild_); - ret->weight_ = 1; - ret->weight_ += (ret->lChild_ == NULL ? 0 : ret->lChild_->weight_); - ret->weight_ += (ret->rChild_ == NULL ? 0 : ret->rChild_->weight_); - return ret; - } - Node* merge(Node* left, Node* right) { - if (left == NULL) return right; - if (right == NULL) return left; - if (left->value_ < right->value_) { - std::swap(left, right); - } - left->rChild_ = merge(left->rChild_, right); - size_t lw = (left->lChild_ == NULL ? 0 : left->lChild_->weight_); - size_t rw = (left->rChild_ == NULL ? 0 : left->rChild_->weight_); - if (lw < rw) { - std::swap(left->lChild_, left->rChild_); - } - left->weight_ = 1 + lw + rw; - return left; - } -public: - //! @brief constructor - MergeableHeap(): root_(NULL){ - } - - //! @brief constructor, 並且複製資料 - MergeableHeap(MergeableHeap const& heap2): root_(dup(heap2.root_)) { - } - - //! @brief destructor - ~MergeableHeap(){ - clear(root_); - } - - //! @brief 複製資料 - MergeableHeap& copyFrom(MergeableHeap const& heap2) { - delete root_; - root_ = dup(heap2.root_); - return *this; - } - - /*! - * @brief 將自己的資料丟給指定的heap, 從此自己一身空 - */ - void moveTo(MergeableHeap* heap2){ - heap2->clear(); - heap2->root_ = root_; - root_ = NULL; - } - - /*! - * @brief 回傳最大的那個 Element - */ - Element const& top() const { - return root_->value_; - } - - /*! - * @brief 回傳資料個數 - */ - size_t size() const { - return (root_ == NULL ? 0 : root_->weight_); - } - - /*! - * @brief 回傳是否為空 - */ - bool empty() const { - return (size() == 0); - } - - /*! - * @brief 加入element - */ - void push(Element const& value) { - root_ = merge(root_, new Node(value)); - } - - /*! - * @brief 將最大的element移除 - */ - void pop() { - Node* l = root_->lChild_; - Node* r = root_->rChild_; - delete root_; - root_ = merge(l, r); - } - - /*! - * 將資料清空 - */ - void clear() { - clear(root_); - root_ = NULL; - } - - /*! - * 將給定的MergeableHeap的資料統統加到自己身上並且清空該heap - */ - void merge(MergeableHeap* heap2) { - root_ = merge(root_, heap2->root_); - heap2->root_ = NULL; - } - - //! @brief same as \c copyFrom(heap2) - MergeableHeap& operator=(MergeableHeap const& heap2) { - return copyFrom(heap2); - } -}; - -} // meow - -#endif // dsa_MergeableHeap_H__ diff --git a/meowpp/dsa/SegmentTree.h b/meowpp/dsa/SegmentTree.h deleted file mode 100644 index 305c4c3..0000000 --- a/meowpp/dsa/SegmentTree.h +++ /dev/null @@ -1,194 +0,0 @@ -#ifndef dsa_SegmentTree_H__ -#define dsa_SegmentTree_H__ - -#include "../math/utility.h" - -#include -#include - -#include - -namespace meow { -/*! - * @brief 中文名 \c 線段樹 - * - * 維護一個陣列, 並且讓user可以有區間查詢, 區間修改的小東東 - * - * Template Class Operators Request - * -------------------------------- - * - * |const?|Typename|Operator | Parameters |Return Type | Description | - * |-----:|:------:|----------:|:-------------|:----------:|:------------------| - * |const |Vector |operator[] |(size_t \c n) |Scalar | 取得第 `n` 維度量 | - * |const |Vector |operator< |(Vector \c v) |bool | 權重比較 | - * |const |Scalar |operator* |(Scalar \c s) |Scalar | 相乘 | - * |const |Scalar |operator+ |(Scalar \c s) |Scalar | 相加 | - * |const |Scalar |operator- |(Scalar \c s) |Scalar | 相差 | - * |const |Scalar |operator< |(Scalar \c s) |bool | 大小比較 | - * |const |Value |operator+ |(Value \c v) |Value | 相加(位移) | - * |const |Value |operator* |(size_t \c n) |Value | 每個Value都一樣, - * 長為 `n` 的區間的值| - * |const |Value |operator{b}|(Value \c v) |Value | 區間合併後的值 | - * - * - 若要維護區間最小值, 即每次都是詢問範圍 `[a, b]` 的最小值, 則可以定義 - * - \c operator+ 為 '回傳相加值' - * - \c operator* 為 '回傳*this' - * - \c operator| 為 '回傳std::min(*this, v)' - * - 若要維護區間最總和, 即每次都是詢問範圍 `[a, b]` 的總和, 則可以定義 - * - \c operator+ 為 '回傳相加值' - * - \c operator* 為 '回傳(*this) * n' - * - \c operator| 為 '回傳相加值' - * - * @author cat_leopard - */ -template -class SegmentTree { -private: - struct Node { - Value value_; - Value offset_; - bool sameFlage_; - }; - // - size_t size_; - std::vector nodes_; - // - void update(size_t index, size_t size, Value const& value, bool override) { - if (override) { - nodes_[index].value_ = value * size; - nodes_[index].offset_ = value; - nodes_[index].sameFlage_ = true; - } - else { - nodes_[index].value_ = nodes_[index].value_ + value * size; - nodes_[index].offset_ = nodes_[index].offset_ + value; - } - } - void update(size_t l, size_t r, size_t L, size_t R, - size_t index, Value const& value, - bool override) { - if (l == L && r == R) { - update(index, R - L + 1, value, override); - return ; - } - size_t mid = (L + R) / 2; - if (L < R) { - update(index * 2 + 1, mid - L + 1, - nodes_[index].offset_, nodes_[index].sameFlage_); - update(index * 2 + 2, R - mid, - nodes_[index].offset_, nodes_[index].sameFlage_); - nodes_[index].offset_ = Value(0); - nodes_[index].sameFlage_ = false; - } - if (r <= mid) { - update(l, r, L ,mid, index * 2 + 1, value, override); - } - else if (mid + 1 <= l) { - update(l, r, mid + 1,R, index*2 + 2, value, override); - } - else { - update(l, mid , L, mid , index * 2 + 1, value, override); - update( mid + 1, r, mid + 1, R, index * 2 + 2, value, override); - } - nodes_[index].value_ = ( - (nodes_[index * 2 + 1].value_ | nodes_[index * 2 + 2].value_) - + nodes_[index].offset_ - ); - } - Value query(size_t l, size_t r, size_t L, size_t R, size_t index) { - if (l == L && r == R) return nodes_[index].value_; - Value off = nodes_[index].offset_ * (r - l + 1); - if (nodes_[index].sameFlage_) return off; - size_t mid = (L + R) / 2; - if (r <= mid) return query(l, r, L , mid, index * 2 + 1) + off; - else if(mid + 1 <= l) return query(l, r, mid + 1, R, index * 2 + 2) + off; - else{ - return ( query(l, mid , L, mid , index * 2 + 1) - | query( mid + 1, r, mid + 1, R, index * 2 + 2) - ) + off; - } - } - // - bool rangeCorrect(ssize_t* first, ssize_t* last) const { - if (*last < *first || *last < 0 || (ssize_t)size_ - 1 < *first) - return false; - *first = inRange((ssize_t)0, (ssize_t)size_ - 1, *first); - *last = inRange((ssize_t)0, (ssize_t)size_ - 1, *last ); - return true; - } -public: - //! @brief constructor - SegmentTree() { - reset(1); - } - - //! @brief constructor, with \c size gived - SegmentTree(size_t size) { - reset(size); - } - - //! @brief constructor, 並且複製資料 - SegmentTree(SegmentTree const& tree2): - size_(tree2.size_), nodes_(tree2.nodes_) { - } - - /*! - * @brief 複製 - */ - SegmentTree copyFrom(SegmentTree const& b) { - size_ = b.size_; - nodes_ = b.nodes_; - return *this; - } - - /*! - * @brief 回傳size - */ - size_t size() const { - return size_; - } - - /*! - * @brief 將資料清空且設定維護範圍是 \c 0~size-1 - */ - void reset(size_t size){ - size_ = std::max(size, (size_t)1); - nodes_.resize(size * 4); - nodes_[0].sameFlage_ = true; - nodes_[0].value_ = Value(0); - nodes_[0].offset_ = Value(0); - } - - /*! - * @brief 回傳區間 \c [first,last] (邊界都含) 的區間值 - */ - Value query(ssize_t first, ssize_t last) const { - if (rangeCorrect(&first, &last) == false) return Value(); - return ((SegmentTree*)this)->query(first, last, 0, size_ - 1, 0); - } - - /*! - * @brief 將區間 \c [first,last] 全部都設定成 \c value - */ - void override(ssize_t first, ssize_t last, Value const& value) { - if (rangeCorrect(&first, &last) == false) return ; - update(first, last, 0, size_ - 1, 0, value, true); - } - - /*! - * @brief 將區間 \c [first,last] 全部都加上 \c delta - */ - void offset(ssize_t first, ssize_t last, Value const& delta) { - if (rangeCorrect(&first, &last) == false) return ; - update(first, last, 0, size_ - 1, 0, delta, false); - } - - //! @brief same as copyFrom(b) - SegmentTree& operator=(SegmentTree const& b) { - return copyFrom(b); - } -}; - -} // meow - -#endif // dsa_SegmentTree_H__ diff --git a/meowpp/dsa/SplayTree.h b/meowpp/dsa/SplayTree.h deleted file mode 100644 index 483b965..0000000 --- a/meowpp/dsa/SplayTree.h +++ /dev/null @@ -1,1151 +0,0 @@ -#ifndef dsa_SplayTree_h__ -#define dsa_SplayTree_h__ - -#include -#include - -#include "../math/utility.h" - -namespace meow { - -/*! - * @brief - * - * 是一種神乎其技的資料結構, 維護一堆 Key->Value . 並且支援 - * 一些 \c std::map 難以快速實踐的操作, 如 \c split , \c merge , \c keyOffset - * - * Template Class Operators Request - * -------------------------------- - * - * |const?|Typename|Operator | Parameters |Return Type | Description | - * |-----:|:------:|----------:|:-------------|:----------:|:------------------| - * |const |Key |operator+ |(Key \c k) | Key |相加 | - * |const |Key |operator< |(Key \c k) | bool |大小比較 | - * | |Key |operator= |(Key \c k) | Key |copy oper | - * | |Key |Key |(int \c n) | |構子,\c n 永遠是0 | - * | |Value | Value |( ) | |建構子 | - * - * @note: - * -假設現在有兩個SplayTree `A` 和 `B`, 則: - * -執行 `B.moveTo(&A)` 後 `B` 會變成空的, `A` 原本擁有的資料也會覆蓋掉 - * -行 `A.merge(&B)` 或 `A.mergeAfter(&B)` 後 - * 如果檢查發現確實可以merge, 則之後 `B` 會變成空的 - * - * @author cat_leopard - */ -template -class SplayTree { -private: - struct Node { - Key key_; - Key keyOffset_; - Value value_; - size_t size_; - Node* parent_; - Node* child_[2]; - - Node(Key const& key, Value const& value): - key_(key), keyOffset_(0), value_(value) { - size_ = 1; - parent_ = NULL; - child_[0] = NULL; - child_[1] = NULL; - } - // - void keyOffset(Key const& delta) { - key_ = key_ + delta; - keyOffset_ = keyOffset_ + delta; - } - void syncDown() const { - for (size_t i = 0; i < 2; i++) { - if (child_[i] == NULL) continue; - child_[i]->keyOffset(keyOffset_); - } - ((Node*)this)->keyOffset_ = Key(0); - } - void syncUp() const { - ((Node*)this)->size_ = 1; - for (size_t i = 0; i < 2; i++) { - if (child_[i] == NULL) continue; - ((Node*)this)->size_ += child_[i]->size_; - } - } - }; - - Node* root_; - - //! @brief 指定左子or右子, 連接parent<--->child - void connect(Node const* parent, size_t left_right, Node const* child) const { - Node* p = (Node*)parent; - Node* c = (Node*)child; - if (p != NULL) p->child_[left_right] = c; - if (c != NULL) c->parent_ = p; - } - - //! @brief 一路往上轉 - Node const* splay(Node const* node) const { - if (node != NULL && node->parent_ != NULL) { - for (const Node *g_grand, *grand, *parent, *child = node; ; ) { - g_grand = (grand = parent = child->parent_)->parent_; - size_t pc = (parent->child_[0] == child ? 0 : 1); - connect(parent, pc, child->child_[!pc]); - connect(child , !pc, parent); - if (g_grand != NULL) { - g_grand = (grand = g_grand)->parent_; - size_t gp = (grand->child_[0] == parent ? 0 : 1); - Node const* who = (pc == gp ? parent : child); - connect(grand, gp, who->child_[!gp]); - connect(who , !gp, grand); - grand->syncUp(); - } - parent->syncUp(); - child ->syncUp(); - if (g_grand == NULL) { - connect(NULL, 0, child); - break; - } - connect(g_grand, (g_grand->child_[0] == grand ? 0 : 1), child); - } - } - return (((SplayTree*)this)->root_ = (Node*)node); - } - - void clear(Node* node) { - if (node == NULL) return ; - clear(node->child_[0]); - clear(node->child_[1]); - delete node; - } - - Node* dup(Node* node2) { - if (node2 == NULL) return NULL; - node2->syncDown(); - Node* node = new Node(node2->key_, node2->value_); - connect(node, 0, dup(node2->child_[0])); - connect(node, 1, dup(node2->child_[1])); - node->syncUp(); - return node; - } - - Node const* findKey(Node const* node, Key const& key) const { - Node const* ret = node; - while (node != NULL) { - node->syncDown(); - ret = node; - if (!(key < node->key_)) { - if (!(node->key_< key)) break; - node = node->child_[1]; - } - else { - node = node->child_[0]; - } - } - return ret; - } - Node const* findMinMax(Node const* node, bool minimum) const { - Node const* ret = node; - for (int i = minimum ? 0 : 1; node != NULL; node = node->child_[i]) { - node->syncDown(); - ret = node; - } - return ret; - } - Node const* findOrder(Node const* node, size_t order) const { - Node const* ret = node; - while (node != NULL) { - node->syncDown(); - ret = node; - size_t ord = 1 + (node->child_[0] == NULL ? 0 : node->child_[0]->size_); - if (ord == order) return ret; - else if(ord < order){ node = node->child_[1]; order -= ord; } - else { node = node->child_[0]; } - } - return ret; - } - - void split(Node* root, Node** left, Node** right) { - if (root == NULL) { *left = NULL; *right = NULL; return ; } - root->syncDown(); - *left = root; - *right = root->child_[1]; - if (*right != NULL) { - (*left )->child_[1] = NULL; - (*right)->parent_ = NULL; - (*left )->syncUp(); - } - } - Node* merge(Node* left, Node* right) { - if (left == NULL) return right; - if (right == NULL) return left ; - left->syncDown(); - connect(left, 1, right); - left->syncUp(); - return left; - } -public: - /*! - * @brief 類似 \c stl 的 \c iterator ,不過這邊叫做\c Element - * - * 用來當作回傳資料的媒介 - */ - class Element{ - private: - typedef std::pair Entry; - Entry* entry_; - Node * node_; - // - void reset(Node* node) { - node_ = node; - delete entry_; - entry_ = (node == NULL ? NULL : new Entry(node->key_, node->value_)); - } - public: - Element(): entry_(NULL), node_(NULL) { - } - Element(Node* node): entry_(NULL), node_(NULL) { - reset(node); - } - Element(Element const& element2): entry_(NULL), node_(NULL) { - reset(element2.node_); - } - ~Element(){ - delete entry_; - } - - //! @brief 複製資料 - Element& copyFrom(Element const& e) { - reset(e.node_); - return *this; - } - - //! @brief 比對兩者是否為指向同一個Entry - bool same(Element const& e2) const { - return (node_ == e2.node_); - } - - //! @brief same as copyFrom - Element& operator=(Element const& e2) { - return copyFrom(e2); - } - - //! @brief 重導至\c std::pair* - Entry* operator->() { - return entry_; - } - - //! @brief 重導至\c std::pair& - Entry& operator*() { - return *entry_; - } - - //! @brief same as \c same(e2) - bool operator==(Element const& e2) const{ - return same(e2); - } - - //! @brief same as \c !same(e2) - bool operator!=(Element const& e2) const{ - return !same(e2); - } - }; - - //! @brief constructor - SplayTree(): root_(NULL) { - } - - //! @brief constructor, 複製資料 - SplayTree(SplayTree const& tree2): - root_(dup((Node*)(tree2.root_))) { - } - - //! @brief destructor - ~SplayTree(){ - clear(root_); - } - - /*! - * @brief 複製資料 - */ - SplayTree& copyFrom(SplayTree const& tree2) { - clear(root_); - root_ = dup((Node*)(tree2.root_)); - return *this; - } - - /*! - * @brief 將資料都丟到 \c tree2 身上, 並且清空自己 - */ - void moveTo(SplayTree* tree2) { - tree2->clear(); - tree2->root_ = root_; - root_ = NULL; - } - - /*! - * @brief 找出第一個(最小的) Element且 \c k <= 它的 Key, 並且回傳之. - * - * 找不到的話回傳 \c this->end() - */ - Element lowerBound(Key const& key) const { - splay(findKey(root_, key)); - if (root_ == NULL || !(root_->key_ < key)) return Element(root_); - if (root_->child_[1] == NULL) return Element(NULL); - splay(findMinMax(root_->child_[1], true)); - return Element(root_); - } - - /*! - * @brief 找出第一個(最小的) Element且 \c k < 它的 Key, 並且回傳之. - * - * 找不到的話回傳 \c this->end() - */ - Element upperBound(Key const& key) const { - splay(findKey(root_, key)); - if (root_ == NULL || key < root_->key_) return Element(root_); - if (root_->child_[1] == NULL) return Element(NULL); - splay(findMinMax(root_->child_[1], true)); - return Element(root_); - } - - /*! - * @brief 找出第一個(最小的) Element且 \c k >= 它的 Key, 並且回傳之. - * - * 找不到的話回傳 \c this->end() - */ - Element rLowerBound(Key const& key) const { - splay(findKey(root_, key)); - if (root_ == NULL || !(key < root_->key_)) return Element(root_); - if (root_->child_[0] == NULL) return Element(NULL); - splay(findMinMax(root_->child_[0], false)); - return Element(root_); - } - - /*! - * @brief 找出第一個(最小的) Element且 \c k > 它的 Key, 並且回傳之. - * - * 找不到的話回傳 \c this->end() - */ - Element rUpperBound(Key const& key) const { - splay(findKey(root_, key)); - if (root_ == NULL || root_->key_ < key) return Element(root_); - if (root_->child_[0] == NULL) return Element(NULL); - splay(findMinMax(root_->child_[0], false)); - return Element(root_); - } - - /*! - * @brief 找出 Key= \c k 的Elemenet 並回傳. 找不到的話回傳 \c this->end() - */ - Element find(Key const& key) const { - splay(findKey(root_, key)); - if (root_ != NULL && !(key < root_->key_) && !(root_->key_ < key)) { - return Element(root_); - } - return Element(NULL); - } - - /*! - * @brief 將Elements依照Key由小到大排序, 回傳第 \c ord 個Element (由0算起). - * - * 其中如果 \c ord>N-1, 則會回傳 \c this->last() - */ - Element order(size_t order) const { - if (root_ == NULL || order >= root_->size_) return Element(NULL); - splay(findOrder(root_, order + 1)); - return Element(root_); - } - - /*! - * @brief 回傳Key最小的Element, 如果SplayTree為空, 則回傳 \c this->end() - */ - Element first() const { - splay(findMinMax(root_, true)); - return Element(root_); - } - - /*! - * @brief 回傳Key最大的Element, 如果SplayTree為空, 則回傳 \c this->end() - */ - Element last() const { - splay(findMinMax(root_, false)); - return Element(root_); - } - - /*! - * @brief 回傳一個指向NULL的Element, - * - * 以供 \c find ,\c order ,\c first ,\c last 等判斷是否有找到相對應的Element - */ - Element end() const { - return Element(NULL); - } - - /*! - * @brief 回傳資料個數 - */ - size_t size() const { - return (root_ == NULL ? 0 : root_->size_); - } - - /*! - * @brief 回傳是否為空 - */ - bool empty() const{ - return (size() == 0); - } - - /*! - * @brief 清空 - */ - void clear() { - clear(root_); - root_ = NULL; - } - - /*! - * @brief 插入一組\c (Key ---> \c Value) - * - * 檢查是否已有Element的Key 為 \c key, 若有則回傳 \c false , 否則將 - * 一個 (Key -> Value) = (\c key -> \c value)的Element加入, 並回傳 \c true - */ - bool insert(Key const& key, Value const& value) { - if (root_ == NULL) { - root_ = new Node(key, value); - } - else { - Node* parent = (Node*)findKey(root_, key); - if (!(parent->key_ < key) && !(key < parent->key_)) { - splay(parent); - return false; - } - Node* new_node = new Node(key, value); - connect(parent, (parent->key_ < key ? 1 : 0), new_node); - parent->syncUp(); - splay(new_node); - } - return true; - } - - /*! - * @brief 刪除一組資料 - * - * 檢查是否已有Element的Key 為 \c key, 若有則刪除之, 並回傳 \c true, - * 否則則回傳 \c false - */ - bool erase(Key const& key) { - if (root_ == NULL) return false; - Node* body = (Node*)findKey(root_, key); - if (body->key_ < key || key < body->key_) { - splay(body); - return false; - } - Node* ghost; - if (body->child_[1] == NULL) { - ghost = body->child_[0]; - if (ghost != NULL) ghost->syncDown(); - } - else { - ghost = (Node*)findMinMax(body->child_[1], true); - connect(ghost, 0, body->child_[0]); - if (ghost != body->child_[1]) { - connect(ghost->parent_, 0, ghost->child_[1]); - connect(ghost, 1, body->child_[1]); - for (Node* a = ghost->parent_; a != ghost; a = a->parent_) - a->syncUp(); - } - ghost->syncUp(); - } - Node* parent = body->parent_; - connect(parent, parent != NULL && parent->child_[0] == body ? 0 : 1, ghost); - delete body; - splay(ghost != NULL ? ghost : parent); - return true; - } - - /*! - * @brief 將所有Element的Key同加上 \c delta - */ - void keyOffset(Key const& delta) { - if (root_ != NULL) { - root_->keyOffset(delta); - } - } - - /*! - * @brief 將\c tree2 清空, 再將所有Key > \c upper_bound 的Element都丟過去 - */ - void splitOut(Key const& upper_bound, SplayTree* right) { - right->clear(); - if (rLowerBound(upper_bound) != end()) { - split(root_, &root_, &(right->root_)); - } - else { - right->root_ = root_; - root_ = NULL; - } - } - - /*! - * @brief 合併 - * - * 檢查是否自己中的 Key 都小於 \c tree2 中的Key, 是的話把 \c tree2` - * 中的 Element 都搬到自己這, 同時清空 \c tree2 , 否則回傳 \c false - */ - bool mergeAfter(SplayTree* tree2) { - if (root_ == NULL || tree2->root_ == NULL || - last()->first < tree2->first()->first) { - root_ = merge(root_, tree2->root_); - tree2->root_ = NULL; - return true; - } - return false; - } - - /*! - * @brief 合併 - * - * 檢查是否自己中的 Key 都小於 \c tree2 中的Key, 或是完全相反, - * 是的話把 \c tree2`中的 Element 都搬到自己這, - * 同時清空 \c tree2 , 否則回傳 \c false - */ - bool merge(SplayTree* tree2) { - if (root_ == NULL || tree2->root_ == NULL || - last()->first < tree2->first()->first) { - root_ = merge(root_, tree2->root_); - } - else if(tree2->last()->first < first()->first) { - root_ = merge(tree2->root_, root_); - } - else { - return false; - } - tree2->root_ = NULL; - return true; - } - - /*! - * @brief 就像\c stl::map::operator[] - * - * 會先檢查是否已有Element的Key 為 \c key, 若有則回傳相對應的Value的Reference - * 否則先執行 \c insert(key,Value()) 再回傳相對應的Reference - */ - Value& operator[](Key const& key) { - if (find(key) == end()) insert(key, Value()); - return root_->value_; - } - - //! @brief same as \c copyFrom(tree2) - SplayTree& operator=(SplayTree const& tree2) { - return copyFrom(tree2); - } -}; - -/*! - * @brief - * - * 基本上跟SplayTree一樣, 不過這邊結合線段樹, 多了區間操作 - * (線段樹相關operator定義請見 \c SegmentTree ) - * - * Template Class Operators Request - * -------------------------------- - * - * |const?|Typename|Operator | Parameters |Return Type | Description | - * |-----:|:------:|----------:|:-------------|:----------:|:------------------| - * |const |Key |operator+ |(Key \c k) | Key |相加 | - * |const |Key |operator< |(Key \c k) | bool |大小比較 | - * | |Key |operator= |(Key \c k) | Key |copy oper | - * | |Key |Key |(int \c n) | |構子,\c n 永遠是0 | - * | |Value | Value |( ) | |建構子 | - * - * @note: - * -假設現在有兩個SplayTree `A` 和 `B`, 則: - * -執行 `B.moveTo(&A)` 後 `B` 會變成空的, `A` 原本擁有的資料也會覆蓋掉 - * -行 `A.merge(&B)` 或 `A.mergeAfter(&B)` 後 - * 如果檢查發現確實可以merge, 則之後 `B` 會變成空的 - * - * @author cat_leopard - */ -template -class SplayTree_Range { -private: - struct Node { - Value valueOffset_; - Value range_; - Key key_; - Key keyOffset_; - Value value_; - bool same_; - size_t size_; - Node* parent_; - Node* child_[2]; - - Node(Key const& key, Value const& value): - valueOffset_(0), range_(value), - key_(key), keyOffset_(0), value_(value) { - same_ = false; - size_ = 1; - parent_ = NULL; - child_[0] = NULL; - child_[1] = NULL; - } - // - void keyOffset(Key const& delta) { - key_ = key_ + delta; - keyOffset_ = keyOffset_ + delta; - } - void valueUpdate(Value const& delta, bool over) { - if(over) { - value_ = delta * size_; - valueOffset_ = delta; - range_ = delta * size_; - same_ = true; - } - else { - value_ = value_ + delta * size_; - valueOffset_ = valueOffset_ + delta; - range_ = range_ + delta * size_; - } - } - void syncDown() const { - for (size_t i = 0; i < 2; i++) { - if (child_[i] == NULL) continue; - child_[i]->keyOffset(keyOffset_); - child_[i]->valueUpdate(valueOffset_, same_); - } - ((Node*)this)->keyOffset_ = Key(0); - ((Node*)this)->valueOffset_ = Value(0); - ((Node*)this)->same_ = false; - } - void syncUp() const { - ((Node*)this)->size_ = 1; - Value* v[3] = {&(((Node*)this)->value_), NULL, NULL}; - size_t vct = 1; - for (size_t i = 0; i < 2; i++) { - if (child_[i] == NULL) continue; - ((Node*)this)->size_ += child_[i]->size_; - v[vct++] = &(child_[i]->range_); - } - if (vct == 1) ((Node*)this)->range_ = (*v[0]); - else if(vct == 2) ((Node*)this)->range_ = (*v[0]) | (*v[1]); - else ((Node*)this)->range_ = (*v[0]) | (*v[1]) | (*v[2]); - } - }; - - Node* root_; - - //! @brief 指定左子or右子, 連接parent<--->child - void connect(Node const* parent, size_t left_right, Node const* child) const { - Node* p = (Node*)parent; - Node* c = (Node*)child; - if (p != NULL) p->child_[left_right] = c; - if (c != NULL) c->parent_ = p; - } - - //! @brief 一路往上轉 - Node const* splay(Node const* node) const { - if (node != NULL && node->parent_ != NULL) { - for (const Node *g_grand, *grand, *parent, *child = node; ; ) { - g_grand = (grand = parent = child->parent_)->parent_; - size_t pc = (parent->child_[0] == child ? 0 : 1); - connect(parent, pc, child->child_[!pc]); - connect(child , !pc, parent); - if (g_grand != NULL) { - g_grand = (grand = g_grand)->parent_; - size_t gp = (grand->child_[0] == parent ? 0 : 1); - Node const* who = (pc == gp ? parent : child); - connect(grand, gp, who->child_[!gp]); - connect(who , !gp, grand); - grand->syncUp(); - } - parent->syncUp(); - child ->syncUp(); - if (g_grand == NULL) { - connect(NULL, 0, child); - break; - } - connect(g_grand, (g_grand->child_[0] == grand ? 0 : 1), child); - } - } - return (((SplayTree_Range*)this)->root_ = (Node*)node); - } - - void clear(Node* node) { - if (node == NULL) return ; - clear(node->child_[0]); - clear(node->child_[1]); - delete node; - } - - Node* dup(Node* node2) { - if (node2 == NULL) return NULL; - node2->syncDown(); - Node* node = new Node(node2->key_, node2->value_); - connect(node, 0, dup(node2->child_[0])); - connect(node, 1, dup(node2->child_[1])); - node->syncUp(); - return node; - } - - Node const* findKey(Node const* node, Key const& key) const { - Node const* ret = node; - while (node != NULL) { - node->syncDown(); - ret = node; - if (!(key < node->key_)) { - if (!(node->key_< key)) break; - node = node->child_[1]; - } - else { - node = node->child_[0]; - } - } - return ret; - } - Node const* findMinMax(Node const* node, bool minimum) const { - Node const* ret = node; - for (int i = minimum ? 0 : 1; node != NULL; node = node->child_[i]) { - node->syncDown(); - ret = node; - } - return ret; - } - Node const* findOrder(Node const* node, size_t order) const { - Node const* ret = node; - while (node != NULL) { - node->syncDown(); - ret = node; - size_t ord = 1 + (node->child_[0] == NULL ? 0 : node->child_[0]->size_); - if (ord == order) return ret; - else if(ord < order){ node = node->child_[1]; order -= ord; } - else { node = node->child_[0]; } - } - return ret; - } - - void split(Node* root, Node** left, Node** right) { - if (root == NULL) { *left = NULL; *right = NULL; return ; } - root->syncDown(); - *left = root; - *right = root->child_[1]; - if (*right != NULL) { - (*left )->child_[1] = NULL; - (*right)->parent_ = NULL; - (*left )->syncUp(); - } - } - Node* merge(Node* left, Node* right) { - if (left == NULL) return right; - if (right == NULL) return left ; - left->syncDown(); - connect(left, 1, right); - left->syncUp(); - return left; - } -public: - /*! - * @brief 類似 \c stl 的 \c iterator ,不過這邊叫做\c Element - * - * 用來當作回傳資料的媒介 - */ - class Element{ - private: - typedef std::pair Entry; - Entry* entry_; - Node * node_; - // - void reset(Node* node) { - node_ = node; - delete entry_; - entry_ = (node == NULL ? NULL : new Entry(node->key_, node->value_)); - } - public: - Element(): entry_(NULL), node_(NULL) { - } - Element(Node* node): entry_(NULL), node_(NULL) { - reset(node); - } - Element(Element const& element2): entry_(NULL), node_(NULL) { - reset(element2.node_); - } - ~Element(){ - delete entry_; - } - - //! @brief 複製資料 - Element& copyFrom(Element const& e) { - reset(e.node_); - return *this; - } - - //! @brief 比對兩者是否為指向同一個Entry - bool same(Element const& e2) const { - return (node_ == e2.node_); - } - - //! @brief same as copyFrom - Element& operator=(Element const& e2) { - return copyFrom(e2); - } - - //! @brief 重導至\c std::pair* - Entry* operator->() { - return entry_; - } - - //! @brief 重導至\c std::pair& - Entry& operator*() { - return *entry_; - } - - //! @brief same as \c same(e2) - bool operator==(Element const& e2) const{ - return same(e2); - } - - //! @brief same as \c !same(e2) - bool operator!=(Element const& e2) const{ - return !same(e2); - } - }; - - //! @brief constructor - SplayTree_Range(): root_(NULL) { - } - - //! @brief constructor, 複製資料 - SplayTree_Range(SplayTree_Range const& tree2): - root_(dup((Node*)(tree2.root_))) { - } - - //! @brief destructor - ~SplayTree_Range() { - clear(root_); - } - - /*! - * @brief 複製資料 - */ - SplayTree_Range& copyFrom(SplayTree_Range const& tree2) { - clear(root_); - root_ = dup((Node*)(tree2.root_)); - return *this; - } - - /*! - * @brief 將資料都丟到 \c tree2 身上, 並且清空自己 - */ - void moveTo(SplayTree_Range* tree2) { - tree2->clear(); - tree2->root_ = root_; - root_ = NULL; - } - - /*! - * @brief 找出第一個(最小的) Element且 \c k <= 它的 Key, 並且回傳之. - * - * 找不到的話回傳 \c this->end() - */ - Element lowerBound(Key const& key) const { - splay(findKey(root_, key)); - if (root_ == NULL || !(root_->key_ < key)) return Element(root_); - if (root_->child_[1] == NULL) return Element(NULL); - splay(findMinMax(root_->child_[1], true)); - return Element(root_); - } - - /*! - * @brief 找出第一個(最小的) Element且 \c k < 它的 Key, 並且回傳之. - * - * 找不到的話回傳 \c this->end() - */ - Element upperBound(Key const& key) const { - splay(findKey(root_, key)); - if (root_ == NULL || key < root_->key_) return Element(root_); - if (root_->child_[1] == NULL) return Element(NULL); - splay(findMinMax(root_->child_[1], true)); - return Element(root_); - } - - /*! - * @brief 找出第一個(最小的) Element且 \c k >= 它的 Key, 並且回傳之. - * - * 找不到的話回傳 \c this->end() - */ - Element rLowerBound(Key const& key) const { - splay(findKey(root_, key)); - if (root_ == NULL || !(key < root_->key_)) return Element(root_); - if (root_->child_[0] == NULL) return Element(NULL); - splay(findMinMax(root_->child_[0], false)); - return Element(root_); - } - - /*! - * @brief 找出第一個(最小的) Element且 \c k > 它的 Key, 並且回傳之. - * - * 找不到的話回傳 \c this->end() - */ - Element rUpperBound(Key const& key) const { - splay(findKey(root_, key)); - if (root_ == NULL || root_->key_ < key) return Element(root_); - if (root_->child_[0] == NULL) return Element(NULL); - splay(findMinMax(root_->child_[0], false)); - return Element(root_); - } - - /*! - * @brief 找出 Key= \c k 的Elemenet 並回傳. 找不到的話回傳 \c this->end() - */ - Element find(Key const& key) const { - splay(findKey(root_, key)); - if (root_ != NULL && !(key < root_->key_) && !(root_->key_ < key)) { - return Element(root_); - } - return Element(NULL); - } - - /*! - * @brief 將Elements依照Key由小到大排序, 回傳第 \c ord 個Element (由0算起). - * - * 其中如果 \c ord>N-1, 則會回傳 \c this->last() - */ - Element order(size_t order) const { - if (root_ == NULL || order >= root_->size_) return Element(NULL); - splay(findOrder(root_, order + 1)); - return Element(root_); - } - - /*! - * @brief 回傳Key最小的Element, 如果SplayTree為空, 則回傳 \c this->end() - */ - Element first() const { - splay(findMinMax(root_, true)); - return Element(root_); - } - - /*! - * @brief 回傳Key最大的Element, 如果SplayTree為空, 則回傳 \c this->end() - */ - Element last() const { - splay(findMinMax(root_, false)); - return Element(root_); - } - - /*! - * @brief 回傳一個指向NULL的Element, - * - * 以供 \c find ,\c order ,\c first ,\c last 等判斷是否有找到相對應的Element - */ - Element end() const { - return Element(NULL); - } - - /*! - * @brief 回傳資料個數 - */ - size_t size() const { - return (root_ == NULL ? 0 : root_->size_); - } - - /*! - * @brief 回傳是否為空 - */ - bool empty() const{ - return (size() == 0); - } - - /*! - * @brief 查找 - * - * 詢問目前整個range的值 - */ - Value query() const { - if (root_ == NULL) return Value(0); - return root_->range_; - } - - /*! - * @brief 查找 - * - * 詢問給定range的值 - */ - Value query(Key const& first, Key const& last) const { - SplayTree_Range* self = (SplayTree_Range*)this; - Node* tmp; - rUpperBound(first); - self->split(self->root_, &tmp, &(self->root_)); - upperBound(last); - Value ret(0); - if (root_ != NULL && root_->child_[0] != NULL) { - ret = root_->child_[0]->range_; - } - self->root_ = self->merge(tmp, self->root_); - return ret; - } - - /*! - * @brief 清空 - */ - void clear() { - clear(root_); - root_ = NULL; - } - - /*! - * @brief 插入一組\c (Key ---> \c Value) - * - * 檢查是否已有Element的Key 為 \c key, 若有則回傳 \c false , 否則將 - * 一個 (Key -> Value) = (\c key -> \c value)的Element加入, 並回傳 \c true - */ - bool insert(Key const& key, Value const& value) { - if (root_ == NULL) { - root_ = new Node(key, value); - } - else { - Node* parent = (Node*)findKey(root_, key); - if (!(parent->key_ < key) && !(key < parent->key_)) { - splay(parent); - return false; - } - Node* new_node = new Node(key, value); - connect(parent, (parent->key_ < key ? 1 : 0), new_node); - parent->syncUp(); - splay(new_node); - } - return true; - } - - /*! - * @brief 刪除一組資料 - * - * 檢查是否已有Element的Key 為 \c key, 若有則刪除之, 並回傳 \c true, - * 否則則回傳 \c false - */ - bool erase(Key const& key) { - if (root_ == NULL) return false; - Node* body = (Node*)findKey(root_, key); - if (body->key_ < key || key < body->key_) { - splay(body); - return false; - } - Node* ghost; - if (body->child_[1] == NULL) { - ghost = body->child_[0]; - if (ghost != NULL) ghost->syncDown(); - } - else { - ghost = (Node*)findMinMax(body->child_[1], true); - connect(ghost, 0, body->child_[0]); - if (ghost != body->child_[1]) { - connect(ghost->parent_, 0, ghost->child_[1]); - connect(ghost, 1, body->child_[1]); - for (Node* a = ghost->parent_; a != ghost; a = a->parent_) - a->syncUp(); - } - ghost->syncUp(); - } - Node* parent = body->parent_; - connect(parent, parent != NULL && parent->child_[0] == body ? 0 : 1, ghost); - delete body; - splay(ghost != NULL ? ghost : parent); - return true; - } - - /*! - * @brief 將所有Element的Key同加上 \c delta - */ - void keyOffset(Key const& delta) { - if (root_ != NULL) { - root_->keyOffset(delta); - } - } - - /*! - * @brief 將所有Element的Value同加上 \c delta - */ - void valueOffset(Value const& delta){ - if (root_ != NULL) { - root_->valueUpdate(delta, false); - } - } - - /*! - * @brief 將所有Element的Value全部設定成\c value - */ - void valueOverride(Value const& value){ - if(root_ != NULL){ - root_->valueUpdate(value, true); - } - } - - /*! - * @brief 將\c tree2 清空, 再將所有Key > \c upper_bound 的Element都丟過去 - */ - void splitOut(Key const& upper_bound, SplayTree_Range* right) { - right->clear(); - if (rLowerBound(upper_bound) != end()) { - split(root_, &root_, &(right->root_)); - } - else { - right->root_ = root_; - root_ = NULL; - } - } - - /*! - * @brief 合併 - * - * 檢查是否自己中的 Key 都小於 \c tree2 中的Key, 是的話把 \c tree2` - * 中的 Element 都搬到自己這, 同時清空 \c tree2 , 否則回傳 \c false - */ - bool mergeAfter(SplayTree_Range* tree2) { - if (root_ == NULL || tree2->root_ == NULL || - last()->first < tree2->first()->first) { - root_ = merge(root_, tree2->root_); - tree2->root_ = NULL; - return true; - } - return false; - } - - /*! - * @brief 合併 - * - * 檢查是否自己中的 Key 都小於 \c tree2 中的Key, 或是完全相反, - * 是的話把 \c tree2`中的 Element 都搬到自己這, - * 同時清空 \c tree2 , 否則回傳 \c false - */ - bool merge(SplayTree_Range* tree2) { - if (root_ == NULL || tree2->root_ == NULL || - last()->first < tree2->first()->first) { - root_ = merge(root_, tree2->root_); - } - else if(tree2->last()->first < first()->first) { - root_ = merge(tree2->root_, root_); - } - else { - return false; - } - tree2->root_ = NULL; - return true; - } - - /*! - * @brief 就像\c stl::map::operator[] - * - * 會先檢查是否已有Element的Key 為 \c key, 若有則回傳相對應的Value的Reference - * 否則先執行 \c insert(key,Value()) 再回傳相對應的Reference - */ - Value& operator[](Key const& key) { - if (find(key) == end()) insert(key, Value()); - return root_->value_; - } - - //! @brief same as \c copyFrom(tree2) - SplayTree_Range& operator=(SplayTree_Range const& tree2){ - return copyFrom(tree2); - } -}; - -} // meow - -#endif // dsa_SplayTree_h__ diff --git a/meowpp/dsa/VP_Tree.h b/meowpp/dsa/VP_Tree.h deleted file mode 100644 index 3d85327..0000000 --- a/meowpp/dsa/VP_Tree.h +++ /dev/null @@ -1,337 +0,0 @@ -#ifndef dsa_VP_Tree_H__ -#define dsa_VP_Tree_H__ - -#include "../math/utility.h" - -#include - -#include -#include -#include -#include - -namespace meow { - -/*! - * @brief 跟KD_Tree很像歐 - * - * \c VP_Tree 用來維護由 \b N個K維度向量所成的集合 , - * 並可於該set中查找 \b 前i個離給定向量最接近的向量* . - * 不像 \c KD_Tree 二分樹每次都選擇一個維度去分, 分成小的跟大的, - * \c VP_Tree 每次選一個點, 將資料分成 離這個點近的, 跟離這個點遠的. - * 至於怎麼選呢...., 嘛還沒研究, 先random - * - * 參考資料連結: - * - http://stevehanov.ca/blog/index.php?id=130 - * - http://pnylab.com/pny/papers/vptree/vptree - * - * Template Class Operators Request - * -------------------------------- - * - * |const?|Typename|Operator | Parameters |Return Type | Description | - * |-----:|:------:|----------:|:-------------|:----------:|:------------------| - * |const | Vector|operator[] |(size_t \c n) | Scalar | 取得第\c n 維度量 | - * |const | Vector|operator= |(Vector \c v) | Vector& | copy operator | - * |const | Vector|operator< |(Vector \c v) | bool | 權重比較 | - * |const | Scalar| 'Scalar' |(int \c n) | Scalar | 建構子, - * 其中一定\c n=0or4 | - * |const | Scalar|operator* |(Scalar \c s) | Scalar | 相乘 | - * |const | Scalar|operator+ |(Scalar \c s) | Scalar | 相加 | - * |const | Scalar|operator- |(Scalar \c s) | Scalar | 相差 | - * |const | Scalar|operator- |( ) | Scalar | 取負號 | - * |const | Scalar|operator< |(Scalar \c s) | bool | 大小比較 | - * - * @note: - * -實測結果發覺, 維度小的時候, 比起中規中矩的 \c KD_Tree, \c VP_Tree 有 - * \b random 於其中, 因此時間複雜度只是期望值 \c O(logN) 但是測資大到 - * 一定程度, \c KD_Tree 效率會一整個大幅掉下, 但 \c VP_Tree 幾乎不受影響 - * -TODO \c insert(), \c erase() 算是未完成功能 - */ -template -class VP_Tree { -public: - typedef std::vector Vectors; -private: - struct Node { - size_t index_; - Scalar threshold_; - Node* nearChild_; - Node* farChild_; - // - Node(size_t index): index_(index), nearChild_(NULL), farChild_(NULL){ - } - }; - struct Answer { - size_t index_; - Scalar dist2_; - // - Answer(size_t index, Scalar const& dist2): index_(index), dist2_(dist2){ - } - Answer(Answer const& answer2): - index_(answer2.index_), dist2_(answer2.dist2_){ - } - }; - class AnswerCompare { - private: - Vectors const* vectors_; - bool cmpValue_; - public: - AnswerCompare(Vectors const* vectors, bool cmpValue): - vectors_(vectors), cmpValue_(cmpValue){ - } - bool operator()(Answer const& a, Answer const& b) const { - if (a.dist2_ < b.dist2_) return true; - if (b.dist2_ < a.dist2_) return false; - return (cmpValue_ && ((*vectors_)[a.index_] < (*vectors_)[b.index_])); - } - }; - typedef std::vector AnswerV; - typedef std::priority_queue Answers; - - Vectors vectors_; - Node* root_; - size_t dimension_; - bool needRebuild_; - - Scalar distance2(Vector const& v1, Vector const& v2) const { - Scalar ret(0); - for (size_t i = 0; i < dimension_; i++) ret += squ(v1[i] - v2[i]); - return ret; - } - int distanceCompare(Scalar const& a2, Scalar const& b2, - Scalar const& c2) const { - if (b2 < 0) { - return -distanceCompare(c2, -b2, a2); - } - Scalar cab(c2 - a2 - b2); - if (cab < Scalar(0)) return 1; - Scalar ab2(Scalar(4) * a2 * b2), cab2(squ(cab)); - if ( ab2 < cab2) return -1; - else if (cab2 < ab2) return 1; - else return 0; - } - Scalar split(ssize_t first, ssize_t last, size_t order, - Vector const& center) { - ssize_t first0 = first; - std::vector dist2(last - first + 1); - for (ssize_t i = first; i <= last; i++) { - dist2[i - first0] = distance2(vectors_[i], center); - } - while (first < last) { - size_t thresholdindex_ = first + rand() % (last - first + 1); - Scalar threshold(dist2[thresholdindex_ - first0]); - size_t large_first = last + 1; - for( ssize_t i=first; first<=(ssize_t)large_first-1; large_first--) { - if (threshold < dist2[large_first - 1 - first0]) continue; - while (i < (ssize_t)large_first-1&&!(threshold < dist2[i-first0])) i++; - if (i < (ssize_t)large_first - 1){ - std::swap(dist2 [large_first - 1 - first0], dist2 [i - first0]); - std::swap(vectors_[large_first - 1 ], vectors_[i ]); - i++; - } - else { - break; - } - } - if (large_first == (size_t)last + 1) { - std::swap(dist2 [thresholdindex_-first0], dist2 [last-first0]); - std::swap(vectors_[thresholdindex_ ], vectors_[last ]); - if ((ssize_t)order == last - first) { - first = last; - break; - } - last--; - } - else { - if (order < large_first - first) { - last = large_first - 1; - } - else { - order -= large_first - first; - first = large_first; - } - } - } - return dist2[first - first0]; - } - // - Node* build(ssize_t first, ssize_t last) { - if (first > last) return NULL; - Node* ret = new Node(first); - if (first < last) { - std::swap(vectors_[first], - vectors_[first + rand() % (last - first + 1)]); - ssize_t mid = (first + 1 + last + 1) / 2; - ret->threshold_ = split(first + 1, last, mid - (first + 1), - vectors_[first]); - ret->nearChild_ = build(first + 1, mid - 1 ); - ret->farChild_ = build( mid , last); - } - return ret; - } - void query(Vector const& vector, - size_t k, - AnswerCompare const& cmp, - Node const* node, - Answers* out) const { - if (node == NULL) return ; - Scalar dist2 = distance2(vector, vectors_[node->index_]); - Answer my_ans(node->index_, dist2); - if (out->size() < k || cmp(my_ans, out->top())) { - out->push(my_ans); - if (out->size() > k) { - out->pop(); - } - } - if (node->nearChild_ == NULL && node->farChild_ == NULL) return ; - if (out->size() < k || distanceCompare(dist2, -out->top().dist2_, - node->threshold_) <= 0) { - query(vector, k, cmp, node->nearChild_, out); - } - if (out->size() < k || distanceCompare(dist2, out->top().dist2_, - node->threshold_) >= 0) { - query(vector, k, cmp, node->farChild_, out); - } - } - void clear(Node* root) { - if(root == NULL) return ; - clear(root->nearChild_); - clear(root->farChild_); - delete root; - } - Node* dup(Node* root) { - if(root == NULL) return ; - Node* ret = new Node(root->index_); - ret->threshold_ = root->threshold_; - ret->nearChild_ = dup(root->nearChild_); - ret->farChild_ = dup(root->farChild_ ); - return ret; - } -public: - //! @brief constructor, with dimension = 1 - VP_Tree(): root_(NULL), vectors_(0), dimension_(1), needRebuild_(false){ - reset(0); - } - - //! @brief constructor, 複製資料 - VP_Tree(VP_Tree const& tree2): - vectors_(tree2.vectors_), - root_(dup(tree2.root_)), - dimension_(tree2.dimension_), - needRebuild_(tree2.needRebuild_) { - } - - //! @brief constructor, 給定dimension - VP_Tree(size_t dimension): - vectors_(0), - root_(NULL), - dimension_(0), - needRebuild_(false) { - reset(dimension); - } - - //! @brief destructor - ~VP_Tree() { - clear(root_); - } - - /*! - * @brief 複製資料 - */ - VP_Tree& copyFrom(VP_Tree const& tree2) { - reset(tree2.dimension_); - vectors_ = tree2.vectors_; - root_ = dup(tree2.root_); - needRebuild_ = tree2.needRebuild_; - return *this; - } - - /*! - * @brief 將給定的Vector加到set中 - */ - void insert(Vector const& vector) { - vectors_.push_back(vector); - needRebuild_ = true; - } - - /*! - * @brief 將給定的Vector從set移除 - */ - bool erase (Vector const& vector) { - for (ssize_t i = 0, I = vectors_.size(); i < I; i++) { - if (vectors_[i] == vector) { - if (i != I - 1) std::swap(vectors_[i], vectors_[I - 1]); - needRebuild_ = true; - vectors_.pop_back(); - return true; - } - } - return false; - } - - /*! - * @brief 檢查至今是否有 insert/erase 被呼叫來決定是否 \c rebuild() - */ - void build() { - if (needRebuild_) { - forceBuild(); - } - } - - /*! - * @brief 重新建樹 - */ - void forceBuild() { - root_ = build(0, (size_t)vectors_.size() - 1); - needRebuild_ = false; - } - - /*! - * @brief 查找 - * - * 於set中找尋距離指定向量前 \c i 近的向量, 並依照由近而遠的順序排序. - * 如果有兩個向量\c v1,v2 距離一樣, 且 \c cmp 為\c true , 則直接依照 - * \c v1build(); - AnswerCompare cmp(&vectors_, compareWholeVector); - Answers answers(cmp); - query(vector, nearestNumber, cmp, root_, &answers); - std::stack rev; - for ( ; !answers.empty(); answers.pop()) rev.push(answers.top()); - Vectors ret; - for ( ; !rev.empty(); rev.pop()) ret.push_back(vectors_[rev.top().index_]); - return ret; - } - - /*! - * @brief 清空所有資料 - */ - void clear() { - clear(root_); - vectors_.clear(); - root_ = NULL; - needRebuild_ = false; - } - - /*! - * @brief 清空所有資料並重新給定維度 - */ - size_t reset(size_t dimension) { - clear(); - dimension_ = std::max((size_t)1, dimension); - return dimension_; - } - - //! @brief same as \c copyFrom(tree2) - VP_Tree& operator=(VP_Tree const& tree2) { - return copyFrom(tree2); - } -}; - -} // meow - -#endif // dsa_VP_Tree_H__ diff --git a/meowpp/geo/!readme.asciidoc b/meowpp/geo/!readme.asciidoc deleted file mode 100644 index 7308afc..0000000 --- a/meowpp/geo/!readme.asciidoc +++ /dev/null @@ -1,12 +0,0 @@ - -計算幾何相關, 算是從math中特化出來的 - -===== Vectors.h - -實作上不是用陣列, 是直接宣告2到3個變數分別存x, y (,z) - -.Classes -* `meow::Vector2D` -* `meow::Vector3D` - - diff --git a/meowpp/geo/Vectors.h b/meowpp/geo/Vectors.h deleted file mode 100644 index 0f69a86..0000000 --- a/meowpp/geo/Vectors.h +++ /dev/null @@ -1,505 +0,0 @@ -#ifndef geo_Vectors_H__ -#define geo_Vectors_H__ - -#include "../math/utility.h" -#include "../math/Vector.h" -#include "../math/Matrix.h" - -#include - -namespace meow { - -/*! - * @brief 2D's vector - * - * @author cat_leopard - */ -template -class Vector2D { -private: - Scalar x_, y_; -public: - //! @brief consturctor (0, 0) - Vector2D(): x_(0), y_(0) { - } - - //! @brief consturctor (from another Vector2D) - Vector2D(Vector2D const& v): x_(v.x_), y_(v.y_) { - } - - //! @brief constructor (s, s) - Vector2D(Scalar const& s): x_(s), y_(s) { - } - - //! @brief constructor (sx, sy) - Vector2D(Scalar const& sx, Scalar const& sy): x_(sx), y_(sy) { - } - - //! @brief constructor - Vector2D(size_t dimension, Scalar const& s): x_(s), y_(s) { - } - - //! @brief constructor (from another Vector) - Vector2D(Vector const& v): x_(v(0)), y_(v(1)) { - } - - //! @brief constructor (from another Vector, i-th) - Vector2D(Vector const& v, size_t i): x_(v(i)), y_(v(i + 1)) { - } - - //! @brief constructor (from a Matrix) - Vector2D(Matrix const& m): x_(m(0, 0)), y_(m(1, 0)) { - } - - //! @brief constructor (from a Matrix, i-th row, j-th col) - Vector2D(Matrix const& m, size_t i, size_t j): - x_(m(i, j)), y_(m(i + 1, j)) { - } - - //! @brief destructor - ~Vector2D() { - } - - //! @brief copy - Vector2D& copyFrom(Vector2D const& v) { - return xy(v.x(), v.y()); - } - - size_t dimension() const { return 2; } //!< @brief return 2 - - Scalar const& x() const { return x_; } //!< @brief access x - Scalar const& y() const { return y_; } //!< @brief access y - - Scalar& xGet() { return x_; } //!< @brief access x with non constant reference - Scalar& yGet() { return y_; } //!< @brief access y with non constant reference - - Scalar const& x(Scalar const& s) { x_ = s; return x(); } //!< @brief modify x - Scalar const& y(Scalar const& s) { y_ = s; return y(); } //!< @brief modify y - - //! @brief modify x and y - Vector2D& xy(Scalar const& sx, Scalar const& sy){ - x(sx); - y(sy); - return *this; - } - - //! @brief access the \c i -th scalar (0 => x, 1 => y) - Scalar const& scalar(size_t i) const { - return (i == 0 ? x() : y()); - } - - //! @brief modivy the \c i -th scalar (0 => x, 1 => y) - Scalar const& scalar(size_t i, Scalar const& s) { - return (i == 0 ? x(s) : (i == 1 ? y(s) : s)); - } - - //! @brief return \a +(*this) - Vector2D positive() const { - return *this; - } - - //! @brief return \a -(*this) - Vector2D negative() const { - return Vector2D(-x(), -y()); - } - - //! @brief return \a count-clockwise \a rotate \a 90 \a degree of itself - Vector2D right()const{ - return Vector2D(-y(), x()); - } - - //! @brief return \a (*this)+v - Vector2D add(Vector2D const& v) const { - return Vector2D(x() + v.x(), y() + v.y()); - } - - //! @brief Let itself add v - Vector2D& added(Vector2D const& v) { - return xy(x() + v.x(), y() + v.y()); - } - - //! @brief return \a (*this)-v - Vector2D sub(Vector2D const& v) const { - return Vector2D(x() - v.x(), y() - v.y()); - } - - //! @brief Let itself substract v - Vector2D& subed(Vector2D const& v) { - return xy(x() - v.x(), y() - v.y()); - } - - //! @brief return \a (*this)*s , where s is a scalar - Vector2D mul(Scalar const& s) const { - return Vector2D(x() * s, y() * s); - } - - //! @brief Let itself mulitple s - Vector2D& muled(Scalar const& s) { - return xy(x() * s, y() * s); - } - - //! @brief return \a (*this)/s , where s is a scalar - Vector2D div(Scalar const& s) const { - return Vector2D(x() / s, y() / s); - } - - //! @brief Let itself divide s - Vector2D& dived(Scalar const& s) { - return xy(x() / s, y() / s); - } - - //! @brief same as dot(v) - Scalar mul(Vector2D const& v) const { - return dot(v); - } - - //! @brief dot - Scalar dot(Vector2D const& v) const { - return x() * v.x() + y() * v.y(); - } - - //! @brief cross - Scalar cross(Vector2D const& v) const { - return x() * v.y() - y() * v.x(); - } - - //! @brief sqrt of length2 - Scalar length() const { - return Scalar(sqrt(double(length2()))); - } - - //! @brief same as \a dot(*this) - Scalar length2() const { - return dot(*this); - } - - //! @brief return normalize form of itself - Vector2D normalize() const { - return div(length()); - } - - //! @brief normalize itself - Vector2D& normalized() { - return dived(length()); - } - - //! @brief return rotate \a theta degree of itself - Vector2D rotate(Scalar const& theta) const { - Scalar cs(cos(-double(theta))); - Scalar sn(sin(-double(theta))); - Vector2D new_x(cs, sn); - return Vector2D(new_x.dot(*this), new_x.cross(*this)); - } - - //! @brief Let itself rotate \a theta degree - Vector2D& rotated(Scalar const& theta) { - return copyFrom(rotate(theta)); - } - - //! @brief return reflect from given vector \a v - Vector2D reflect(Vector2D const& v) const { - return v.mul(v.dot(*this) * 2 / v.length2()).sub(*this); - } - - //! @brief reflect itself given vector \a v - Vector2D& reflected(Vector2D const& v) { - return copyFrom(reflecte(v)); - } - - //! @brief return a 2x1 matrix form of itself - Matrix matrix() const { - static Matrix ret(2, 1, Scalar(0)); - ret(0, 0, x()); - ret(1, 0, y()); - return ret; - } - - //! @brief return a 3x1 matrix form of itself - Matrix matrix(Scalar const& homo) const { - static Matrix ret(3, 1, Scalar(0)); - ret(0, 0, x()); - ret(1, 0, y()); - ret(2, 0, homo); - return ret; - } - - Scalar const& operator()(size_t n) const { - return (n == 0 ? x() : y()); - } - - Vector2D& operator()(Scalar const& sx, Scalar const& sy) { - return xy(sx, sy); - } - - Vector2D operator+() const { return positive(); } - Vector2D operator-() const { return negative(); } - Vector2D operator~() const { return right (); } - - Vector2D operator+(Vector2D const& v) const { return add(v); } - Vector2D operator-(Vector2D const& v) const { return sub(v); } - Vector2D operator*(Scalar const& s) const { return mul(s); } - Vector2D operator/(Scalar const& s) const { return div(s); } - Scalar operator*(Vector2D const& v) const { return mul(v); } - - Vector2D& operator =(Vector2D const& v) { return copyFrom(v); } - Vector2D& operator+=(Vector2D const& v) { return added(v); } - Vector2D& operator-=(Vector2D const& v) { return subed(v); } - Vector2D& operator*=(Scalar const& s) { return muled(s); } - Vector2D& operator/=(Scalar const& s) { return dived(s); } - bool operator==(Vector2D const& v) const { return x()==v.x() && y()==v.y(); } -}; - -/*! - * @brief 3D's vector - * - * @author cat_leopard - */ -template -class Vector3D{ -private: - Scalar x_, y_, z_; -public: - //! @brief consturctor (0, 0) - Vector3D(): x_(0), y_(0), z_(0) { - } - - //! @brief consturctor (from another Vector3D) - Vector3D(Vector3D const& v): x_(v.x_), y_(v.y_), z_(v.z_) { - } - - //! @brief constructor (s, s) - Vector3D(Scalar const& s): x_(s), y_(s), z_(s) { - } - - //! @brief constructor - Vector3D(size_t dimension, Scalar const& s): x_(s), y_(s), z_(s) { - } - - //! @brief constructor (sx, sy) - Vector3D(Scalar const& sx, - Scalar const& sy, - Scalar const& sz): x_(sx), y_(sy), z_(sz) { - } - - //! @brief constructor (from another Vector) - Vector3D(Vector const& v): x_(v(0)), y_(v(1)), z_(v(2)) { - } - - //! @brief constructor (from another Vector, i-th) - Vector3D(Vector const& v, size_t i): x_(v(i)), y_(v(i+1)), z_(v(i+2)){ - } - - //! @brief constructor (from a Matrix) - Vector3D(Matrix const& m): x_(m(0, 0)), y_(m(1, 0)), z_(m(2, 0)) { - } - - //! @brief constructor (from a Matrix, i-th row, j-th col) - Vector3D(Matrix const& m, size_t i, size_t j): - x_(m(i, j)), y_(m(i + 1, j)), z_(m(i + 2, j)) { - } - - //! @brief destructor - ~Vector3D() { - } - - //! @brief copy - Vector3D& copyFrom(Vector3D const& v) { - return xyz(v.x(), v.y(), v.z()); - } - - size_t dimension() const { return 3; } //!< @brief return 2 - - Scalar const& x() const { return x_; } //!< @brief access x - Scalar const& y() const { return y_; } //!< @brief access y - Scalar const& z() const { return z_; } //!< @brief access z - - Scalar& xGet() { return x_; } //!< @brief access x with non-constant reference - Scalar& yGet() { return y_; } //!< @brief access y with non-constant reference - Scalar& zGet() { return z_; } //!< @brief access z with non-constant reference - - Scalar const& x(Scalar const& s) { x_ = s; return x(); } //!< @brief modify x - Scalar const& y(Scalar const& s) { y_ = s; return y(); } //!< @brief modify y - Scalar const& z(Scalar const& s) { z_ = s; return z(); } //!< @brief modify z - - //! @brief modify x, y and z - Vector3D& xyz(Scalar const& sx, Scalar const& sy, Scalar const& sz) { - x(sx); - y(sy); - z(sz); - return *this; - } - - //! @brief access the \c i -th scalar (0 => x, 1 => y, 2 => z) { - Scalar const& scalar(size_t i) const { - return (i == 0 ? x() : (i == 1 ? y() : z())); - } - - //! @brief modivy the \c i -th scalar (0 => x, 1 => y, 2 => z) - Scalar const& scalar(size_t i, Scalar const& s) { - return (i == 0 ? x(s) : (i == 1 ? y(s) : (i == 2 ? z(s) : s ))); - } - - //! @brief return \a +(*this) - Vector3D positive() const { - return *this; - } - - //! @brief return \a -(*this) - Vector3D negative() const { - return Vector3D(-x(), -y(), -z()); - } - - //! @brief return \a (*this)+v - Vector3D add(Vector3D const& v) const { - return Vector3D(x() + v.x(), y() + v.y(), z() + v.z()); - } - - //! @brief Let itself add v - Vector3D& added(Vector3D const& v) { - return xyz(x() + v.x(), y() + v.y(), z() + v.z()); - } - - //! @brief return \a (*this)-v - Vector3D sub(Vector3D const& v) const { - return Vector3D(x() - v.x(), y() - v.y(), z() - v.z()); - } - - //! @brief Let itself substract v - Vector3D& subed(Vector3D const& v) { - return xyz(x() - v.x(), y() - v.y(), z() - v.z()); - } - - //! @brief return \a (*this)*s , where s is a scalar - Vector3D mul(Scalar const& s) const { - return Vector3D(x() * s, y() * s, z() * s); - } - - //! @brief Let itself mulitple s - Vector3D& muled(Scalar const& s) { - return xyz(x() * s, y() * s, z() * s); - } - - //! @brief return \a (*this)/s , where s is a scalar - Vector3D div(Scalar const& s) const { - return Vector3D(x() / s, y() / s, z() / s); - } - - //! @brief Let itself divide s - Vector3D& dived(Scalar const& s) { - return xyz(x() / s, y() / s, z() / s); - } - - //! @brief same as dot(v) - Scalar mul(Vector3D const& v) const { - return dot(v); - } - - //! @brief dot - Scalar dot(Vector3D const& v) const { - return x() * v.x() + y() * v.y() + z() * v.z(); - } - - //! @brief cross - Vector3D cross(Vector3D const& v) const { - return Vector3D(y() * v.z() - z() * v.y(), - z() * v.x() - x() * v.z(), - x() * v.y() - y() * v.x()); - } - - //! @brief crossed - Vector3D& crossed(Vector3D const& v) { - return copyFrom(cross(v)); - } - - //! @brief sqrt of length2 - Scalar length() const { - return Scalar(sqrt(double(length2()))); - } - - //! @brief same as \a dot(*this) - Scalar length2() const { - return dot(*this); - } - - //! @brief return normalize form of itself - Vector3D normalize() const { - return div(length()); - } - - //! @brief normalize itself - Vector3D& normalized() { - return dived(length()); - } - - //! @brief return rotate \a theta degree by \a axis of itself - Vector3D rotate(Vector3D const& axis, double theta) const { - Vector3D a(axis.normalize()); - Vector3D xx(sub(a) .mul(cos(theta))); - Vector3D yy(a.cross(*this).mul(sin(theta))); - return a.mul(a.dot(*this)).add(xx).add(yy); - } - - //! @brief Let itself rotate \a theta degree - Vector3D& rotated(Vector3D const& axis, double theta) { - return copyFrom(rotate(axis, theta)); - } - - //! @brief return reflect from given vector \a v - Vector3D reflect(Vector3D const& v) const { - return v.mul(v.dot(*this) * 2 / v.length2()).sub(*this); - } - - //! @brief reflect itself given vector \a v - Vector3D& reflected(Vector3D const& v) { - return copyFrom(reflecte(v)); - } - - //! @brief return a 3x1 matrix form of itself - Matrix matrix() const { - static Matrix ret(3, 1, Scalar(0)); - ret(0, 0, x()); - ret(1, 0, y()); - ret(2, 0, z()); - return ret; - } - - //! @brief return a 4x1 matrix form of itself - Matrix matrix(Scalar const& homo) const { - static Matrix ret(4, 1, Scalar(0)); - ret(0, 0, x()); - ret(1, 0, y()); - ret(2, 0, z()); - ret(3, 0, homo); - return ret; - } - - Scalar const& operator()(size_t n) const { - return (n == 0 ? x() : (n == 1 ? y() : z())); - } - - Vector3D& operator()(Scalar const& sx, Scalar const& sy, Scalar const& sz) { - return xyz(sx, sy, sz); - } - - Vector3D operator+() const { return positive(); } - Vector3D operator-() const { return negative(); } - - Vector3D operator+(Vector3D const& v) const { return add(v); } - Vector3D operator-(Vector3D const& v) const { return sub(v); } - Vector3D operator*(Scalar const& s) const { return mul(s); } - Vector3D operator/(Scalar const& s) const { return div(s); } - Scalar operator*(Vector3D const& v) const { return mul(v); } - - Vector3D& operator =(Vector3D const& v) { return copyFrom(v); } - Vector3D& operator+=(Vector3D const& v) { return added(v); } - Vector3D& operator-=(Vector3D const& v) { return subed(v); } - Vector3D& operator*=(Scalar const& s) { return muled(s); } - Vector3D& operator/=(Scalar const& s) { return dived(s); } - bool operator==(Vector3D const& v) const { return (x() == v.x() && - y() == v.y() && - z() == v.z()); } -}; - -} // meow - -#endif // geo_Vectors_H__ diff --git a/meowpp/gra/Bitmap.h b/meowpp/gra/Bitmap.h deleted file mode 100644 index 5a16037..0000000 --- a/meowpp/gra/Bitmap.h +++ /dev/null @@ -1,437 +0,0 @@ -#ifndef gra_Bitmap_H__ -#define gra_Bitmap_H__ - -#include "../math/utility.h" -#include "../math/Matrix.h" - -#include "../oo/ObjBase.h" - -#include -#include -#include -#include -#include - -namespace meow { - -const unsigned int kBitmapReadWritePixels = 0x1; - -/*! - * @brief 二維點陣資料 - * - * @author cat_leopard - */ -template -class Bitmap: public ObjBase { -private: - Matrix matrix_; - - //! 回傳高斯模糊的權重 - static std::vector gaussianFactor1(double sigma) { - double sigma2 = squ(sigma); - size_t width = std::max(ceil((double)(sigma * 2)), 0.0); - std::vector factor(width + 1 + width); - for (size_t x = 0; x < width; x++) { - double e = exp(-(squ((double)x)) / (2.0 * sigma2)); - factor[width - x - 1] = e; - factor[width + x + 1] = e; - } - factor[width] = 1.0; - return factor; - } - - //! 回傳gradiance的權重 - static std::vector gradianceFactor1(double sigma) { - double sigma2 = squ(sigma), ss = sigma * 2; - size_t width = std::max(ceil(ss), 1.0); - std::vector factor(width + 1 + width); - for (size_t x = 0; x < width; x++) { - double e = exp(-(squ((double)x)) / (2.0 * sigma2)); - factor[width - x - 1] = (double)x * e; - factor[width + x + 1] = -(double)x * e; - } - factor[width] = 0.0; - return factor; - } - - //! 針對某一方向用某種權重模糊 - Bitmap xyBlur(std::vector const& factor, - ssize_t dx, ssize_t dy) const { - if (factor.size() <= 1) - return *this; - Bitmap ret(height(), width(), Pixel(0)); - ssize_t w = factor.size() / 2; - for (size_t y = 0, Y = height(); y < Y; y++) - for (size_t x = 0, X = width(); x < X; x++) { - Pixel sum(0); - double fsum(0); - for (ssize_t i = -w; i <= w; i++) { - ssize_t x2 = (ssize_t)x + dx * i; - ssize_t y2 = (ssize_t)y + dy * i; - if (0 <= x2 && x2 < (ssize_t)X && 0 <= y2 && y2 < (ssize_t)Y) { - sum = sum + pixel(y2, x2) * factor[i + w]; - fsum = fsum + fabs(factor[i + w]); - } - } - ret.pixel(y, x, sum / fsum); - } - return ret; - } -public: - /*! - * @brief constructor, 產生一個空的Bitmap - */ - Bitmap() { - } - - /*! - * @brief constructor, 複製一個bitmap - */ - Bitmap(Bitmap const& b): matrix_(b.matrix_) { - } - - /*! - * @brief constructor, copy data from a matrix - */ - Bitmap(Matrix const& b): matrix_(b) { - } - - /*! - * @brief constructor, 指定寬高, 預設\c Pixel - * - * @param [in] h 高 - * @param [in] w 寬 - * @param [in] p 預設pixel - */ - Bitmap(size_t h, size_t w, Pixel const& p): matrix_(h, w, p) { - } - - /*! - * @brief destructor - */ - ~Bitmap() { - } - - /*! - * @brief 複製 - */ - Bitmap& copyFrom(Bitmap const& b) { - matrix_.copyFrom(b.matrix_); - return *this; - } - - /*! - * @brief reference - */ - Bitmap& referenceFrom(Bitmap const& b) { - matrix_.referenceFrom(b.matrix_); - return *this; - } - - /*! - * @brief 全部重設 - * - * @param [in] h 高 - * @param [in] w 寬 - * @param [in] p 預設pixel - * @return 無 - */ - void reset(size_t h, size_t w, Pixel const& p) { - matrix_.reset(h, w, p); - } - - /*! - * @brief 清除資料, 寬高階規零 - */ - void clear() { - matrix_.clear(); - } - - /*! - * @brief 回傳高度 - */ - size_t height() const { - return matrix_.rows(); - } - - /*! - * @brief 回傳寬度 - */ - size_t width() const { - return matrix_.cols(); - } - - /*! - * @brief 回傳高度乘以寬度 - */ - size_t size() const { - return matrix_.size(); - } - - /*! - * @brief 修改高度 - * - * @param [in] h2 新的高 - * @param [in] p 如果高有變大, 則新長出來的地方用此 pixel填補 - * @return 新的高 - */ - size_t height(size_t h2, Pixel const& p) { - return matrix_.rows(h2, p); - } - - /*! - * @brief 修改寬度 - * - * @param [in] w2 新的寬 - * @param [in] p 如果寬有變大, 則新長出來的地方用此 pixel填補 - * @return 新的寬 - */ - size_t width(size_t w2, Pixel const& p) { - return matrix_.cols(w2, p); - } - - /*! - * @brief 修改寬高 - * - * @param [in] h2 新的高 - * @param [in] w2 新的寬 - * @param [in] p 如果寬or高有變大, 則新長出來的地方用此 pixel填補 - * @return 新的size - */ - size_t size(size_t h2, size_t w2, Pixel const& p) { - return matrix_.size(h2, w2, p); - } - - /*! - * @brief 取得 (y, x) 的pixel - * - * @param [in] y - * @param [in] x - * @return 該pixel 的 constant reference - */ - Pixel pixel(size_t y, size_t x) const { - return matrix_.entry(y, x); - } - - /*! - * @brief 修改 (y, x) 的pixel - * - * @param [in] y - * @param [in] x - * @param [in] p 指定的顏色 - * @return 該pixel 的 constant reference - */ - Pixel pixel(size_t y, size_t x, Pixel const& p) { - return matrix_.entry(y, x, p); - } - - /*! - * @brief 區塊修改 - * - * 一口氣將一個矩形區塊修改成指定的顏色 - * - * @param [in] yFirst y軸方向最小值(含) - * @param [in] yLast y軸方向最大值(含) - * @param [in] xFirst x軸方向最小值(含) - * @param [in] xLast x軸方向最大值(含) - * @param [in] p 指定的顏色 - * @return 無 - */ - void pixels(ssize_t yFirst, ssize_t yLast, - ssize_t xFirst, ssize_t xLast, - Pixel const& p) { - return matrix_.entries(yFirst, yLast, xFirst, xLast, p); - } - - /*! - * @brief 回傳矩陣形式 - */ - Matrix matrix() const { - return matrix_; - } - - /*! - * @brief 回傳矩陣形式 (non-constant form) - */ - Matrix& matrixGet() { - return matrix_; - } - - /*! - * @brief 直接設定 - */ - Matrix matrix(Matrix const& p) { - matrix_.copyFrom(p); - return matrix(); - } - - /*! - * @brief 回傳高斯模糊 - * - * @param [in] radiusY 高斯模糊的Y軸方向的sigma - * @param [in] radiusX 高斯模糊的X軸方向的sigma - * @return 一個\c Bitmap , 是自己被高斯模糊後的結果 - */ - Bitmap gaussian(double radiusY, double radiusX) const { - return (xyBlur(gaussianFactor1(radiusY), 1, 0). - xyBlur(gaussianFactor1(radiusX), 0, 1)); - } - - /*! - * @brief 把自己高斯模糊 - * - * @param [in] radiusY 高斯模糊的Y軸方向的sigma - * @param [in] radiusX 高斯模糊的X軸方向的sigma - * @return *this - */ - Bitmap& gaussianed(double radiusY, double radiusX) { - return copyFrom(gaussian(radiusY, radiusX)); - } - - /*! - * @brief 回傳對x偏微分 - * - * @param [in] radiusY 高斯模糊的Y軸方向的sigma - * @param [in] radiusX 高斯模糊的X軸方向的sigma - * @return 一個\c Bitmap , 是自己被偏微分後的結果 - */ - Bitmap gradianceX(double radiusY, double radiusX) const { - return (xyBlur(gaussianFactor1(radiusY), 1, 0). - xyBlur(gradianceFactor1(radiusX), 0, 1)); - } - - /*! - * @brief 把自己對x偏微分 - * - * @param [in] radiusY 高斯模糊的Y軸方向的sigma - * @param [in] radiusX 高斯模糊的X軸方向的sigma - * @return *this - */ - Bitmap& gradiancedX(double radiusY, double radiusX) { - return copyFrom(gradianceX(radiusY, radiusX)); - } - - /*! - * @brief 回傳對y偏微分 - * - * @param [in] radiusY 高斯模糊的Y軸方向的sigma - * @param [in] radiusX 高斯模糊的X軸方向的sigma - * @return 一個\c Bitmap , 是自己被偏微分後的結果 - */ - Bitmap gradianceY (double radiusY, double radiusX) const { - return (xyBlur(gaussianFactor1(radiusX), 0, 1). - xyBlur(gradianceFactor1(radiusY), 1, 0)); - } - - /*! - * @brief 把自己對y偏微分 - * - * @param [in] radiusY 高斯模糊的Y軸方向的sigma - * @param [in] radiusX 高斯模糊的X軸方向的sigma - * @return *this - */ - Bitmap& gradiancedY(double radiusY, double radiusX) { - return copyFrom(gradianceY(radiusY, radiusX)); - } - - /*! - * @brief same as \c copyFrom(b) - */ - Bitmap& operator=(Bitmap const& b) { - return copyFrom(b); - } - - /*! - * @brief same as \c pixel(y, x) - */ - Pixel operator()(size_t y, size_t x) const { - return pixel(y, x); - } - - /*! - * @brief same as \c pixel(y, x, p) - */ - Pixel const& operator()(size_t y, size_t x, Pixel const& p) const { - return pixel(y, x, p); - } - - /*! @brief 將資料寫入檔案 - * - * @note 未完成, 輸入參數 fg 無用 - */ - bool write(FILE* f, bool bin, unsigned int fg) const { - if (fg & kBitmapReadWritePixels) - return false; - if (bin) { - long tmp; - if (fwrite(&(tmp = matrix_.cols()), sizeof(tmp), 1, f) < 1) return false; - if (fwrite(&(tmp = matrix_.rows()), sizeof(tmp), 1, f) < 1) return false; - } - else { - if (fprintf(f, "%ld %ld\n", (long)matrix_.cols(), (long)matrix_.rows()) - < 2) return false; - } - return true; - } - - /*! @brief 將資料讀入 - * - * @note 未完成, 輸入參數 fg 無用 - */ - bool read(FILE* f, bool bin, unsigned int fg) { - if (fg & kBitmapReadWritePixels) - return false; - long tmp1, tmp2; - if (bin) { - if (fread(&tmp1, sizeof(tmp1), 1, f) < 1) return false; - if (fread(&tmp2, sizeof(tmp2), 1, f) < 1) return false; - } - else { - if (fscanf(f, "%ld %ld", &tmp1, &tmp2) < 2) return false; - } - matrix_.size(tmp1, tmp2, Pixel(0)); - return true; - } - - /*! @brief new一個自己 - * - * @return 一個new出來的Bitmap - */ - ObjBase* create() const { - return new Bitmap(); - } - - /*! @brief 複製資料 - * - * 輸入型別是 \c ObjBase \c const* - * 這裡假設實體其實是 \c Bitmap. - * 事實上這個method就只是幫忙轉型然後呼叫原本的\c copyFrom - * - * @param [in] b 資料來源 - * @return this - */ - ObjBase* copyFrom(ObjBase const* b) { - return &(copyFrom(*(Bitmap const*)b)); - } - - /*! @brief 回傳class的type - * - * @return \c char \c const\c * 形式的typename - */ - char const* ctype() const{ - return typeid(*this).name(); - } - - /*! @brief 回傳class的type - * - * @return \c std::string 形式的typename - */ - std::string type() const { - return std::string(ctype()); - } -}; - - -} // meow - -#endif // gra_Bitmap_H__ diff --git a/meowpp/gra/BitmapDescript.h b/meowpp/gra/BitmapDescript.h deleted file mode 100644 index fe659f6..0000000 --- a/meowpp/gra/BitmapDescript.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef BitmapDescript_H__ -#define BitmapDescript_H__ - -#include "../Self.h" - -#include "../oo/ObjBase.h" - - - -class FeaturePointDescript: public ObjBase { -private: - struct Myself { - double ratioL_; - size_t wSize_; - size_t cNumber_; - }; - Self self; -public: - FeaturePointDescript() { - } - - ~FeaturePointDescript() { - } - - - bool write(FILE* f, bool bin, unsigned int fg) const { - return false; - } - - bool read(FILE* f, bool bin, unsigned int fg) { - return false; - } - - ObjBase* create() const { - return new FeaturePointDescript(); - } - - ObjBase* copyFrom(ObjBase const& b) { - return &(copyFrom(*(FeaturePointDescript const*)b)); - } - - char const* ctype() const { - return typeid(*this).name(); - } - - std::string type() const { - return std::string(ctype()); - } -}; - -#endif // BitmapDescript_H__ diff --git a/meowpp/gra/BundleAdjustment.h b/meowpp/gra/BundleAdjustment.h deleted file mode 100644 index 60040da..0000000 --- a/meowpp/gra/BundleAdjustment.h +++ /dev/null @@ -1,105 +0,0 @@ -#ifndef BundleAdjustment_H__ -#define BundleAdjustment_H__ - -#include "Eye.h" - -#include "../oo/ObjBase.h" - -namespace meow { - -/*! - * @brief 列舉每個 \c Eye 可以有哪些種類的移動 - */ -enum EyesReferenceInfoFlags { - CAN_OFFSET = 0x01, //!< 平移 - CAN_ROTATE = 0x02, //!< 旋轉 - CAN_ZOOM = 0x04 //!< 改變焦距 -}; - -/*! - * @brief 記住每個 \c Eye 的reference以及Flag - */ -template -struct EyesReferenceInfo { - unsigned long flag; //!< Flag, 定義如EyesReferenceInfoFlags - Eye eye; //!< reference - - /*! - * @brief constructor with nothing - */ - EyesReferenceInfo(): flag(0), eye() { - } - - /*! - * @brief constructor with flag and an Eye object. Here we will let - * memember '.eye' reference from the specify paramter \c e - */ - EyesReferenceInfo(Eye& e, unsigned long f): flag(f), eye() { - eye.referenceFrom(e); - } - - /*! - * @brief constructor with another EyesReferenceInfo - */ - EyesReferenceInfo(EyesReferenceInfo const& si): flag(si.flag), eye() { - eye.referenceFrom(si.eye); - } - - /*! - * @brief desructor - */ - ~EyesReferenceInfo() { - } - - /*! - * @brief copy operator, still use reference method - */ - EyesReferenceInfo& operator=(EyesReferenceInfo const& e) { - flag = e.flag; - eye.referenceFrom(e.eye); - return *this; - } -}; - -/*! - * @brief 這邊定義Bundle-Adjustment就是利用一系列場景來反推算出\b 相機資訊 - * (包含拍攝座標, 角度與焦距) 或是在已知相機資訊的情況下推算出底片中 - * 物體如何移動. - */ -template -class BundleAdjustment: public ObjBase { -protected: - BundleAdjustment() { - } -public: - virtual ~BundleAdjustment() { - } - - /*! - * @brief 推算相機資訊 - * - * @param [in] seq 給定一系列場景 - * @return 成功與否 - */ - virtual - bool adjustEyes(std::vector > seq) const { - return false; - } - - /*! - * @brief 推算場景中的物體資訊 - * - * 會將fixedPoints2D推算倒fixedPoints3D - * - * @param [in] seq 一系列場景(這裡的場景是有時間先後順序的) - * @brief 成功與否 - */ - virtual - bool adjustFixedPoints(std::vector > seq) const { - return false; - } -}; - -} // meow - -#endif // BundleAdjustment_H__ diff --git a/meowpp/gra/BundleAdjustment_LM.h b/meowpp/gra/BundleAdjustment_LM.h deleted file mode 100644 index f800141..0000000 --- a/meowpp/gra/BundleAdjustment_LM.h +++ /dev/null @@ -1,376 +0,0 @@ -#ifndef BundleAdjustment_LM_H__ -#define BundleAdjustment_LM_H__ - - -#include "BundleAdjustment.h" - -#include "Eye.h" - -#include "../math/methods.h" -#include "../math/Vector.h" -#include "../math/Matrix.h" -#include "../math/utility.h" - -#include "../oo/ObjBase.h" - -#include - -namespace meow { - -/*! - * @brief 利用 Levenberg-Marquardt Method去推估相機旋轉角度與焦距 - * - * @note 此方法目前只能針對相機都固定在同一點的情況下作調整 - */ -template -class BundleAdjustment_LM: public BundleAdjustment { -private: - /* - struct MatchPair { - size_t from_i; - Matrix from_m; - size_t to_i; - Matrix to_m; - }; - - class NoOffsetController { - private: - std::vector* pairs_; - std::vector >* rot_; - std::vector >* pho_; - BallProjection bll_; - bool flag; - public: - NoOffsetController(std::vector* pairs, - std::vector >* rot, - std::vector >* pho, - bool fg): - pairs_(pairs), rot_(rot), pho_(pho), bll_(3.0, 1.0), flag(fg) { - } - Vector init() { - if (flag == false) { - Vector v(4, 0.0); - int i = (*pho_).size() - 1, n = 0; - v.scalar(n++, (*pho_)[i].focal()); - v.scalar(n++, (*rot_)[i].theta(0)); - v.scalar(n++, (*rot_)[i].theta(1)); - v.scalar(n++, (*rot_)[i].theta(2)); - return v; - } - Vector v((*rot_).size() * 4, 0.0); - for (size_t n = 0, i = 0, I = (*rot_).size(); i < I; ++i) { - v.scalar(n++, (*pho_)[i].focal()); - v.scalar(n++, (*rot_)[i].theta(0)); - v.scalar(n++, (*rot_)[i].theta(1)); - v.scalar(n++, (*rot_)[i].theta(2)); - } - return v; - } - Vector residure(Vector const& v) { - for (size_t n = 0, i = 0, I = (*rot_).size(); i < I; ++i) { - if (flag == false && i != I - 1) continue; - (*pho_)[i].focal(v(n++)); - (*rot_)[i].theta(0, v(n++)); - (*rot_)[i].theta(1, v(n++)); - (*rot_)[i].theta(2, v(n++)); - } - for (typename std::vector::iterator - it = (*pairs_).begin(), ed = (*pairs_).end(); it != ed; ++it) { - (*it).from_m.entry(2, 0, -(*pho_)[(*it).from_i].focal()); - (*it). to_m.entry(2, 0, -(*pho_)[(*it). to_i].focal()); - } - // - Vector ret((*pairs_).size() * 2, 0.0); - size_t n = 0; - for (typename std::vector::iterator - it = (*pairs_).begin(), ed = (*pairs_).end(); it != ed; ++it, ++n) { - Matrix tr( - (*it).to_m - - - (*pho_)[(*it).to_i].transformate( - (*rot_)[(*it).to_i].transformate( - (*rot_)[(*it).from_i].transformateInv( - bll_.transformate( - (*it).from_m - ) - ) - ) - ) - ); - ret.scalar(n * 2 , tr(0, 0)); - ret.scalar(n * 2 + 1, tr(1, 0)); - } - //* - //for (size_t i = 0; i < ret.dimension(); i++) { - // printf("(%-9.1f ", ret(i)); - // if (i % 8 == 7) printf("\n"); - //} - //printf("\n"); - printf("re = %20.5f ?? %f\n", ret.length2(), 25.0 * (*pairs_).size()); - // */ - return ret; - } - Matrix jacobian() const { - Matrix ret; - if (flag == false) { - ret.reset((*pairs_).size() * 2, 4, 0.0); - } - else { - ret.reset((*pairs_).size() * 2, (*rot_).size() * 4, 0.0); - } - size_t n = 0; - for (typename std::vector::iterator - it = (*pairs_).begin(), ed = (*pairs_).end(); it != ed; ++it, ++n) { - Matrix tr_A( bll_ .transformate((*it).from_m)); - Matrix tr_B((*rot_)[(*it).from_i].transformateInv(tr_A)); - Matrix tr_C((*rot_)[(*it). to_i].transformate (tr_B)); - Matrix ja_A((*pho_)[(*it). to_i].jacobian (tr_C)); - Matrix ja_B((*rot_)[(*it). to_i].jacobian (tr_B)); - Matrix ja_C((*rot_)[(*it).from_i].jacobianInv(tr_A)); - Matrix m; - int fr = (flag == false ? 0 : (*it).from_i); - int to = (flag == false ? 0 : (*it). to_i); - if (flag != false || (*it).from_i == (*rot_).size() - 1) { - m = ja_A * ja_B * ja_C * bll_.jacobian((*it).from_m).col(2); - ret.entry(n * 2 , fr * 4, m(0, 0)); - ret.entry(n * 2 + 1, fr * 4, m(1, 0)); - for (size_t k = 0; k < 3; ++k) { - m = ja_A * ja_B * (*rot_)[(*it).from_i].jacobianInv(tr_A, k); - ret.entry(n * 2 , fr * 4 + 1 + k, m(0, 0)); - ret.entry(n * 2 + 1, fr * 4 + 1 + k, m(1, 0)); - } - } - if (flag != false || (*it).to_i == (*rot_).size() - 1) { - m = (*pho_)[(*it).to_i].jacobian(tr_C, 0); - ret.entry(n * 2 , to * 4, m(0, 0)); - ret.entry(n * 2 + 1, to * 4, m(1, 0)); - for (size_t k = 0; k < 3; ++k) { - m = ja_A * (*rot_)[(*it).to_i].jacobian(tr_B, k); - ret.entry(n * 2 , to * 4 + 1 + k, m(0, 0)); - ret.entry(n * 2 + 1, to * 4 + 1 + k, m(1, 0)); - } - } - } - return ret; - } - Matrix identity() const { - if (flag == false) { - Matrix ret(4, 4, 0.0); - ret.identitied(); - return ret; - } - Matrix ret((*rot_).size() * 4, (*rot_).size() * 4, 0.0); - ret.identitied(); - return ret; - } - }; - // */ - - struct Myself { - double t_; - - Myself(): t_(5.0) { - } - - Myself(Myself const& m): t_(m.t_) { - } - - ~Myself() { - } - }; - - Self const self; - -public: - BundleAdjustment_LM(): self() { - } - - BundleAdjustment_LM(BundleAdjustment_LM const& b): - self(b.self, Self::COPY_FROM) { - } - - ~BundleAdjustment_LM() { - } - - BundleAdjustment_LM& copyFrom(BundleAdjustment_LM const& b) { - self().copyFrom(b.self); - return *this; - } - - BundleAdjustment_LM& referenceFrom(BundleAdjustment_LM const& b) { - self().referenceFrom(b.self); - return *this; - } - - double threshold() const { - return self->t_; - } - - double threshold(double t) { - self()->t_ = t; - return threshold(); - } - - bool adjustEyes(std::vector > seq) const { - // check - size_t N = seq.size(); - for (size_t i = 0; i < N; ++i) { - if ( seq[i].flag & CAN_OFFSET ) return false; - if (!(seq[i].flag & CAN_ROTATE)) return false; - if (!(seq[i].flag & CAN_ZOOM )) return false; - if (i > 0 && seq[i - 1].eye.offset() != seq[i].eye.offset()) return false; - } - return false; - - /* - std::vector > > points; - // reference - std::vector > rots(N); - std::vector > phos(N, PhotoProjection(3)); - for (size_t i = 0; i < N; ++i) { - rots[i].referenceFrom(seq[i].eye.cameraGet().rotationGet()); - phos[i].referenceFrom(seq[i].eye.cameraGet().photoGet().projectionGet()); - } - - // get all pairs - typedef typename Camera::FixedPoints2D::IdentityPointsMapIterK FPS_K; - std::vector beg(N), end(N); - for (size_t i = 0; i < N; ++i) { - beg[i] = seq[i].eye.cameraGet().fixedPoints2DGet().pointsGet().begin(); - end[i] = seq[i].eye.cameraGet().fixedPoints2DGet().pointsGet().end (); - } - - FPS_K it1, it2; - std::vector > > all_pairs(N); - for (size_t i = 0; i < N; ++i) { - all_pairs[i].resize(N); - for (size_t j = 0; j < N; ++j) { - if (i == j) continue; - for (it1 = beg[i], it2 = beg[j]; it1 != end[i] && it2 != end[j]; ) { - if (it1->first < it2->first) ++it1; - else if(it1->first > it2->first) ++it2; - else { - MatchPair tmp; - tmp.from_i = i; - tmp.from_m = it1->second.matrix(); - tmp.from_m.rows(3, -seq[i].eye.camera().photo().focal()); - tmp. to_i = j; - tmp. to_m = it2->second.matrix(); - tmp. to_m.rows(3, -seq[j].eye.camera().photo().focal()); - all_pairs[i][j].push_back(tmp); - ++it1; - ++it2; - } - } - } - } - // - std::vector pairs; - std::vector > rot; - std::vector > pho; - std::vector sum (N, 0); - std::vector big (N, 0); - std::vector real(N); - std::vector rev (N); - // first!! - int best = -1, best_ct = -1; - for (size_t i = 0; i < N; ++i) { - int d = 0; - for (size_t j = 0; j < N; ++j) { - d += all_pairs[i][j].size(); - } - if (best_ct < d) { - best_ct = d; - best = i; - } - real[i] = i; - big [i] = i; - } - for (size_t i = 0; i < N; ++i) { - // update else - real[i] = best; - rev[best] = i; - for (size_t j = 0; j < N; ++j) { - if ((int)j == best) { - sum[j] = -1; - continue; - } - if (sum[j] < 0) continue; - sum[j] += all_pairs[best][j].size(); - if (all_pairs[j][big[j]].size() < all_pairs[j][best].size()) - big[j] = best; - } - // add me - printf("%d same as %d\n", best, big[best]); - if (big[best] == best) { - rot.push_back((*seq)[big[best]].eye->camera() .rotation()); - pho.push_back((*seq)[big[best]].eye->camera().photo().projection()); - } - else { - rot.push_back(rot[rev[big[best]]]); - pho.push_back(pho[rev[big[best]]]); - } - for (size_t j = 0; j < N; ++j) { - if (sum[j] >= 0) continue; - for (size_t k = 0, K = all_pairs[best][j].size(); k < K; ++k) { - all_pairs[best][j][k].from_i = rev[all_pairs[best][j][k].from_i]; - all_pairs[best][j][k]. to_i = rev[all_pairs[best][j][k]. to_i]; - pairs.push_back(all_pairs[best][j][k]); - } - for (size_t k = 0, K = all_pairs[j][best].size(); k < K; ++k) { - all_pairs[j][best][k].from_i = rev[all_pairs[j][best][k].from_i]; - all_pairs[j][best][k]. to_i = rev[all_pairs[j][best][k]. to_i]; - pairs.push_back(all_pairs[j][best][k]); - } - } - if (i > 0) { - NoOffsetController ct1(&pairs, &rot, &pho, false); - ct1.residure(levenbergMarquardtTraining(ct1, ct1.init(), - 7.3, 1.0, - squ(threshold()) * pairs.size(), - 7, 1000)); - } - best_ct = 0; - for (size_t j = 0; j < N; ++j) { - if (best_ct < sum[j]) { - best = j; - best_ct = sum[j]; - } - } - } - return true; - // */ - } - - bool adjustFixedPoints(std::vector > seq) const { - return false; - } - - bool write(FILE* f, bool bin, unsigned int fg) const { - return false; - } - - bool read(FILE* f, bool bin, unsigned int fg) const { - return false; - } - - ObjBase* create() const { - return new BundleAdjustment_LM; - } - - ObjBase* copyFrom(ObjBase const* o) { - return &(copyFrom(*(BundleAdjustment_LM const*)o)); - } - - char const* ctype() const { - return typeid(*this).name(); - } - - std::string type() const { - return std::string(ctype()); - } -}; - -} // meow - -#endif // BundleAdjustment_LM_H__ diff --git a/meowpp/gra/Camera.h b/meowpp/gra/Camera.h deleted file mode 100644 index 0cb2582..0000000 --- a/meowpp/gra/Camera.h +++ /dev/null @@ -1,261 +0,0 @@ -#ifndef gra_Camera_H__ -#define gra_Camera_H__ - -#include "Photo.h" -#include "IdentityPoints.h" -#include "../Self.h" -#include "../math/utility.h" -#include "../math/LinearTransformations.h" -#include "../math/methods.h" -#include "../oo/ObjBase.h" - -namespace meow { - -/*! - * @brief Camera - * - * 實際上就是一個 \c Photo 加上一個 \c Rotation3D. - * 另外附有 fixedPoint, 可以用來定位時參考 - * - * @author cat_leopard - */ -template -class Camera: public ObjBase { -public: - typedef IdentityPoints > FixedPoints2D; -private: - struct Myself { - Photo photo_; - Rotation3D rot_; - FixedPoints2D fixed2D_; - - Myself(): fixed2D_(2) { - } - - Myself(Myself const& v): - photo_(v.photo_), rot_(v.rot_), fixed2D_(v.fixed2D_) { - } - - ~Myself() { - } - }; - - Self const self; -public: - /*! - * @brief constructor - */ - Camera(): self() { - } - - /*! - * @brief copy constructor - */ - Camera(Camera const& b): self(b.self, Self::COPY_FROM) { - } - - /*! - * @brief destructor - */ - ~Camera() { - } - - /*! - * @brief 複製資料 - */ - Camera& copyFrom(Camera const& b) { - self().copyFrom(b.self); - return *this; - } - - /*! - * @brief 參照 - */ - Camera& referenceFrom(Camera const& b) { - self().referenceFrom(b.self); - return *this; - } - - /*! - * @brief 取得 photo - */ - Photo photo() const { - return self->photo_; - } - - /*! - * @brief 取得 photo (non-constant) - */ - Photo& photoGet() { - return self()->photo_; - } - - /*! - * @brief 設定 photo - */ - Photo photo(Photo const& pho) { - self()->photo_.copyFrom(pho); - return photo(); - } - - /*! - * @brief 取得rotation - */ - Rotation3D rotation() const { - return self->rot_; - } - - /*! - * @brief 取得rotation (non-constant) - */ - Rotation3D& rotationGet() { - return self()->rot_; - } - - /*! - * @brief 設定rotation - */ - Rotation3D rotation(Rotation3D const& rot) { - self()->rot_.copyFrom(rot); - return rotation(); - } - - /*! - * @brief 取得所有FixedPoint - */ - FixedPoints2D fixedPoints2D() const { - return self->fixed2D_; - } - - /*! - * @brief 取得所有FixedPoint(non-constant reference) - */ - FixedPoints2D& fixedPoints2DGet() const { - return self()->fixed2D_; - } - - /*! - * @brief 設定FixedPoint - */ - FixedPoints2D fixedPoints2D(FixedPoints2D const& fps2d) const { - if (fps2d.dimension() == 2) { - self()->fixed2D_.copyFrom(fps2d); - } - return fixedPoints2D(); - } - - /*! - * @brief 取得編號為i的fixed points 2d - */ - Vector fixedPoint2D(int i) { - return self->fixed2D_.identityPoint(i); - } - - /*! - * @brief 詢問某點是否在底片範圍內 - */ - bool inside(Vector3D const& p) const { - return self->photo_.inside( - Vector3D(rotation().transformate(p.matrix()))); - } - - /*! - * @brief 取得底片color - */ - Pixel color(Vector3D const& p) const { - return self->photo_.color( - Vector3D(rotation().transformate(p.matrix()))); - } - - /*! - * @brief same as \c copyFrom(b) - */ - Camera& operator=(Camera const& b) { - return copyFrom(b); - } - - /*! @brief 將資料寫入檔案 - * - * @note 未完成 - */ - bool write(FILE* f, bool bin, unsigned int fg) const { - if (bin) { - double tmp; - for (size_t i = 0; i < 3; ++i) { - if (fwrite(&(tmp = rotation().theta(i)), sizeof(tmp), 1, f) < 1) - return false; - } - } - else { - for (size_t i = 0; i < 3; ++i) { - if (fprintf(f, "%f ", rotation().theta(i)) < 1) return false; - } - fprintf(f, "\n"); - } - return (fixedPoints2D().write(f, bin, fg) && photo().write(f, bin, fg)); - } - - /*! @brief 將資料讀入 - * - * @note 未完成 - */ - bool read(FILE* f, bool bin, unsigned int fg) { - if (bin) { - double tmp; - for (size_t i = 0; i < 3; ++i) { - if (fread(&tmp, sizeof(tmp), 1, f) < 1) { - return false; - } - rotationGet().theta(i, tmp); - } - } - else { - double a; - for (size_t i = 0; i < 3; ++i) { - if (fscanf(f, "%lf", &a) < 1) return false; - rotationGet().theta(i, a); - } - } - return (fixedPoints2DGet().read(f, bin, fg) && photoGet().read(f, bin, fg)); - } - - /*! @brief new一個自己 - * - * @return 一個new出來的pointer - */ - ObjBase* create() const { - return new Camera(); - } - - /*! @brief 複製資料 - * - * 輸入型別是 \c ObjBase \c const* - * 事實上這個method就只是幫忙轉型然後呼叫原本的\c copyFrom - * - * @param [in] b 資料來源 - * @return this - */ - ObjBase* copyFrom(ObjBase const* b) { - return &(copyFrom(*(Camera const*)b)); - } - - /*! @brief 回傳class的type - * - * @return \c char \c const\c * 形式的typename - */ - char const* ctype() const{ - return typeid(*this).name(); - } - - /*! @brief 回傳class的type - * - * @return \c std::string 形式的typename - */ - std::string type() const { - return std::string(ctype()); - } -}; - -} // meow - -#endif // gra_Camera_H__ diff --git a/meowpp/gra/Eye.h b/meowpp/gra/Eye.h deleted file mode 100644 index cff5ccd..0000000 --- a/meowpp/gra/Eye.h +++ /dev/null @@ -1,174 +0,0 @@ -#ifndef Eye_H__ -#define Eye_H__ - -#include "Camera.h" - -#include "../Self.h" -#include "../oo/ObjBase.h" - -namespace meow { - -/*! - * @brief 一個 \c Camera 加上一個offset transformation - * - * @author cat_leopard - */ -template -class Eye: public ObjBase { -private: - struct Myself { - Camera cam_; - Vector3D ofs_; - - Myself(): cam_(), ofs_(0.0, 0.0, 0.0) { - } - - Myself(Camera const& c, Vector3D const& o): cam_(c), ofs_(o){ - } - - Myself(Myself const& b): cam_(b.cam_), ofs_(b.ofs_) { - } - - ~Myself() { - } - }; - - Self const self; -public: - Eye(): self() { - } - - Eye(Eye const& b): self(b.self(), Self::COPY_FROM) { - } - - Eye(Camera const& c, Vector3D const& o): self(Myself(c, o)) { - } - - ~Eye() { - } - - Eye& copyFrom(Eye const& e) { - self().copyFrom(e.self); - return *this; - } - - Eye& referenceFrom(Eye const& e) { - self().referenceFrom(e.self); - return *this; - } - - Camera camera() const { - return self->cam_; - } - - Camera& cameraGet() { - return self()->cam_; - } - - Camera camera(Camera const& c) { - self()->cam_.copyFrom(c); - return camera(); - } - - Vector3D offset() const { - return self->ofs_; - } - - Vector3D& offsetGet() { - return self()->ofs_; - } - - Vector3D offset(Vector3D const& ofs) { - self()->ofs_ = ofs; - return offset(); - } - - bool inside(Vector3D const& v) const { - return camera().inside(v - offset()); - } - - Eye& operator=(Eye const& e) { - return copyFrom(e); - } - - /*! @brief 將資料寫入檔案 - * - * @note 未完成 - */ - bool write(FILE* f, bool bin, unsigned int fg) const { - if (bin) { - double tmp; - for (size_t i = 0; i < 3; ++i) { - if (fwrite(&(tmp = offset()(i)), sizeof(tmp), 1, f) < 1) - return false; - } - } - else { - for (size_t i = 0; i < 3; ++i) { - if (fprintf(f, "%f ", offset()(i)) < 1) return false; - } - fprintf(f, "\n"); - } - return camera().write(f, bin, fg); - } - - /*! @brief 將資料讀入 - * - * @note 未完成 - */ - bool read(FILE* f, bool bin, unsigned int fg) { - if (bin) { - double tmp[3]; - if (fread(tmp, sizeof(double), 3, f) < 3) return false; - offsetGet().xyz(tmp[0], tmp[1], tmp[2]); - } - else { - double a, b, c; - if (fscanf(f, "%lf %lf %lf", &a, &b, &c) < 3) return false; - offsetGet().x(a); - offsetGet().y(b); - offsetGet().z(c); - } - return cameraGet().read(f, bin, fg); - } - - /*! @brief new一個自己 - * - * @return 一個new出來的pointer - */ - ObjBase* create() const { - return new Eye(); - } - - /*! @brief 複製資料 - * - * 輸入型別是 \c ObjBase \c const* - * 事實上這個method就只是幫忙轉型然後呼叫原本的\c copyFrom - * - * @param [in] b 資料來源 - * @return this - */ - ObjBase* copyFrom(ObjBase const* b) { - return &(copyFrom(*(Eye const*)b)); - } - - /*! @brief 回傳class的type - * - * @return \c char \c const\c * 形式的typename - */ - char const* ctype() const{ - return typeid(*this).name(); - } - - /*! @brief 回傳class的type - * - * @return \c std::string 形式的typename - */ - std::string type() const { - return std::string(ctype()); - } -}; - -} // meow - -#endif // Eye_H__ diff --git a/meowpp/gra/FeaturePoint.h b/meowpp/gra/FeaturePoint.h deleted file mode 100644 index 68ac65e..0000000 --- a/meowpp/gra/FeaturePoint.h +++ /dev/null @@ -1,262 +0,0 @@ -#ifndef gra_FeaturePoint_H__ -#define gra_FeaturePoint_H__ - -#include "../oo/ObjBase.h" - -#include "../math/Vector.h" - -#include -#include -#include -#include - -namespace meow { - -/*! - * @brief 特徵點 - * - * @author cat_leopard - */ -template , - class Feature = Vector > - -class FeaturePoint: public ObjBase { -private: - Position pos_; - Feature des_; -public: - /*! - * @brief constructor - */ - FeaturePoint() { - } - - /*! - * @brief constructor - */ - FeaturePoint(size_t pDim, size_t dDim): - pos_(pDim, Scalar(0)), des_(dDim, Description(0)) { - } - - /*! - * @brief constructor - */ - FeaturePoint(Position const& v, Feature const& d): - pos_(v), des_(d) { - } - - /*! - * @brief constructor - */ - FeaturePoint(FeaturePoint const& fp): - pos_(fp.pos_), des_(fp.des_) { - } - - /*! - * @brief destructor - */ - ~FeaturePoint() { - } - - /*! - * @brief 複製 - */ - FeaturePoint& copyFrom(FeaturePoint const& fp) { - pos_.copyFrom(fp.pos_); - des_.copyFrom(fp.des_); - return *this; - } - - /*! - * @brief 參照 - */ - FeaturePoint& referenceFrom(FeaturePoint const& fp) { - pos_.referenceFrom(fp.pos_); - des_.referenceFrom(fp.des_); - return *this; - } - - /*! - * @brief 回傳position - */ - Position position() const { - return pos_; - } - - /*! - * @brief 回傳position (non-const reference) - */ - Position& positionGet() { - return pos_; - } - - /*! - * @brief 回傳description - */ - Feature description() const { - return des_; - } - - /*! - * @brief 回傳description (non-const reference) - */ - Feature& descriptionGet() { - return des_; - } - - /*! - * @brief 修改position - */ - Position position(Position const& p) { - pos_.copyFrom(p); - return position(); - } - - /*! - * @brief 修改description - */ - Feature description(Feature const& d) { - des_.copyFrom(d); - return description(); - } - - /*! - * @brief 回傳position的第i個scalar - */ - Scalar position(size_t index) const { - return position()(index); - } - - /*! - * @brief 回傳description的第i個Description - */ - Description description(size_t index) const { - return des_(index); - } - - /*! - * @brief 修改position的第i個scalar - */ - Scalar position(size_t i, Scalar const& s) { - pos_.scalar(i, s); - return position()(i); - } - - /*! - * @brief 修改description的第i個Description - */ - Description description(size_t i, Description const& d) { - des_.scalar(i, d); - return description()(i); - } - - /*! - * @brief same as copyFrom(fp) - */ - FeaturePoint& operator=(FeaturePoint const& fp) { - return copyFrom(fp); - } - - /*! - * @brief same as position(i) - */ - Scalar const& operator()(size_t i) const { - return position(i); - } - - /*! - * @brief same as description(i) - */ - Description operator[](size_t i) const { - return description(i); - } - - bool write(FILE* f, bool bin, unsigned int fg) const { - if (bin) { - double tmp; - int a, b; - a = position().dimension(); - b = description().dimension(); - if (fwrite(&a, sizeof(a), 1, f) < 1) return false; - if (fwrite(&b, sizeof(b), 1, f) < 1) return false; - for (size_t i = 0, I = position().dimension(); i < I; ++i) { - if (fwrite(&(tmp = position(i)), sizeof(tmp), 1, f) < 1) return false; - } - for (size_t i = 0, I = description().dimension(); i < I; ++i) { - if (fwrite(&(tmp = description(i)), sizeof(tmp), 1, f) < 1) - return false; - } - } - else { - int a, b; - a = position().dimension(); - b = description().dimension(); - if (fprintf(f, "%d %d\n", a, b) < 2) return false; - for (size_t i = 0, I = position().dimension(); i < I; ++i) { - if (fprintf(f, "%f ", (double)position(i)) < 1) return false; - } - fprintf(f, "\n"); - for (size_t i = 0, I = description().dimension(); i < I; ++i) { - if (fprintf(f, "%f ", (double)description(i)) < 1) return false; - } - fprintf(f, "\n"); - } - return true; - } - - bool read(FILE* f, bool bin, unsigned int fg) { - if (bin) { - double tmp; - int a, b; - if (fread(&a, sizeof(a), 1, f) < 1) return false; - if (fread(&b, sizeof(b), 1, f) < 1) return false; - position(Position((size_t)a, Scalar(0))); - description(Feature((size_t)b, Description(0))); - for (size_t i = 0, I = position().dimension(); i < I; ++i) { - if (fread(&tmp, sizeof(tmp), 1, f) < 1) return false; - position(i, tmp); - } - for (size_t i = 0, I = description().dimension(); i < I; ++i) { - if (fread(&tmp, sizeof(tmp), 1, f) < 1) return false; - description(i, tmp); - } - } - else { - double tmp; - int a, b; - if (fscanf(f, "%d %d", &a, &b) < 2) return false; - position(Position((size_t)a, Scalar(0))); - description(Feature((size_t)b, Description(0))); - for (size_t i = 0, I = position().dimension(); i < I; ++i) { - if (fscanf(f, "%lf", &tmp) < 1) return false; - position(i, tmp); - } - for (size_t i = 0, I = description().dimension(); i < I; ++i) { - if (fscanf(f, "%lf", &tmp) < 1) return false; - description(i, tmp); - } - } - return true; - } - - ObjBase* create() const { - return new FeaturePoint(); - } - - ObjBase* copyFrom(ObjBase const& b) { - return &(copyFrom(*(FeaturePoint const*)b)); - } - - char const* ctype() const { - return typeid(*this).name(); - } - - std::string type() const { - return std::string(ctype()); - } -}; - -} // meow - -#endif // gra_FeaturePoint_H__ diff --git a/meowpp/gra/FeaturePointsDetector.h b/meowpp/gra/FeaturePointsDetector.h deleted file mode 100644 index fad051e..0000000 --- a/meowpp/gra/FeaturePointsDetector.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef gra_FeaturePointsDetector_H__ -#define gra_FeaturePointsDetector_H__ - -#include "../oo/ObjBase.h" - -#include "FeaturePoint.h" -#include "Bitmap.h" - -#include - -namespace meow { - -template > -class FeaturePointsDetector: public ObjBase { -protected: - FeaturePointsDetector() { } -public: - virtual ~FeaturePointsDetector() { } - - virtual std::vector detect(Bitmap const& bmp) const = 0; -}; - -} // meow - -#endif // gra_FeaturePointsDetector_H__ diff --git a/meowpp/gra/FeaturePointsDetector_Harris.h b/meowpp/gra/FeaturePointsDetector_Harris.h deleted file mode 100644 index d5fbb45..0000000 --- a/meowpp/gra/FeaturePointsDetector_Harris.h +++ /dev/null @@ -1,365 +0,0 @@ -#ifndef gra_FeaturePointsDetector_Harris -#define gra_FeaturePointsDetector_Harris - -#include "FeaturePointsDetector.h" - -#include "Bitmap.h" -#include "FeaturePoint.h" -#include "FeaturePointsDetector.h" - -#include "../dsa/DisjointSet.h" -#include "../math/utility.h" - -#include "../Self.h" - -#include -#include - -namespace meow { - -/*! - * @brief Harris-Corner-Detect algorithm for finding feature points. - * - * @author cat_leopard - */ -template > -class FeaturePointsDetector_Harris: public FeaturePointsDetector { -# define FPD_Harris FeaturePointsDetector_Harris -private: - struct Myself { - double ratioK_; - double thresholdR_; - double sizeW_; - double noiseN_; - double lightL_; - double featureG_; - size_t boundB_; - size_t angleA_; - - Myself(): - ratioK_(0.03), - thresholdR_(0.001), - sizeW_(2.0), - noiseN_(3.0), - lightL_(30.0), - featureG_(3.0), - boundB_(10u), - angleA_(8) { - } - Myself(Myself const& m): - ratioK_(m.ratioK_), - thresholdR_(m.thresholdR_), - sizeW_(m.sizeW_), - noiseN_(m.noiseN_), - lightL_(m.lightL_), - featureG_(m.featureG_), - boundB_(m.boundB_){ - } - ~Myself() { - } - }; - - Self const self; -public: - //! @brief constructor 使用預設參數 - FPD_Harris(): self() { - } - - //! @brief constructor 參數複製自另一個 FeaturePointsDetector_Harris - FPD_Harris(FPD_Harris const& fps): self(fps.self, Self::COPY_FROM) { - } - - //! @brief 解構子 - ~FPD_Harris() { - } - - //! @brief 複製 - FPD_Harris& copyFrom(FPD_Harris const& fps) { - self().copyFrom(fps.self); - return *this; - } - - //! @brief 參照 - FPD_Harris& referenceFrom(FPD_Harris const& fps) { - self().referenceFrom(fps.self); - return *this; - } - - //! @brief K - double paramK() const { - return self->ratioK_; - } - - //! @brief R - double paramR() const { - return self->thresholdR_; - } - - //! @brief W - double paramW() const { - return self->sizeW_; - } - - //! @brief N - double paramN() const { - return self->noiseN_; - } - - //! @brief G - double paramG() const { - return self->featureG_; - } - - //! @brief L - double paramL() const { - return self->lightL_; - } - - //! @brief bound - size_t paramB() const { - return self->boundB_; - } - - //! @brief algle - size_t paramA() const { - return self->angleA_; - } - - //! @brief K - double paramK(double k) { - self()->ratioK_ = k; - return paramK(); - } - - //! @brief R - double paramR(double r) { - self()->thresholdR_ = r; - return paramR(); - } - - //! @brief W - double paramW(double w) { - self()->sizeW_ = w; - return paramW(); - } - - //! @brief N - double paramN(double n){ - self()->noiseN_ = n; - return paramN(); - } - - //! @brief L - double paramL(double l) { - self()->lightL_ = l; - return paramL(); - } - - //! @brief G - double paramG(double g) { - self()->featureG_ = g; - return paramG(); - } - - //! @brief B - size_t paramB(size_t b) { - self()->boundB_ = b; - return paramB(); - } - - //! @brief A - size_t paramA(size_t a) { - self()->angleA_ = a; - return paramA(); - } - - size_t descriptionDimension() const { - return (paramA() + 1) * squ(paramB() * 2 + 1); - //return (squ(self->boundB_ * 2 + 1) - 1) * 2; - } - - /*! @brief 找出特徵點 - * - * @param [in] bmp 要抓特徵點的點陣圖 - * @return \c std::vector> 型態的一堆特徵點 - */ - std::vector detect(Bitmap const& bmp) const { - // blur for feature, gradiance - Bitmap input (bmp.gaussian (self->featureG_, self->featureG_)); - Bitmap input_gx(bmp.gradianceX(0 , self->noiseN_ )); - Bitmap input_gy(bmp.gradianceY(self->noiseN_ , 0 )); - - // get Matrix Ixx, Iyy, Ixy for each pixel - Bitmap > Ixys(input.height(), input.width(), - Vector3D(0.0)); - for (ssize_t y = 0, Y = input.height(); y < Y; y++) - for (ssize_t x = 0, X = input.width(); x < X; x++) { - Pixel gx(input_gx(y, x)); - Pixel gy(input_gy(y, x)); - Ixys.pixel(y, x, Vector3D(gx * gx, gy * gy, gx * gy)); - } - - // blur for window size - Ixys.gaussianed(self->sizeW_, self->sizeW_); - //input_gx.clear(); - //input_gy.clear(); - - // filter too flat or on edge - Bitmap R(input.height(), input.width(), 0.0); - Bitmap good(input.height(), input.width(), false); - for (ssize_t y = 0, Y = input.height(); y < Y; y++) - for (ssize_t x = 0, X = input.width(); x < X; x++) { - double det = Ixys(y, x)(0) * Ixys(y, x)(1) - squ(Ixys(y, x)(2)); - double tra = Ixys(y, x)(0) + Ixys(y, x)(1); - double r = det - self->ratioK_ * squ(tra); - R.pixel(y, x, r); - good.pixel(y, x, (r >= self->thresholdR_)); - } - Ixys.clear(); - - // find union neighbor - DisjointSet dsj(input.size()); - ssize_t dy[2] = {0, 1}; - ssize_t dx[2] = {1, 0}; - for (ssize_t y = 0, Y = input.height(); y + 1 < Y; y++) - for (ssize_t x = 0, X = input.width(); x + 1 < X; x++) - if(good.pixel((size_t)y, (size_t)x)) - for (size_t k = 0; k < 2u; k++) - if (good.pixel((size_t)(y + dy[k]), (size_t)(x + dx[k]))) - dsj.merge( y * input.width() + x, - (y + dy[k]) * input.width() + (x + dx[k])); - - // find local maximum - std::vector max_i(input.size()); - for (size_t i = 0, I = input.size(); i < I; i++) - max_i[i] = i; - - for (size_t i = 0, I = input.size(); i < I; i++) { - size_t ri = dsj.root(i); - if (R.pixel( i / input.width(), i % input.width()) > - R.pixel(max_i[ri] / input.width(), max_i[ri] % input.width())) - max_i[ri] = i; - } - - // Ignore side - ssize_t b = std::max(std::max(self->boundB_, - 2 * self->sizeW_), - 2 * self->noiseN_); - std::vector ret; - Vector desc(descriptionDimension(), 0.0); // description - for (ssize_t y = b, Y = -b + input.height(); y < Y; y++) - for (ssize_t x = b, X = -b + input.width(); x < X; x++) { - if (!good.pixel((size_t)y, (size_t)x)) continue; - size_t i = y * input.width() + x; - if (max_i[dsj.root(i)] != i) continue; - int B = paramB(); - size_t ct = 0; - for (ssize_t dx = -B; dx <= B; ++dx) - for (ssize_t dy = -B; dy <= B; ++dy) { - double gx = input_gx.pixel(y+dy, x+dx) * input_gx.pixel(y+dy, x+dx); - double gy = input_gy.pixel(y+dy, x+dx) * input_gy.pixel(y+dy, x+dx); - double light = sqrt(gx + gy); - double angle = circle(atan2(sqrt(gy), sqrt(gx))); - int a = angle / (2 * PI / paramA()); - for (size_t k = 0; k < paramA(); ++k) { - desc.scalar(ct++, (a + k) % paramA()); - } - desc.scalar(ct++, light * paramL()); - } - /* - ssize_t dx[4] = {1, 0, -1, 0}; - ssize_t dy[4] = {0, 1, 0, -1}; - size_t ct = 0; - for (ssize_t d = 1; d <= (ssize_t)self->boundB_; ++d) { - std::vector light; - size_t max_id = 0, x0 = x - d, y0 = y - d; - for (size_t k = 0; k < 4; k++) - for (ssize_t n = 0; n < (ssize_t)d * 2; n++, - x0 += dx[k], y0 += dy[k]) { - Pixel diff = input.pixel(y0, x0) - input.pixel(y, x) * 0.2; - light.push_back(diff * diff * self->lightL_); - if (light[max_id] < light[(ssize_t)light.size() - 1]) - max_id = (ssize_t)light.size() - 1; - } - double W = squ(light.size()) * 0.5; - for (ssize_t n = 0, N = light.size(); n < N; n++) { - desc.scalar(ct++, (max_id + n) % N * 1.0 / W); - desc.scalar(ct++, light[(max_id + n) % N] / N); - } - } - // */ - ret.push_back(MyFP(Vector2D(1.0 * x, 1.0 * y).matrix(), desc)); - } - return ret; - } - - //! @brief same as \c copyFrom(fps) - FPD_Harris& operator=(FPD_Harris const& fps) { - return copyFrom(fps); - } - - //! @brief same as \c detect(bmp) - std::vector operator()(Bitmap const& bmp) const { - return detect(bmp); - } - - /*! @brief 寫到檔案裡 - * - * 未完成 - */ - bool write(FILE* f, bool bin, unsigned int fg) const { - // TODO - return false; - } - - /*! @brief 將資料讀入 - * - * 未完成 - */ - bool read (FILE* f, bool bin, unsigned int fg) { - // TODO - return false; - } - - /*! @brief new一個自己 - * - * @return 一個new出來的FeaturePointsDetector_Harris - */ - ObjBase* create() const { - return (ObjBase*)new FPD_Harris(); - } - - /*! @brief 複製資料 - * - * 輸入型別是 \c ObjBase \c const* - * 這裡假設實體其實是 \c FeaturePointsDetector_Harris. - * 事實上這個method就只是幫忙轉型然後呼叫原本的\c copyFrom - * - * @param [in] b 資料來源 - * @return this - */ - ObjBase* copyFrom(ObjBase const* b) { - return &(copyFrom(*(FPD_Harris const*)b)); - } - - /*! @brief 回傳class的type - * - * @return \c char \c const\c * 形式的typename - */ - char const* ctype() const { - return typeid(*this).name(); - } - - /*! @brief 回傳class的type - * - * @return \c std::string 形式的typename - */ - std::string type() const { - return std::string(ctype()); - } -# undef FPD_Harris -}; - -} // meow - -#endif // gra_FeaturePointsDetector_Harris diff --git a/meowpp/gra/FeaturePointsMatch.h b/meowpp/gra/FeaturePointsMatch.h deleted file mode 100644 index 85bc2dd..0000000 --- a/meowpp/gra/FeaturePointsMatch.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef gra_FeaturePointsMatch_H__ -#define gra_FeaturePointsMatch_H__ - -#include "FeaturePoint.h" - -#include "../utility.h" -#include "../oo/ObjBase.h" - -#include - -namespace meow { - -typedef PairToPair FeaturePointIndexPair ; -typedef std::vector FeaturePointIndexPairs; - -template > -class FeaturePointsMatch: public ObjBase { -protected: - FeaturePointsMatch() { - } -public: - typedef std::vector FeaturePoints; - typedef std::vector FeaturePointss; - - virtual ~FeaturePointsMatch() { - } - - virtual FeaturePointIndexPairs match(size_t dimension, - FeaturePoints const& from, - FeaturePoints const& to) const = 0; - - virtual FeaturePointIndexPairs match(size_t dimension, - FeaturePoints const& from, - FeaturePointss const& to) const = 0; - - virtual FeaturePointIndexPairs match(size_t dimension, - FeaturePointss const& from, - FeaturePointss const& to) const = 0; - - virtual FeaturePointIndexPairs match(size_t dimension, - FeaturePointss const& fpss) const = 0; -}; - -} // meow - -#endif // gra_FeaturePointsMatch_H__ diff --git a/meowpp/gra/FeaturePointsMatch_K_Match.h b/meowpp/gra/FeaturePointsMatch_K_Match.h deleted file mode 100644 index 9bb5a65..0000000 --- a/meowpp/gra/FeaturePointsMatch_K_Match.h +++ /dev/null @@ -1,180 +0,0 @@ -#ifndef gra_FeaturePointsMatch_K_Match_H__ -#define gra_FeaturePointsMatch_K_Match_H__ - -#include "FeaturePointsMatch.h" - -#include "../Self.h" -#include "../dsa/VP_Tree.h" -#include "../oo/ObjBase.h" - -#include - -namespace meow { - -template > -class FeaturePointsMatch_K_Match: public FeaturePointsMatch { -# define FPMKM FeaturePointsMatch_K_Match -public: - typedef std::vector FeaturePoints ; - typedef std::vector FeaturePointss; -private: - struct Node { - size_t id_; - size_t index_; - FeaturePointss const* ptr_; - - Node() { - } - Node(Node const& nd) { - id_ = nd. id_; - index_ = nd.index_; - ptr_ = nd. ptr_; - } - Node(size_t id, size_t index, FeaturePointss const* ptr) { - id_ = id; - index_ = index; - ptr_ = ptr; - } - ~Node() { - } - bool operator<(Node const& nd) const { - return (id_ < nd.id_); - } - Description operator[](size_t id) const { - return (*ptr_)[id_][index_][id]; - } - }; - - struct Myself { - size_t k_; - Myself(): k_(1) { - } - Myself(size_t k): k_(k) { - } - Myself(Myself const& m): k_(m.k_) { - } - ~Myself() { - } - }; - - Self const self; -public: - FPMKM(): self() { - } - - FPMKM(FPMKM const& m): self(m.self, Self::COPY_FROM) { - self().copyFrom(m.self); - } - - FPMKM(size_t k): self(Myself(k)) { - } - - ~FPMKM() { - } - - FPMKM& copyFrom(FPMKM const& m) { - self().copyFrom(m.self); - return *this; - } - - FPMKM& referenceFrom(FPMKM const& m) { - self().referenceFrom(m.self); - return *this; - } - - size_t paramK() const { - return self->k_; - } - - size_t paramK(size_t k) { - self()->k_ = std::max(k, (size_t)1); - return paramK(); - } - - - FeaturePointIndexPairs match(size_t dimension, - FeaturePoints const& from, - FeaturePoints const& to) const { - return match(dimension, FeaturePointss(1, from), FeaturePointss(1, to)); - } - - - FeaturePointIndexPairs match(size_t dimension, - FeaturePoints const& from, - FeaturePointss const& to) const { - return match(dimension, FeaturePointss(1, from), to); - } - - FeaturePointIndexPairs match(size_t dimension, - FeaturePointss const& from, - FeaturePointss const& to) const { - VP_Tree tree(dimension); - for (size_t i = 0, I = to.size(); i < I; i++) - for (size_t j = 0, J = to[i].size(); j < J; j++) - tree.insert(Node(i, j, &to)); - FeaturePointIndexPairs ret; - for (size_t i = 0, I = from.size(); i < I; i++) - for (size_t j = 0, J = from[i].size(); j < J; j++) { - Node now(i, j, &from); - std::vector tree_ret = tree.query(now, self->k_, true); - for (size_t k = 0, K = tree_ret.size(); k < K; k++) - ret.push_back(FeaturePointIndexPair(i, j, - tree_ret[k].id_, - tree_ret[k].index_)); - } - return ret; - } - - FeaturePointIndexPairs match(size_t dimension, - FeaturePointss const& fpss) const { - FeaturePointIndexPairs ret, add; - FeaturePointss to(fpss); - for (size_t i = 0, I = fpss.size(); i < I; i++) { - to[i].clear(); - add = match(dimension, fpss[i], to); - for (size_t j = 0, J = add.size(); j < J; j++) { - ret.push_back(FeaturePointIndexPair(i , add[j].from.second, - add[j].to.first, add[j].to.second)); - } - to[i] = fpss[i]; - } - return ret; - } - - FPMKM& operator=(FPMKM const& b) { - return copyFrom(b); - } - - - bool write(FILE* f, bool bin, unsigned int fg) const { - // TODO - return false; - } - - bool read (FILE* f, bool bin, unsigned int fg) { - // TODO - return false; - } - - ObjBase* create() const { - return new FPMKM(); - } - - ObjBase* copyFrom(ObjBase const* ptr) { - return &(copyFrom(*(FPMKM*)ptr)); - } - - char const* ctype() const { - return typeid(*this).name(); - } - - std::string type() const { - return std::string(ctype()); - } -# undef FPMKM -}; - -} // meow - -#endif // gra_FeaturePointsMatch_K_Match_H__ diff --git a/meowpp/gra/IdentityPoints.h b/meowpp/gra/IdentityPoints.h deleted file mode 100644 index 029180f..0000000 --- a/meowpp/gra/IdentityPoints.h +++ /dev/null @@ -1,392 +0,0 @@ -#ifndef gra_IdentityPoints_H__ -#define gra_IdentityPoints_H__ - -#include "../Self.h" -#include "../math/Vector.h" -#include "../oo/ObjBase.h" - -#include -#include -#include - -#include - -namespace meow { - -/*! - * @brief 把一個 \c std::map 包起來 - * - * @author cat_leopard - */ -template > -class IdentityPoints: public ObjBase { -public: - - typedef typename std::vector Identities; - typedef typename std::vector Points; - - typedef typename std::pair IdentityPointPair; - typedef typename std::vector IdentityPointPairs; - - typedef typename std::pair PointPair; - typedef typename std::vector PointPairs; - -private: - typedef typename std::map IdentityPointsMap ; - typedef typename IdentityPointsMap:: iterator IdentityPointsMapIter ; - typedef typename IdentityPointsMap::const_iterator IdentityPointsMapIterK; - - struct Myself { - IdentityPointsMap points_; - size_t dimension_; - - Myself(size_t d): dimension_(d) { - } - - Myself(Myself const& m): points_(m.points_), dimension_(m.dimension_) { - } - - ~Myself() { - } - }; - - Self const self; -public: - /*! - * @brief setup dimension - */ - IdentityPoints(size_t d): self(Myself(d)) { - } - - /*! - * @brief constructor, 並且複製資料 - */ - IdentityPoints(IdentityPoints const& b): - self(b.self, Self::COPY_FROM) { - } - - /*! - * @brief destructor - */ - ~IdentityPoints() { - } - - /*! - * @brief 複製資料 - */ - IdentityPoints& copyFrom(IdentityPoints const& b) { - self().copyFrom(b.self); - return *this; - } - - /*! - * @brief 參照 - */ - IdentityPoints& referenceFrom(IdentityPoints const& b) { - self().referenceFrom(b.self); - return *this; - } - - /*! - * @brief 清除一切identity points - */ - void clear() { - self()->points_.clear(); - } - - /*! - * @brief 回傳有幾個identity points - */ - size_t size() const { - return self->points_.size(); - } - - /*! - * @brief 回傳是否沒有identity points - */ - bool empty() const { - return (size() == 0u); - } - - /*! - * @brief 檢查某id是否有使用 - */ - bool exist(Identity const& id) const { - return (self->points_.find(id) != self->points_.end()); - } - - /*! - * @brief 回傳dimension - */ - size_t dimension() const { - return self->dimension_; - } - - /*! - * @brief 回傳所有 identity - */ - Identities identities() const { - Identities ret; - for (IdentityPointsMapIterK - it = self->points_.begin(), ed = self->points_.end(); it != ed; ++it) { - ret.push_back(it->first); - } - return ret; - } - - /*! - * @brief 回傳所有 points - */ - Points points() const { - Points ret; - for (IdentityPointsMapIterK - it = self->points_.begin(), ed = self->points_.end(); it != ed; ++it) { - ret.push_back(it->second); - } - return ret; - } - - /*! - * @brief 回傳所有pair - */ - IdentityPointPairs pairs() const { - IdentityPointPairs ret; - for (IdentityPointsMapIterK - it = self->points_.begin(), ed = self->points_.end(); it != ed; ++it) { - ret.push_back(IdentityPointPair(it->first, it->second)); - } - return ret; - } - - /*! - * @brief 取代所有pair - */ - IdentityPointPairs pairs(IdentityPointPairs const& p) { - clear(); - for (size_t i = 0, I = p.size(); i < I; ++i) { - pointAdd(p[i].first, p[i].second); - } - return pairs(); - } - - /*! - * @brief 加入所有pair - */ - IdentityPointPairs pairsAdd(IdentityPointPairs const& p) { - for (size_t i = 0, I = p.size(); i < I; ++i) { - pointAdd(p[i].first, p[i].second); - } - return pairs(); - } - - /*! - * @brief 取得一個identity point - */ - Point point(Identity const& id) const { - return (exist(id) ? self->points_.find(id)->second : Point()); - } - - /*! - * @brief 取得一個 identity point (non-constant reference) - */ - Point& point(Identity const& id) { - static Point tmp(0); - return (exist(id) ? self()->points_.find(id)->second : tmp); - } - - /*! - * @brief 修改一個identity point - */ - Point point(Identity const& id, Point const& b) { - if (b.dimension() == self->dimension_) { - self()->points_[id].copyFrom(b); - } - return point(id); - } - - /*! - * @brief 新增一個identity point - */ - Point pointAdd(Identity const& id, Point const& b) { - if (b.dimension() == self->dimension_ && !exist(id)) { - self()->points_[id].copyFrom(b); - } - return point(id); - } - - /*! - * @brief 刪除一個identity point - */ - void pointDel(Identity const& id) { - self()->points_.erase(id); - } - - /*! - * @brief intersection - */ - Identities intersectIdentites(IdentityPoints const& b) { - Identities ret; - IdentityPointsMapIterK it1, ed1, it2, ed2; - it1 = self->points_.begin(); - ed1 = self->points_.end (); - it2 = b.self->points_.begin(); - ed2 = b.self->points_.end (); - while (it1 != ed1 && it2 != ed2) { - if (it1->first < it2->first) { ++it1; } - else if(it1->first > it2->first) { ++it2; } - else { - ret.push_back(it1->first); - ++it1; - ++it2; - } - } - return ret; - } - - /*! - * @brief intersection - */ - PointPairs intersectPoints(IdentityPoints const& b) { - PointPairs ret; - IdentityPointsMapIterK it1, ed1, it2, ed2; - it1 = self->points_.begin(); - ed1 = self->points_.end (); - it2 = b.self->points_.begin(); - ed2 = b.self->points_.end (); - while (it1 != ed1 && it2 != ed2) { - if (it1->first < it2->first) { ++it1; } - else if(it1->first > it2->first) { ++it2; } - else { - ret.push_back(PointPair(it1->second, it2->second)); - ++it1; - ++it2; - } - } - return ret; - } - - /*! - * @brief same as \c copyFrom(b) - */ - IdentityPoints& operator=(IdentityPoints const& b) { - return copyFrom(b); - } - - /*! @brief 將資料寫入檔案 - * - * @note 未完成 - */ - bool write(FILE* f, bool bin, unsigned int fg) const { - if (bin) { - long dim, ct; - if (fwrite(&(dim = dimension()), sizeof(dim), 1, f) < 1) return false; - if (fwrite(&(ct = size()), sizeof(ct), 1, f) < 1) return false; - IdentityPointsMapIterK it = self->points_.begin(); - IdentityPointsMapIterK ed = self->points_.end (); - for ( ; it != ed; ++it) { - double tmp; - if (fwrite(&(tmp = it->first), sizeof(tmp), 1, f) < 1) return false; - for (long i = 0; i < dim; ++i) { - if (fwrite(&(tmp = it->second(i)), sizeof(tmp), 1, f) < 1) - return false; - } - } - } - else { - if (fprintf(f, "%ld %lu\n", dimension(), size()) < 1) return false; - IdentityPointsMapIterK it = self->points_.begin(); - IdentityPointsMapIterK ed = self->points_.end (); - for ( ; it != ed; ++it) { - if (fprintf(f, "%f ", (double)it->first) < 1) return false; - for (long i = 0, I = dimension(); i < I; ++i) { - if (fprintf(f, "%f ", (double)it->second(i)) < 1) return false; - } - fprintf(f, "\n"); - } - } - return true; - } - - /*! @brief 將資料讀入 - * - * @note 未完成 - */ - bool read(FILE* f, bool bin, unsigned int fg) { - long dim, ct; - if (bin) { - if (fread(&dim, sizeof(dim), 1, f) < 1) return false; - copyFrom(IdentityPoints(dim)); - if (fread(&ct, sizeof(ct), 1, f) < 1) return false; - double id, tt; - IdentityPointsMapIterK it = self->points_.begin(); - IdentityPointsMapIterK ed = self->points_.end (); - Point tmp((size_t)dim, Scalar(0)); - for ( ; it != ed; ++it) { - if (fread(&id, sizeof(id), 1, f) < 1) return false; - for (size_t j = 0, J = dim; j < J; ++j) { - if (fread(&tt, sizeof(tt), 1, f) < 1) return false; - tmp.scalar(j, tt); - } - pointAdd((Identity)id, tmp); - } - } - else { - if (fscanf(f, "%ld %ld", &dim, &ct) < 2) return false; - copyFrom(IdentityPoints(dim)); - double id, tt; - IdentityPointsMapIterK it = self->points_.begin(); - IdentityPointsMapIterK ed = self->points_.end (); - Point tmp((size_t)dim, Scalar(0)); - for ( ; it != ed; ++it) { - if (fscanf(f, "%lf", &id) < 1) return false; - for (int j = 0, J = dim; j < J; ++j) { - if (fscanf(f, "%lf", &tt) < 1) return false; - tmp.scalar(j, tt); - } - pointAdd((Identity)id, tmp); - } - } - return true; - } - - /*! @brief new一個自己 - * - * @return 一個new出來的Bitmap - */ - ObjBase* create() const { - return new IdentityPoints(dimension()); - } - - /*! @brief 複製資料 - * - * 輸入型別是 \c ObjBase \c const* - * 這裡假設實體其實是 \c Bitmap. - * 事實上這個method就只是幫忙轉型然後呼叫原本的\c copyFrom - * - * @param [in] b 資料來源 - * @return this - */ - ObjBase* copyFrom(ObjBase const* b) { - return &(copyFrom(*(IdentityPoints const*)b)); - } - - /*! @brief 回傳class的type - * - * @return \c char \c const\c * 形式的typename - */ - char const* ctype() const { - return typeid(*this).name(); - } - - /*! @brief 回傳class的type - * - * @return \c std::string 形式的typename - */ - std::string type() const { - return std::string(ctype()); - } -}; - -} // meow - -#endif // gra_IdentityPoints_H__ diff --git a/meowpp/gra/Photo.h b/meowpp/gra/Photo.h deleted file mode 100644 index ebd49a4..0000000 --- a/meowpp/gra/Photo.h +++ /dev/null @@ -1,446 +0,0 @@ -#ifndef gra_Photo_H__ -#define gra_Photo_H__ - -#include "Bitmap.h" - -#include "../Self.h" - -#include "../geo/Vectors.h" -#include "../math/utility.h" -#include "../math/Matrix.h" -#include "../math/Transformations.h" - -#include "../oo/ObjBase.h" - -#include -#include -#include -#include -#include - -namespace meow { - -/*! - * @brief 底片 - * - * 基本上就是一個 \c Bitmap 加上 \c focal - * - * @author cat_leopard - */ -template -class Photo: public ObjBase { -private: - struct Myself { - Bitmap bmp_; - Vector2D c_; - PhotoProjection proj_; - - Myself(): proj_(3) { - } - - Myself(Myself const& b): bmp_(b.bmp_), c_(b.c_), proj_(b.proj_) { - } - - ~Myself() { - } - }; - - Self const self; - - /*! - * @brief 取得bitmap座標 - */ - Vector2D bitmapCoord(Vector2D const& yx) const { - return Vector2D(yx.x() + center().x(), -yx.y() + center().y()); - } -public: - /*! - * @brief constructor - * - * focal 預設為 1 - */ - Photo(): self() { - self()->proj_.focal(1.0); - } - - /*! - * @brief constructor - * - * 複製資料 - * - * @param [in] b 資料來源 - */ - Photo(Photo const& b): self(b.self, Self::COPY_FROM) { - } - - /*! - * @brief constructor - * - * 直接給定圖片, 焦距用猜的 - * - * @param [in] bmp 給定的圖片 - */ - Photo(Bitmap const& bmp): self() { - reset(bmp); - } - - /*! - * @brief constructor - * - * 直接給定圖片與焦距 - * - * @param [in] bmp 給定的圖片 - * @param [in] f 給定的焦距 - */ - Photo(Bitmap const& bmp, double f): self() { - reset(bmp, f); - } - - /*! - * @brief constructor - * - * 直接給定圖片, 焦距與中心點位置 - * - * @param [in] bmp 給定的圖片 - * @param [in] f 給定的焦距 - * @param [in] c 中心點作標 - */ - Photo(Bitmap const& bmp, double f, Vector2D const& c): self() { - reset(bmp, f, c); - } - - /*! - * @brief destructor - */ - ~Photo() { - } - - /*! - * @brief 複製資料 - * - * @param [in] b 資料來源 - */ - Photo& copyFrom(Photo const& b) { - self().copyFrom(b.self); - return *this; - } - - /*! - * @brief 參照 - * - * @param [in] b 參照來源 - */ - Photo& referneceFrom(Photo const& b) { - self().referenceFrom(b.self); - return *this; - } - - /*! - * @brief 重設bitmap, focal 用猜的 - * - * focal直接代對角線, center代bitmap中心點 - * - * @param [in] bmp 新的 \c bitmap - */ - void reset(Bitmap const& bmp) { - bitmap(bmp); - focal(sqrt(squ(width()) + squ(height()))); - center(Vector2D(bmp.width() / 2, bmp.height() / 2)); - } - - /*! - * @brief 重設bitmap, focal - * - * center代bitmap中心點 - * - * @param [in] bmp 新的 \c bitmap - * @param [in] f 新的 \c focal - */ - void reset(Bitmap const& bmp, double f) { - bitmap(bmp); - focal(f); - center(Vector2D(bmp.width() / 2, bmp.height() / 2)); - } - - /*! - * @brief 重設bitmap, focal, center - * - * @param [in] bmp 新的 \c bitmap - * @param [in] f 新的 \c focal - * @param [in] c 新的中心點作標 - */ - void reset(Bitmap const& bmp, double f, Vector2D const& c) { - bitmap(bmp); - focal(f); - center(c); - } - - /*! - * @brief 回傳\c bitmap - */ - Bitmap bitmap() const { - return self->bmp_; - } - - /*! - * @brief 回傳\c bitmap 的參照(非constant) - */ - Bitmap& bitmapGet() { - return self()->bmp_; - } - - /*! - * @brief 設定bitmap - * - * @param [in] bmp 新的 bitmap - * @return 新的 \c bitmap - */ - Bitmap bitmap(Bitmap const& bmp) { - self()->bmp_.copyFrom(bmp); - return bitmap(); - } - - /*! - * @brief 回傳focal length - */ - double focal() const { - return self->proj_.focal(); - } - - /*! - * @brief 設定 focal length - * - * @param [in] f 新的 focal length - * @return 新的 \c focal length - */ - double focal(double f) { - self()->proj_.focal(f); - return focal(); - } - - /*! - * @brief 回傳相應的 photo projection - */ - PhotoProjection projection() const { - return self->proj_; - } - - /*! - * @brief 設定 photo projection - */ - PhotoProjection projection(PhotoProjection const& p) { - if (p.dimension() == 3) { - self()->proj_ = p; - } - return projection(); - } - - /*! - * @brief 取得照片中心點底片座標 - * - * @return 一個二維vector - */ - Vector2D center() const { - return self->c_; - } - - /*! - * @brief 取得照片中心點底片座標 (non-constant reference) - * - * @return 一個二維vector - */ - Vector2D& centerGet() { - return self()->c_; - } - - /*! - * @brief 設定照片中心點底片座標 - * - * @param [in] c 新的座標 - * - * @return 新的座標 - */ - Vector2D center(Vector2D const& c) { - self()->c_ = c; - return center(); - } - - /*! - * @brief 回傳bitmap寬 - */ - size_t width() const { - return self->bmp_.width(); - } - - /*! - * @brief 回傳bitmap高 - */ - size_t height() const { - return self->bmp_.height(); - } - - /*! - * @brief 回傳bitmap的某pixel - */ - Pixel pixel(size_t y, size_t x) const { - return self->bmp_.pixel(y, x); - } - - /*! - * @brief 設定某pixel - */ - Pixel pixel(size_t y, size_t x, Pixel const& p) { - self()->bmp_.pixel(y, x, p); - return pixel(y, x); - } - - /*! - * @brief 檢查某點是否在底片範圍內 - * - * @param [in] yx 底片座標 - * - * @return \c true/false - */ - bool inside(Vector2D const& yx) const { - Vector2D c = bitmapCoord(yx); - ssize_t h_max = (ssize_t)height() - 1; - ssize_t w_max = (ssize_t)width () - 1; - return (0 <= c.y() && c.y() <= h_max && 0 <= c.x() && c.x() <= w_max); - } - - /*! - * @brief 檢查某點是否在底片範圍內 - * - * @param [in] p 大地座標 - * - * @return \c true/false - */ - bool inside(Vector3D const& p) const { - if (p.z() > 0) return false; - return inside(Vector2D(self->proj_.transformate(p.matrix()))); - } - - /*! - * @brief 取得給照片座標中某點的色彩 - * - * 用浮點數vector傳入, 所以色彩是經過渲染過的 - * - * @param [in] yx 底片座標(原點為center) - * - * @return pixel - */ - Pixel color(Vector2D const& yx) const { - if (!inside(yx)) return Pixel(0); - Vector2D c(bitmapCoord(yx)); - int y0 = (int)c.y(); - int x0 = (int)c.x(); - double h[2] = {1 - (c.y() - y0), c.y() - y0}; - double w[2] = {1 - (c.x() - x0), c.x() - x0}; - Pixel sum(0); - for (int dy = 0; dy < 2; dy++) - for (int dx = 0; dx < 2; dx++) { - sum = sum + bitmap().pixel( - std::min(y0 + dy, (int)height() - 1), - std::min(x0 + dx, (int)width () - 1)) * (w[dy] * h[dx]); - } - return sum; - } - - /*! - * @brief 取得給照片座標中某點的色彩 - * - * 這次是輸入大地座標 - * - * @param [in] p 大地座標p - * @return pixel - */ - Pixel color(Vector3D const& p) const { - return color(Vector2D(self->proj_.transformate(p.matrix()))); - } - - /*! - * @brief same as \c .copyFrom(b) - */ - Photo& operator=(Photo const& b) { - return copyFrom(b); - } - - /*! @brief 將資料寫入檔案 - * - * @note 未完成 - */ - bool write(FILE* f, bool bin, unsigned int fg) const { - if (bitmap().write(f, bin, fg) == false) return false; - if (bin) { - double tmp; - if (fwrite(&(tmp = center().x()), sizeof(tmp), 1, f) < 1) return false; - if (fwrite(&(tmp = center().y()), sizeof(tmp), 1, f) < 1) return false; - if (fwrite(&(tmp = focal()), sizeof(tmp), 1, f) < 1) return false; - } - else { - if (fprintf(f, "%f %f\n", center().x(), center().y()) < 2) return false; - if (fprintf(f, "%f\n", focal()) < 1) return false; - } - return true; - } - - /*! @brief 將資料讀入 - * - * @note 未完成 - */ - bool read(FILE* f, bool bin, unsigned int fg) { - if (bitmapGet().read(f, bin, fg) == false) return false; - double tmp[3]; - if (bin) { - if (fread(tmp, sizeof(double), 3, f) < 3) return false; - } - else { - if (fscanf(f, "%lf %lf %lf", tmp + 0, tmp + 1, tmp + 2) < 3) return false; - } - centerGet().x(tmp[0]); - centerGet().y(tmp[1]); - focal(tmp[2]); - return true; - } - - /*! @brief new一個自己 - * - * @return 一個new出來的Photo - */ - ObjBase* create() const { - return new Photo(); - } - - /*! @brief 複製資料 - * - * 輸入型別是 \c ObjBase \c const* - * 這裡假設實體其實是 \c Bitmap. - * 事實上這個method就只是幫忙轉型然後呼叫原本的\c copyFrom - * - * @param [in] b 資料來源 - * @return this - */ - ObjBase* copyFrom(ObjBase const* b) { - return &(copyFrom(*(Photo*)b)); - } - - /*! @brief 回傳class的type - * - * @return \c char \c const\c * 形式的typename - */ - char const* ctype() const{ - return typeid(*this).name(); - } - - /*! @brief 回傳class的type - * - * @return \c std::string 形式的typename - */ - std::string type() const { - return std::string(ctype()); - } -}; - -} // meow - -#endif // gra_Photo_H__ diff --git a/meowpp/gra/ViewPort.h b/meowpp/gra/ViewPort.h deleted file mode 100644 index 81ad8f3..0000000 --- a/meowpp/gra/ViewPort.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef gra_ViewPort_H__ -#define gra_ViewPort_H__ - -#include "../oo/ObjBase.h" - -namespace meow { - -/*! - * @brief 未完待續 - */ -class ViewPort: public ObjBase { - -}; - - -} // meow - -#endif // gra_ViewPort_H__ - diff --git a/meowpp/gra/WatchBall.h b/meowpp/gra/WatchBall.h deleted file mode 100644 index 3c73e2f..0000000 --- a/meowpp/gra/WatchBall.h +++ /dev/null @@ -1,252 +0,0 @@ -#ifndef gra_WatchBall_H__ -#define gra_WatchBall_H__ - -#include "Camera.h" - -#include "../Self.h" -#include "../geo/Vectors.h" -#include "../math/LinearTransformations.h" -#include "../oo/ObjBase.h" - -#include -#include - -namespace meow { - -/*! - * @brief \b 多個camera, 一個offset, 一個rotation - * - * @author cat_leopard - */ -template -class WatchBall: public ObjBase { -public: - typedef std::vector > Cameras; -private: - struct Myself { - Cameras cameras_; - Vector3D offset_; - - Myself() { - } - - Myself(Myself const& b): cameras_(b.cameras_), offset_(b.offset_) { - } - - ~Myself() { - } - }; - - Self const self; -public: - /*! - * @brief constructor - */ - WatchBall(): self() { - } - - /*! - * @brief copy constructor - */ - WatchBall(WatchBall const& b): self(b.self, Self::COPY_FROM) { - } - - /*! - * @brief destructor - */ - ~WatchBall() { - } - - /*! - * @brief copy data - */ - WatchBall& copyFrom(WatchBall const& b) { - self().copyFrom(b.self); - return *this; - } - - /*! - * @brief reference - */ - WatchBall& referenceFrom(WatchBall const& b) { - self().referenceFrom(b.self); - return *this; - } - - /*! - * @brief 取得有幾個camera - */ - size_t cameraSize() const { - return self->cameras_.size(); - } - - /*! - * @brief 取得 cameras - */ - Cameras cameras() const { - return self->cameras_; - } - - /*! - * @brief 取得 cameras (non-constant) - */ - Cameras& camerasGet() { - return self()->cameras_; - } - - /*! - * @brief 設定 camera - */ - Cameras cameras(Cameras const& c) { - self()->cameras_ = c; - return cameras(); - } - - /*! - * @brief 取得第i個camera - */ - Camera camera(size_t i) const { - return cameras()[i]; - } - - /*! - * @brief 取得第i個camera (non-constant reference) - */ - Camera& cameraGet(size_t i) { - return cameras()[i]; - } - - /*! - * @brief 設定第i個camera - */ - Camera camera(size_t i, Camera const& c) { - cameras()[i] = c; - return camera(i); - } - - /*! - * @brief 取得offset - */ - Vector3D offset() const { - return self->offset_; - } - - /*! - * @brief 取得offset (non-constant reference) - */ - Vector3D& offsetGet() { - return self()->offset_; - } - - /*! - * @brief 設定offset - */ - Vector3D offset(Vector3D const& ofs) { - self()->offset_ = ofs; - return offset(); - } - - /*! - * @brief 取得底片color - */ - Pixel color(Vector3D p) const { - Vector3D p2(p - offset()); - Pixel sum(0); - double ct = 0; - for (size_t i = 0, I = cameraSize(); i < I; ++i) { - if (camera(i).inside(p2)) { - sum = sum + camera(i).color(p2); - ++ct; - } - } - return (ct > 0 ? sum / ct : sum); - } - - /*! - * @brief 輸出展開圖 - * - * @param [in] radius 半徑 - */ - Bitmap expand(double radius) const { - radius = std::max(radius, 0.5); - size_t height = std::max(1, 2.0 * radius); - size_t width = 2.0* PI * radius; - Bitmap ret(height, width, Pixel(0)); - for (size_t i = 0; i < height; ++i) { - for (size_t j = 0; j < width; ++j) { - double theta = (1.0 * j / width - 0.5) * 2 * PI; - double phi = asin(-(1.0 * i / height - 0.5) * 2.0); - ret.pixel(i, j, color(Vector3D( - sin(theta) * cos(phi), - sin(phi), - -cos(theta) * cos(phi) - ))); - } - } - return ret; - } - - /*! - * @brief same as \c copyFrom(b) - */ - WatchBall& operator=(WatchBall const& b) { - return copyFrom(b); - } - - /*! @brief 將資料寫入檔案 - * - * @note 未完成 - */ - bool write(FILE* f, bool bin, unsigned int fg) const { - return false; - } - - /*! @brief 將資料讀入 - * - * @note 未完成 - */ - bool read(FILE* f, bool bin, unsigned int fg) { - return false; - } - - /*! @brief new一個自己 - * - * @return 一個new出來的pointer - */ - ObjBase* create() const { - return new WatchBall(); - } - - /*! - * @brief 複製資料 - * - * 輸入型別是 \c ObjBase \c const* - * 事實上這個method就只是幫忙轉型然後呼叫原本的\c copyFrom - * - * @param [in] b 資料來源 - * @return this - */ - ObjBase* copyFrom(ObjBase const* b) { - return &(copyFrom(*(WatchBall const*)b)); - } - - /*! @brief 回傳class的type - * - * @return \c char \c const\c * 形式的typename - */ - char const* ctype() const{ - return typeid(*this).name(); - } - - /*! @brief 回傳class的type - * - * @return \c std::string 形式的typename - */ - std::string type() const { - return std::string(ctype()); - } -}; - -} // meow - -#endif // gra_WatchBall_H__ diff --git a/meowpp/math/!readme.asciidoc b/meowpp/math/!readme.asciidoc deleted file mode 100644 index 062b45d..0000000 --- a/meowpp/math/!readme.asciidoc +++ /dev/null @@ -1,73 +0,0 @@ - - -===== utility.h - -數學相關的小 function 雜七雜八的不知道歸類何處 - -.Functions -* noEPS() -* normalize() -* denormalize() -* ratioMapping() -* inRange() -* squ() -* cub() -* average() -* average() -* tAbs() - -.Constants -* PI - -===== Matrix.h - -.Classes -* `meow::Matrix` - -===== Vector.h - -實作上將 *Matrix* 重新包裝 - -.Classes -* `meow::Vector` - -===== Transformation.h - -各種轉換的 Base Class, 這裡所謂的 *Transformation* 形式上不一定要是 Linear, -但原則上都是 *input a vector, output a vector* 其中input/output的dimension可以 -不同. - -.Classes -* `meow::Transformation` - -===== Transformations.h - -包含各種 *Non-Linear* transformation - -.Classes -* `meow::BallProjection` -* `meow::PhotoProjection` - -===== LinearTransformation.h - -各種 LinearTransformation 的Base Class, 繼承自 `meow::Transformation` - -.Classes -* `meow::LinearTransformation` - -===== LinearTransformations.h - -各種 *Linear* Transformation - -.Classes -* `meow::Rotation3D` - -===== methods.h - -一些數學方法 - -.Functions -* ransac() -* levenbergMarquardt() - - diff --git a/meowpp/math/LinearTransformation.h b/meowpp/math/LinearTransformation.h deleted file mode 100644 index 0dc3735..0000000 --- a/meowpp/math/LinearTransformation.h +++ /dev/null @@ -1,110 +0,0 @@ -#ifndef math_LinearTransformation_H__ -#define math_LinearTransformation_H__ - -#include "Transformation.h" -#include "Matrix.h" - -#include - -namespace meow { - -/*! - * @brief A base class for implementing kinds of linear transformations. - * - * Because all linear transformations belong to transformations, - * this class inherit to Transformation. - * - * @author cat_leopard - */ -template -class LinearTransformation: public Transformation { -private: - Matrix matrix_; -protected: - /*! - * Constructor with input/output size gived - */ - LinearTransformation(size_t inputRows, size_t outputRows, size_t psize): - Transformation(inputRows, 1u, outputRows, 1u, psize), - matrix_(outputRows, inputRows, Scalar(0.0)) { - } - - /*! - * Constructor with input/output size gived and a inital matrix - */ - LinearTransformation(size_t inputRows, size_t outputRows, size_t psize, - Matrix const& m): - Transformation(inputRows, 1u, outputRows, 1u, psize), - matrix_(m) { - } - - /*! - * Constructor with another LinearTransformation - * - * @param [in] b another LinearTransformation - */ - LinearTransformation(LinearTransformation const& b): - Transformation(b), - matrix_(b.matrix_) { - } - - /*! - * @brief Copy settings, matrix from another LinearTransformation - * - * @param [in] b another LinearTransformation - */ - LinearTransformation& copyFrom(LinearTransformation const& b) { - Transformation::copyFrom(b); - matrix_.copyFrom(b.matrix_); - return *this; - } - - /*! - * @brief Reference settings, matrix from another LinearTransformation - * - * @param [in] b another LinearTransformation - */ - LinearTransformation& referenceFrom(LinearTransformation const& b) { - Transformation::referenceFrom(b); - matrix_.referenceFrom(b.matrix_); - return *this; - } - - /*! - * @brief setup the matrix - */ - virtual Matrix const& matrix(Matrix const& m) { - matrix_.copyFrom(m); - return matrix(); - } - -public: - /*! - * Destructor - */ - virtual ~LinearTransformation() { - } - - /*! - * @brief Return the matrix form of this transformation - * - * @return A matrix - */ - virtual Matrix const& matrix() const { - return matrix_; - } - - /*! - * @brief Return the inverse of the matrix form of this transformate - * - * @return A matrix (may be invalid) - */ - virtual Matrix matrixInv() const { - return matrix_.inverse(); - } -}; - - -} // meow - -#endif // math_LinearTransformation_H__ diff --git a/meowpp/math/LinearTransformations.h b/meowpp/math/LinearTransformations.h deleted file mode 100644 index 4bf9a36..0000000 --- a/meowpp/math/LinearTransformations.h +++ /dev/null @@ -1,404 +0,0 @@ -#ifndef math_LinearTransformations_H__ -#define math_LinearTransformations_H__ - -#include "LinearTransformation.h" -#include "Matrix.h" -#include "utility.h" -#include "../Self.h" -#include "../geo/Vectors.h" - -#include - -namespace meow { - -/*! - * @brief Rotation a point/vector alone an axis with given angle in 3D world. - * - * @author cat_leopard - */ -template -class Rotation3D: public LinearTransformation { -private: - struct Myself { - Vector3D theta_; - bool need_; - - Myself(): theta_(0, 0, 0), need_(true) { - } - - Myself(Myself const& b): theta_(b.theta_), need_(b.need_) { - } - - ~Myself() { - } - }; - - Self const self; - - void calcMatrix() const { - if (self->need_) { - Matrix tmp(3, 3, 0.0); - if (noEPS(self->theta_.length2()) == 0) { - tmp.identitied(); - } - else { - Vector3D axis (self->theta_.normalize()); - double angle(self->theta_.length()); - double cs(cos(angle / 2.0)); - double sn(sin(angle / 2.0)); - - tmp.entry(0, 0, 2*(squ(axis.x())-1.0)*squ(sn) + 1); - tmp.entry(1, 1, 2*(squ(axis.y())-1.0)*squ(sn) + 1); - tmp.entry(2, 2, 2*(squ(axis.z())-1.0)*squ(sn) + 1); - tmp.entry(0, 1, 2*axis.x()*axis.y()*squ(sn) - 2*axis.z()*cs*sn); - tmp.entry(1, 0, 2*axis.y()*axis.x()*squ(sn) + 2*axis.z()*cs*sn); - tmp.entry(0, 2, 2*axis.x()*axis.z()*squ(sn) + 2*axis.y()*cs*sn); - tmp.entry(2, 0, 2*axis.z()*axis.x()*squ(sn) - 2*axis.y()*cs*sn); - tmp.entry(1, 2, 2*axis.y()*axis.z()*squ(sn) - 2*axis.x()*cs*sn); - tmp.entry(2, 1, 2*axis.z()*axis.y()*squ(sn) + 2*axis.x()*cs*sn); - } - ((Rotation3D*)this)->LinearTransformation::matrix(tmp); - self()->need_ = false; - } - } - -public: - /*! - * Constructor with no rotation - */ - Rotation3D(): LinearTransformation(3u, 3u, 3u), self() { - } - - /*! - * Constructor and copy data - */ - Rotation3D(Rotation3D const& b): LinearTransformation(b), - self(b.self, Self::COPY_FROM) { - } - - /*! - * Destructor - */ - ~Rotation3D() { - } - - /*! - * @brief Copy data - * - * @param [in] b another Rotation3D class. - * @return \c *this - */ - Rotation3D& copyFrom(Rotation3D const& b) { - LinearTransformation::copyFrom(b); - self().copyFrom(b.self); - return *this; - } - - /*! - * @brief Reference data - * - * @param [in] b another Rotation3D class. - * @return \c *this - */ - Rotation3D& referenceFrom(Rotation3D const& b) { - LinearTransformation::referenceFrom(b); - self().referenceFrom(b.self); - return *this; - } - - /*! - * @brief same as \c theta(i) - */ - Scalar parameter(size_t i) const { - return theta(i); - } - - /*! - * @brief same as \c theta(i, s) - */ - Scalar parameter(size_t i, Scalar const& s) { - return theta(i, s); - } - - /*! - * @brief Get the \c i -th theta - * - * \c i can only be 1, 2 or 3 - * - * @param [in] i index - * @return \c i -th theta - */ - Scalar const& theta(size_t i) const { - return self->theta_(i); - } - - /*! - * @brief Set the \c i -th theta - * - * \c i can only be 1, 2 or 3 - * - * @param [in] i index - * @param [in] s new theta value - * @return \c i -th theta - */ - Scalar const& theta(size_t i, Scalar const& s) { - if (theta(i) != s) { - if (i == 0) self()->theta_.x(s); - else if (i == 1) self()->theta_.y(s); - else if (i == 2) self()->theta_.z(s); - self()->need_ = true; - } - return theta(i); - } - - /*! - * @brief Setting - * - * @param [in] axis axis - * @param [in] angle angle - */ - void axisAngle(Vector const& axis, Scalar const& angle) { - Vector n(axis.normalize()); - for (size_t i = 0; i < 3; i++) { - theta(i, n(i) * angle); - } - } - - /*! - * @brief Concat another rotation transformation - * @param [in] r another rotation transformation - */ - Rotation3D& add(Rotation3D const& r) { - for (size_t i = 0; i < 3; i++) { - theta(i, r.theta(i)); - } - return *this; - } - - /*! - * @brief Do the transformate - - * Assume: - * - The input vector is \f$ (x ,y ,z ) \f$ - * - The output vector is \f$ (x',y',z') \f$ - * - The parameters theta is\f$ \vec{\theta}=(\theta_x,\theta_y,\theta_z) \f$ - * . - * Then we have: - * \f[ - * \left[ \begin{array}{c} x' \\ y' \\ z' \\ \end{array} \right] - * = - * \left[ \begin{array}{ccc} - * 2(n_x^2 - 1) \sin^2\phi + 1 & - * 2n_x n_y \sin^2\phi - 2n_z\cos \phi\sin \phi & - * 2n_x n_z \sin^2\phi + 2n_y\cos \phi\sin \phi \\ - * 2n_y n_x \sin^2\phi + 2n_z\cos \phi\sin \phi & - * 2(n_y^2 - 1) \sin^2\phi + 1 & - * 2n_y n_z \sin^2\phi - 2n_x\cos \phi\sin \phi \\ - * 2n_z n_x \sin^2\phi - 2n_y\cos \phi\sin \phi & - * 2n_z n_y \sin^2\phi + 2n_x\cos \phi\sin \phi & - * 2(n_z^2 - 1) \sin^2\phi + 1 \\ - * \end{array} \right] - * \left[ \begin{array}{c} x \\ y \\ z \\ \end{array} \right] - * \f] - * Where: - * - \f$ \phi \f$ is the helf of length of \f$ \vec{\theta} \f$ , - * which means \f$ \phi = \frac{\left|\vec{\theta}\right|}{2} - * = \frac{1}{2}\sqrt{\theta_x^2 + \theta_y^2 + \theta_z^2} \f$ - * - \f$ \vec{n} \f$ is the normalized form of \f$ \vec{\theta} \f$ , - * which means \f$ \vec{n} = (n_x,n_y,n_z) = \vec{\theta} / 2\phi \f$ - * - * @param [in] x the input vector - * @return the output matrix - */ - Matrix transformate(Matrix const& x) const { - calcMatrix(); - return LinearTransformation::matrix() * x; - } - - /*! - * @brief Return the jacobian matrix (derivate by the input vector) - * of this transformate - * - * The matrix we return is: - * \f[ - * \left[ \begin{array}{ccc} - * 2(n_x^2 - 1) \sin^2\phi + 1 & - * 2n_x n_y \sin^2\phi - 2n_z\cos \phi\sin \phi & - * 2n_x n_z \sin^2\phi + 2n_y\cos \phi\sin \phi \\ - * 2n_y n_x \sin^2\phi + 2n_z\cos \phi\sin \phi & - * 2(n_y^2 - 1) \sin^2\phi + 1 & - * 2n_y n_z \sin^2\phi - 2n_x\cos \phi\sin \phi \\ - * 2n_z n_x \sin^2\phi - 2n_y\cos \phi\sin \phi & - * 2n_z n_y \sin^2\phi + 2n_x\cos \phi\sin \phi & - * 2(n_z^2 - 1) \sin^2\phi + 1 \\ - * \end{array} \right] - * \f] - * Where the definition of \f$ \vec{n} \f$ and \f$ \phi \f$ - * is the same as the definition in the description of - * the method \b transformate() . - * - * @param [in] x the input vector (in this case it is a useless parameter) - * @return a matrix - */ - Matrix jacobian(Matrix const& x) const { - calcMatrix(); - return LinearTransformation::matrix(); - } - - /*! - * @brief Return the jacobian matrix of this transformate - * - * Here we need to discussion in three case: - * - \a i = 0, derivate by the x axis of the vector theta - * \f[ - * \left[ \begin{array}{ccc} - * 0 & 0 & 0 \\ - * 0 & 0 & -1 \\ - * 0 & 1 & 0 \\ - * \end{array} \right] - * \left[ \begin{array}{ccc} - * 2(n_x^2 - 1) \sin^2\phi + 1 & - * 2n_x n_y \sin^2\phi - 2n_z\cos \phi\sin \phi & - * 2n_x n_z \sin^2\phi + 2n_y\cos \phi\sin \phi \\ - * 2n_y n_x \sin^2\phi + 2n_z\cos \phi\sin \phi & - * 2(n_y^2 - 1) \sin^2\phi + 1 & - * 2n_y n_z \sin^2\phi - 2n_x\cos \phi\sin \phi \\ - * 2n_z n_x \sin^2\phi - 2n_y\cos \phi\sin \phi & - * 2n_z n_y \sin^2\phi + 2n_x\cos \phi\sin \phi & - * 2(n_z^2 - 1) \sin^2\phi + 1 \\ - * \end{array} \right] - * \left[ \begin{array}{c} x \\ y \\ z \\ \end{array} \right] - * \f] - * - \a i = 1, derivate by the y axis of the vector theta - * \f[ - * \left[ \begin{array}{ccc} - * 0 & 0 & 1 \\ - * 0 & 0 & 0 \\ - * -1 & 0 & 0 \\ - * \end{array} \right] - * \left[ \begin{array}{ccc} - * 2(n_x^2 - 1) \sin^2\phi + 1 & - * 2n_x n_y \sin^2\phi - 2n_z\cos \phi\sin \phi & - * 2n_x n_z \sin^2\phi + 2n_y\cos \phi\sin \phi \\ - * 2n_y n_x \sin^2\phi + 2n_z\cos \phi\sin \phi & - * 2(n_y^2 - 1) \sin^2\phi + 1 & - * 2n_y n_z \sin^2\phi - 2n_x\cos \phi\sin \phi \\ - * 2n_z n_x \sin^2\phi - 2n_y\cos \phi\sin \phi & - * 2n_z n_y \sin^2\phi + 2n_x\cos \phi\sin \phi & - * 2(n_z^2 - 1) \sin^2\phi + 1 \\ - * \end{array} \right] - * \left[ \begin{array}{c} x \\ y \\ z \\ \end{array} \right] - * \f] - * - \a i = 2, derivate by the z axis of the vector theta - * \f[ - * \left[ \begin{array}{ccc} - * 0 & -1 & 0 \\ - * 1 & 0 & 0 \\ - * 0 & 0 & 0 \\ - * \end{array} \right] - * \left[ \begin{array}{ccc} - * 2(n_x^2 - 1) \sin^2\phi + 1 & - * 2n_x n_y \sin^2\phi - 2n_z\cos \phi\sin \phi & - * 2n_x n_z \sin^2\phi + 2n_y\cos \phi\sin \phi \\ - * 2n_y n_x \sin^2\phi + 2n_z\cos \phi\sin \phi & - * 2(n_y^2 - 1) \sin^2\phi + 1 & - * 2n_y n_z \sin^2\phi - 2n_x\cos \phi\sin \phi \\ - * 2n_z n_x \sin^2\phi - 2n_y\cos \phi\sin \phi & - * 2n_z n_y \sin^2\phi + 2n_x\cos \phi\sin \phi & - * 2(n_z^2 - 1) \sin^2\phi + 1 \\ - * \end{array} \right] - * \left[ \begin{array}{c} x \\ y \\ z \\ \end{array} \right] - * \f] - * . - * Where \f$ (x,y,z) \f$ is the input vector, \f$ \vec{n}, \phi \f$ is the - * same one in the description of \b transformate(). - * - * @param [in] x the input vector - * @param [in] i the index of the parameters(theta) to dervite - * @return a matrix - */ - Matrix jacobian(Matrix const& x, size_t i) const { - calcMatrix(); - Matrix mid(3u, 3u, Scalar(0.0)); - if (i == 0) { - mid.entry(1, 2, Scalar(-1.0)); - mid.entry(2, 1, Scalar( 1.0)); - } - else if(i == 1) { - mid.entry(0, 2, Scalar( 1.0)); - mid.entry(2, 0, Scalar(-1.0)); - } - else { - mid.entry(0, 1, Scalar(-1.0)); - mid.entry(1, 0, Scalar( 1.0)); - } - return mid * LinearTransformation::matrix() * x; - } - - /*! - * @brief Do the inverse transformate - * - * @param [in] x the input vector - * @return the output vector - */ - Matrix transformateInv(Matrix const& x) const { - return matrixInv() * x; - } - - /*! - * @brief Return the jacobian matrix of the inverse form of this transformate - * - * @param [in] x the input vector - * @return a matrix - */ - Matrix jacobianInv(Matrix const& x) const { - return matrixInv(); - } - - /*! - * @brief Return the jacobian matrix of the inverse form of this transformate - * - * @param [in] x the input vector - * @param [in] i the index of the parameters(theta) to dervite - * @return a matrix - */ - Matrix jacobianInv(Matrix const& x, size_t i) const { - calcMatrix(); - Matrix mid(3u, 3u, Scalar(0.0)); - if (i == 0) { - mid.entry(1, 2, Scalar(-1.0)); - mid.entry(2, 1, Scalar( 1.0)); - } - else if(i == 1) { - mid.entry(0, 2, Scalar( 1.0)); - mid.entry(2, 0, Scalar(-1.0)); - } - else { - mid.entry(0, 1, Scalar(-1.0)); - mid.entry(1, 0, Scalar( 1.0)); - } - return matrixInv() * mid.transpose() * x; - return (-mid) * matrixInv() * x; - } - - /*! - * @brief Return the inverse matrix - * - * In this case, the inverse matrix is equal to the transpose of the matrix - * - * @return a matrix - */ - Matrix matrixInv() const { - calcMatrix(); - return LinearTransformation::matrix().transpose(); - } - - //! @brief same as \c copyFrom(b) - Rotation3D& operator=(Rotation3D const& b) { - return copyFrom(b); - } -}; - -} // meow - -#endif // math_LinearTransformations_H__ diff --git a/meowpp/math/Matrix.h b/meowpp/math/Matrix.h deleted file mode 100644 index a2f45aa..0000000 --- a/meowpp/math/Matrix.h +++ /dev/null @@ -1,536 +0,0 @@ -#ifndef math_Matrix_H__ -#define math_Matrix_H__ - -#include "../Self.h" -#include "../math/utility.h" - -#include -#include - -#include - -namespace meow { -/*! - * @brief \b matrix - * - * @author cat_leopard - */ -template -class Matrix { -public: - typedef typename std::vector::reference EntryRef ; - typedef typename std::vector::const_reference EntryRefK; -private: - struct Myself { - size_t rows_; - size_t cols_; - std::vector entries_; - - Myself(): - rows_(0), cols_(0), entries_(0) { - } - - Myself(Myself const& b): - rows_(b.rows_), cols_(b.cols_), entries_(b.entries_) { - } - - Myself(size_t r, size_t c, Entry const& e): - rows_(r), cols_(c), entries_(r * c, e) { - } - - ~Myself() { - } - - size_t index(size_t r, size_t c) const { - return r * cols_ + c; - } - - void realSize() { - std::vector tmp(entries_); - entries_.swap(tmp); - } - }; - - Self const self; -public: - /*! - * @brief constructor - * - * Create an empty matrix with size \b 0x0. - * In other world, create an \b invalid matrix - */ - Matrix(): self() { } - - /*! - * @brief constructor - * - * Copy data from another one - * - * @param [in] m another matrix - */ - Matrix(Matrix const& m): self(m.self, Self::COPY_FROM) { - } - - /*! - * @brief constructor - * - * Create an \a r x \a c matrix with all entry be \a e - * - * @param [in] r number of rows - * @param [in] c number of columns - * @param [in] e inital entry - */ - Matrix(size_t r, size_t c, Entry const& e): self(Myself(r, c, e)) { - } - - //! @brief destructor - ~Matrix() { } - - /*! - * @brief copy - * - * Copy data from another matrix - * - * @param [in] m matrix - * @return *this - */ - Matrix& copyFrom(Matrix const& m) { - self().copyFrom(m.self); - return *this; - } - - /*! - * @brief reference - * - * Reference itself to another matrix - * - * @param [in] m matrix - * @return *this - */ - Matrix& referenceFrom(Matrix const& m) { - self().referenceFrom(m.self); - return *this; - } - - //! @brief reset the size of the matrix to \a r x \a c with entry all be \a e - void reset(size_t r, size_t c, Entry const& e) { - self()->rows_ = r; - self()->cols_ = c; - self()->entries_.clear(); - self()->entries_.resize(r * c, e); - } - - //! @brief Return whether it is a \b valid matrix - bool valid() const { - return (rows() > 0 && cols() > 0); - } - - //! @brief Return number of rows - size_t rows() const { - return self->rows_; - } - - //! @brief Return number of cols - size_t cols() const { - return self->cols_; - } - - //! @brief Return number of rows times number of cols - size_t size() const { - return rows() * cols(); - } - - /*! - * @brief resize the matrix such that number of rows become \a r. - * - * New created entry will be \a e - * - * @param [in] r new number of rows - * @param [in] e inital entry - * @return new number of rows - */ - size_t rows(size_t r, Entry const& e) { - if (r != rows()) { - self()->entries_.resize(r * cols(), e); - self()->rows_ = r; - } - return rows(); - } - - /*! - * @brief resize the matrix such that number of cols become \a c - * - * New created entry will be \a e - * - * @param [in] c new number of columns - * @param [in] e inital entry - * @return new number of columns - */ - size_t cols(size_t c, Entry const& e) { - if (c != cols()) { - Self const old(self, Self::COPY_FROM); - self()->entries_.resize(rows() * c); - self()->cols_ = c; - for (size_t i = 0, I = rows(); i < I; i++) { - size_t j, J1 = std::min(old->cols_, cols()), J2 = cols(); - for (j = 0; j < J1; j++) - self()->entries_[self->index(i, j)] = old->entries_[old->index(i, j)]; - for (j = J1; j < J2; j++) - self()->entries_[self->index(i, j)] = e; - } - } - return cols(); - } - - /*! - * @brief resize - * - * Resize to \a r x \a c, with new created entry be \a e - * - * @param [in] r number of rows - * @param [in] c number of rows - * @param [in] e inital entry - * @return \a r * \a c - */ - size_t size(size_t r, size_t c, Entry const& e) { - cols(c, e); - rows(r, e); - return rows() * cols(); - } - - /*! - * @brief free the memory - */ - void clear() { - self()->rows_ = 0; - self()->cols_ = 0; - self()->entries_.clear(); - self()->realSize(); - } - - //! @brief Access the entry at \a r x \a c - Entry entry(size_t r, size_t c) const { - return self->entries_[self->index(r, c)]; - } - - //! @brief Change the entry at \a r x \a c - Entry entry(size_t r, size_t c, Entry const& e) { - self()->entries_[self->index(r, c)] = e; - return entry(r, c); - } - - //! @brief Get the entry at \a r x \a c - EntryRef entryGet(size_t r, size_t c) { - return self()->entries_[self->index(r, c)]; - } - - /*! - * @brief Change the entries from \a rFirst x \a cFirst to \a rLast x \a cLast - * - * @param [in] rFirst - * @param [in] rLast - * @param [in] cFirst - * @param [in] cLast - * @param [in] e value - * @return void - */ - void entries(ssize_t rFirst, ssize_t rLast, - ssize_t cFirst, ssize_t cLast, - Entry const& e) { - for (ssize_t r = rFirst; r <= rLast; r++) { - for (ssize_t c = cFirst; c <=cFirst; c++) { - entry(r, c, e); - } - } - } - - /*! - * @brief Return a \a rLast-rFirst+1 x \a cLast-cFirst+1 matrix - * - * With value be the entries from \a rFirst x \a cFirst to \a rLast x \a cLast - * - * @param [in] rFirst - * @param [in] rLast - * @param [in] cFirst - * @param [in] cLast - * @return a matrix - */ - Matrix subMatrix(size_t rFirst, size_t rLast, - size_t cFirst, size_t cLast) const { - if (rFirst > rLast || cFirst > cLast) return Matrix(); - if (rFirst == 0 && cFirst == 0) { - Matrix ret(*this); - ret.size(rLast + 1, cLast + 1, Entry(0)); - return ret; - } - Matrix ret(rLast - rFirst + 1, cLast - cFirst + 1, entry(rFirst, cFirst)); - for (size_t r = rFirst; r <= rLast; r++) - for (size_t c = cFirst; c <= cLast; c++) - ret.entry(r - rFirst, c - cFirst, entry(r, c)); - return ret; - } - - //! @brief Return the \a r -th row - Matrix row(size_t r) const { - return subMatrix(r, r, 0, cols() - 1); - } - - //! @brief Return the \a c -th column - Matrix col(size_t c) const { - return subMatrix(0, rows() - 1, c, c); - } - - //! @brief return +\a (*this) - Matrix positive() const { - return *this; - } - - //! @brief return -\a (*this) - Matrix negative() const { - Matrix ret(*this); - for (size_t r = 0, R = rows(); r < R; r++) - for (size_t c = 0, C = cols(); c < C; c++) - ret.entry(r, c, -ret.entry(r, c)); - return ret; - } - - /*! @brief return \a (*this) + \a m. - * - * If the size not match, it will return an invalid matrix - */ - Matrix add(Matrix const& m) const { - if (rows() != m.rows() || cols() != m.cols()) return Matrix(); - Matrix ret(*this); - for (size_t r = 0, R = rows(); r < R; r++) - for (size_t c = 0, C = cols(); c < C; c++) - ret.entry(r, c, ret.entry(r, c) + m.entry(r, c)); - return ret; - } - - /*! @brief return \a (*this) - \a m. - * - * If the size not match, it will return an invalid matrix - */ - Matrix sub(Matrix const& m) const { - if (rows() != m.rows() || cols() != m.cols()) return Matrix(); - Matrix ret(*this); - for (size_t r = 0, R = rows(); r < R; r++) - for (size_t c = 0, C = cols(); c < C; c++) - ret.entry(r, c, ret.entry(r, c) - m.entry(r, c)); - return ret; - } - - /*! @brief return \a (*this) times \a m. - * - * If the size not match, it will return an invalid matrix - */ - Matrix mul(Matrix const& m) const { - if (cols() != m.rows()) return Matrix(); - Matrix ret(rows(), m.cols(), Entry(0)); - for (size_t r = 0, R = rows(); r < R; r++) - for (size_t c = 0, C = m.cols(); c < C; c++) - for (size_t k = 0, K = cols(); k < K; k++) - ret.entry(r, c, ret.entry(r, c) + entry(r, k) * m.entry(k, c)); - return ret; - } - - //! @brief return \a (*this) times \a s. \a s is a scalar - Matrix mul(Entry const& s) const { - Matrix ret(*this); - for (size_t r = 0, R = rows(); r < R; r++) - for (size_t c = 0, C = cols(); c < C; c++) - ret.entry(r, c, ret.entry(r, c) * s); - return ret; - } - - //! @brief return \a (*this) / \a s. \a s is a scalar - Matrix div(Entry const& s) const { - Matrix ret(*this); - for (size_t r = 0, R = rows(); r < R; r++) - for (size_t c = 0, C = cols(); c < C; c++) - ret.entry(r, c, ret.entry(r, c) / s); - return ret; - } - - //! @brief Return a identity matrix with size equal to itself - Matrix identity() const { - Matrix ret(*this); - ret.identitied(); - return ret; - } - - /*! - * @brief Let itself be an identity matrix - * - * Our definition of Identity matrix is 1 for entry(i, i) and 0 otherwise. - */ - Matrix& identitied() { - for (size_t r = 0, R = rows(); r < R; r++) - for (size_t c = 0, C = cols(); c < C; c++) - entry(r, c, (r == c ? Entry(1) : Entry(0))); - return *this; - } - - /*! - * @brief Let itself be an diagonal form of original itself - */ - Matrix& diagonaled() { - triangulared(); - for (size_t i = 0, I = rows(); i < I; ++i) { - for (size_t j = i + 1, J = cols(); j < J; ++j) { - entry(i, j, Entry(0)); - } - } - return *this; - } - - /*! - * @brief Return a matrix which is a diangonal form of me - */ - Matrix diagonal() const { - Matrix ret(*this); - ret.diagonaled(); - return ret; - } - - /*! - * @brief Return a matrix which is an inverse matrix of \a (*this) - * - * If inverse matrix doesn't exist, it will return a invalid matrix - */ - Matrix inverse() const { - if (rows() != cols() || rows() == 0) return Matrix(); - Matrix tmp(rows(), cols() * 2, Entry(0)); - for (size_t r = 0, R = rows(); r < R; r++) { - for (size_t c = 0, C = cols(); c < C; c++) { - tmp.entry(r, c, entry(r, c)); - tmp.entry(r, c + cols(), (r == c ? Entry(1) : Entry(0))); - } - } - tmp.triangulared(); - for (ssize_t r = rows() - 1; r >= 0; r--) { - if (tmp(r, r) == Entry(0)) return Matrix(); - for (ssize_t r2 = r - 1; r2 >= 0; r2--) { - Entry rat(-tmp.entry(r2, r) / tmp.entry(r, r)); - for (size_t c = r, C = tmp.cols(); c < C; c++) { - tmp.entry(r2, c, tmp.entry(r2, c) + rat * tmp(r, c)); - } - } - Entry rat(tmp.entry(r, r)); - for (size_t c = cols(), C = tmp.cols(); c < C; c++) { - tmp.entry(r, c - cols(), tmp.entry(r, c) / rat); - } - } - tmp.size(cols(), rows(), Entry(0)); - return tmp; - } - - //! @brief let itself become itself's inverse matrix - Matrix& inversed() { - copyFrom(inverse()); - return *this; - } - - //! @brief return itself's transpose matrix - Matrix transpose() const { - Matrix ret(cols(), rows(), Entry(0)); - for (size_t r = 0, R = cols(); r < R; r++) - for (size_t c = 0, C = rows(); c < C; c++) - ret.entry(r, c, entry(c, r)); - return ret; - } - - //! @brief Let itself become itself's transpose matrix - Matrix& transposed() { - copyFrom(transpose()); - return *this; - } - - //! @brief return a matrix which is the triangular form of \a (*this) - Matrix triangular() const { - Matrix ret(*this); - ret.triangulared(); - return ret; - } - - //! @brief triangluar itself - Matrix& triangulared() { - for (size_t r = 0, c = 0, R = rows(), C = cols(); r < R && c < C; r++) { - ssize_t maxR; - for ( ; c < C; c++) { - maxR = -1; - for (size_t r2 = r; r2 < R; r2++) - if (maxR == -1 || tAbs(entry(r2, c)) > tAbs(entry(maxR, c))) - maxR = r2; - if (entry(maxR, c) != Entry(0)) break; - } - if (c >= C) break; - if (maxR != (ssize_t)r) { - for (size_t c2 = c; c2 < C; c2++) - std::swap(self()->entries_[self->index( r, c2)], - self()->entries_[self->index(maxR, c2)]); - } - for (size_t r2 = r + 1; r2 < R; r2++) { - Entry rati = -entry(r2, c) / entry(r, c); - entry(r2, c, Entry(0)); - for (size_t c2 = c + 1; c2 < C; c2++) - entry(r2, c2, entry(r2, c2) + entry(r, c2) * rati); - } - } - return *this; - } - - //! @brief same as \a copyFrom - Matrix& operator=(Matrix const& m) { - return copyFrom(m); - } - - //! @brief same as \a entry(r,c) - Entry operator()(size_t r, size_t c) const { - return entry(r, c); - } - - //! @brief same as \a entry(r,c,e) - Entry operator()(size_t r, size_t c, Entry const& e) { - return entry(r, c, e); - } - - //! @brief same as \a positive() - Matrix operator+() const { - return positive(); - } - - //! @brief same as \a negative() - Matrix operator-() const { - return negative(); - } - - //! @brief same as \a add(m) - Matrix operator+(Matrix const& m) const { - return add(m); - } - - //! @brief same as \a sub(m) - Matrix operator-(Matrix const& m) const { - return sub(m); - } - - //! @brief same as \a mul(m) - Matrix operator*(Matrix const& m) const { - return mul(m); - } - - //! @brief same as \a mul(m) - Matrix operator*(Entry const& s) const { - return mul(s); - } - - //! @brief same as \a div(s) - Matrix operator/(Entry const& s) const { - return div(s); - } -}; - -} // meow - -#endif // math_Matrix_H__ diff --git a/meowpp/math/Transformation.h b/meowpp/math/Transformation.h deleted file mode 100644 index 086cb03..0000000 --- a/meowpp/math/Transformation.h +++ /dev/null @@ -1,237 +0,0 @@ -#ifndef math_Transformation_H__ -#define math_Transformation_H__ - -#include "Matrix.h" -#include "../Self.h" - -#include -#include - -namespace meow { - -/*! - * @brief A base class for implementing kinds of transformations. - * - * We define that the input and output form of our transformations all be - * \b matrix . Some advance methods such as calculating jacobian matrix - * will require that the input form must be a vector. - * @author cat_leopard - */ -template -class Transformation { -private: - struct Myself { - size_t inputRows_; - size_t inputCols_; - size_t outputRows_; - size_t outputCols_; - size_t psize_; - - Myself(Myself const& b): - inputRows_(b.inputRows_), inputCols_(b.inputCols_), - outputRows_(b.outputRows_), outputCols_(b.outputCols_), - psize_(b.psize_) { - } - - Myself(size_t ir, size_t ic, size_t or_, size_t oc, size_t ps): - inputRows_(ir), inputCols_(ic), outputRows_(or_), outputCols_(oc), - psize_(ps) { - } - - ~Myself() { - } - }; - - Self const self; -protected: - /*! - * Construct and setup - * @param [in] inputRows number of rows of the input matrix. - * @param [in] inputCols number of columns of the input matrix. - * @param [in] outputRows number of rows of the output matrix. - * @param [in] outputCols number of columns of the output matrix. - * @param [in] psize number of parameters - */ - Transformation(size_t inputRows, size_t inputCols, - size_t outputRows, size_t outputCols, - size_t psize): - self(Myself(inputRows, inputCols, outputRows, outputCols, psize)) { - } - - /*! - * Construct and copy setings from another transformation class. - * @param [in] b Specify where to copy the informations. - */ - Transformation(Transformation const& b): - self(b.self, Self::COPY_FROM) { - } - - /*! - * @brief Copy from the specified one - * - * @param [in] b The specified one - * @return \c *this - */ - Transformation& copyFrom(Transformation const& b) { - self().copyFrom(b.self); - return *this; - } - - /*! - * @brief reference from the specified one - * - * @param [in] b The specified one - * @return \c *this - */ - Transformation& referenceFrom(Transformation const& b) { - self().referenceFrom(b.self); - return *this; - } -public: - /*! - * Destructor - */ - virtual ~Transformation() { - } - - /*! - * @brief Return the number of rows of the input matrix. - * - * @return Number of rows. - */ - size_t inputRows() const { - return self->inputRows_; - } - - /*! - * @brief Return the number of columns of the input matrix. - * - * @return Number of columns. - */ - size_t inputCols() const { - return self->inputCols_; - } - - /*! - * @brief Return the number of rows of the output matrix. - * - * @return Number of rows. - */ - size_t outputRows() const { - return self->outputRows_; - } - - /*! - * @brief Return the number of columns of the output matrix. - * - * @return Number of columns. - */ - size_t outputCols() const { - return self->outputCols_; - } - - /*! - * @brief Return the number of parameters. - * - * @return Number of parameters. - */ - size_t parameterSize() const { - return self->psize_; - } - - /*! - * @brief Get the \a i -th parameter. - * - * @param [in] i The index of the specified parameter. - * @note It's a pure virtual method. - */ - virtual Scalar parameter(size_t i) const = 0; - - /*! - * @brief Setup the \a i -th parameter. - * - * @param [in] i The index of the specified parameter. - * @param [in] s The new value to the specified parameter. - * @note It's a pure virtual method. - */ - virtual Scalar parameter(size_t i, Scalar const& s) = 0; - - /*! - * @brief Do transformate. - * - * @param [in] x The input matrix. - * @note It's a pure virtual method. - */ - virtual Matrix transformate(Matrix const& x) const = 0; - - /*! - * @brief Calculate the jacobian matrix (derivate by the input matrix) - * of the transformation. - * - * Consider the case of a non-differentiable - * transformation might be implemented, we return an empty matrix - * now instead of making it be a pure virtual method. - * @param [in] x The input matrix. - * @return An empty matrix. - */ - virtual Matrix jacobian(Matrix const& x) const { - return Matrix(); - } - - /*! - * @brief Calculate the jacobian matrix (derivate by the \a i -th parameter) - * of the transformation. - * - * Consider the case of a non-differentiable transformation might be - * implemented, we return an empty matrix now instead of making it be - * a pure virtual method. - * @param [in] x The input matrix. - * @param [in] i The index of the specified parameter. - * @return An empty matrix. - */ - virtual Matrix jacobian(Matrix const& x, size_t i) const { - return Matrix(); - } - - /*! - * @brief Return whether this transformation is inversable or not - * - * @return \c false - */ - virtual bool inversable() const { return false; } - - /*! - * @brief Do the inverse transformation - * - * @param [in] x The input matirx - * @return An empty matrix - */ - virtual Matrix transformateInv(Matrix const& x) const { - return Matrix(); - } - - /*! - * @brief Return the jacobian matrix of the inverse transformation - * - * @param [in] x The input matirx - * @return An empty matrix - */ - virtual Matrix jacobianInv(Matrix const& x) const { - return Matrix(); - } - - /*! - * @brief Return the jacobian matrix of the inverse transformation - * - * @param [in] x The input matirx - * @param [in] i The index of the specified parameter. - * @return An empty matrix - */ - virtual Matrix jacobianInv(Matrix const& x, size_t i) const { - return Matrix(); - } -}; - -} // meow - -#endif // math_Transformation_H__ diff --git a/meowpp/math/Transformations.h b/meowpp/math/Transformations.h deleted file mode 100644 index 99d6483..0000000 --- a/meowpp/math/Transformations.h +++ /dev/null @@ -1,550 +0,0 @@ -#ifndef math_Transformations_H__ -#define math_Transformations_H__ - -#include "Transformation.h" -#include "Matrix.h" -#include "utility.h" -#include "../Self.h" - -#include - -namespace meow { - -/*! - * @brief A ball projection is to project the given vector to a hyper-sphere - * - * Assume: - * - The dimension of a ball projection is \f$ N \f$ - * - The radius of the hyper-sphere is \f$ R \f$ - * . - * Then the transformation is like below: \n - * \f[ - * \left[ - * \begin{array}{c} - * x_1 \\ - * x_2 \\ - * x_3 \\ - * . \\ - * . \\ - * . \\ - * x_N \\ - * \end{array} - * \right] - * \stackrel{transformate}{\rightarrow} - * \left[ - * \begin{array}{c} - * \frac{x_1 \times R}{L} \\ - * \frac{x_2 \times R}{L} \\ - * \frac{x_3 \times R}{L} \\ - * . \\ - * . \\ - * . \\ - * \frac{x_N \times R}{L} \\ - * \end{array} - * \right] \\ - * \f] - * where \f$ L=\sqrt{x_1^2 + x_2^2 + x_3^2 + ... + x_N^2 } \f$ - * @author cat_leopard - */ -template -class BallProjection: public Transformation { -private: - struct Myself { - size_t dimension_; - Scalar radius_; - - Myself(size_t d): dimension_(1), radius_(1) { - } - - Myself(size_t d, Scalar const& r): dimension_(d), radius_(r) { - } - - Myself(Myself const& m): dimension_(m.dimension_), radius_(m.radius_) { - } - }; - - Self const self; -public: - /*! - * Constructor, copy settings from given BallProjection - * @param [in] b another ball projection class - */ - BallProjection(BallProjection const& b): Transformation(b), - self(b.self, Self::COPY_FROM) { - } - - /*! - * Constructor and setup, radius = 1 - * @param [in] d Dimension of the input/output vector - */ - BallProjection(size_t d): Transformation(d, 1, d, 1, 1), - self(Myself(d)) { - radius(1); - } - - /*! - * Constructor and setup - * @param [in] d Dimension of the input/output vector - * @param [in] r Radius of the hyper-sphere - */ - BallProjection(size_t d, Scalar const& r): Transformation(d,1,d,1,1), - self(Myself(d, r)) { - radius(r); - } - - /*! - * @brief Copy settings from another one - * @param [in] b Another one - * @return \c *this - */ - BallProjection& copyFrom(BallProjection const& b) { - Transformation::copyFrom(b); - copyFrom(b); - return *this; - } - - /*! - * @brief Reference settings from another one - * @param [in] b Another one - * @return \c *this - */ - BallProjection& referenceFrom(BallProjection const& b) { - Transformation::referenceFrom(b); - referenceFrom(b); - return *this; - } - - /*! - * @brief same as \c radius() - */ - Scalar parameter(size_t i) const { - return radius(); - } - - /*! - * @brief same as \c radius(s) - */ - Scalar parameter(size_t i, Scalar const& s) { - return radius(s); - } - - /*! - * @brief Return the value of the radius - */ - Scalar radius() const { - return self->radius_; - } - - /*! - * @brief Setup the radius - * - * @param [in] r New value of the radius - * @return New radius - */ - Scalar radius(Scalar const& r) { - self()->radius_ = r; - return radius(); - } - - /*! - * @brief Get the dimension of this projection - */ - size_t dimension() const { - return self->dimension_; - } - - - /*! - * @brief Project the input vector(s) onto the hyper-sphere and return it. - * - * If the number of columns of the input matrix is larger than 1, this - * method will think that you want to transform multiple vector once - * and the number of columns of the output matrix will be the same of - * the number of columns of the input one. - * - * @param [in] x The input matrix. - * @return The output matrix. - * @note Take into account that too much safty checking will lead to - * inefficient, this method will not checking whether the dimension - * of the input vector/matrix is right. So be sure the data is valid - * before you call this method. - */ - Matrix transformate(Matrix const& x) const { - Matrix ret(x); - for (size_t c = 0, C = ret.cols(); c < C; c++) { - Scalar sum(0); - for (size_t i = 0; i < self->dimension_; i++) { - sum = sum + squ(ret(i, c)); - } - Scalar len(sqrt(double(sum))); - for (size_t i = 0; i < self->dimension_; i++) { - ret(i, c, ret(i, c) * radius() / len); - } - } - return ret; - } - - /*! - * @brief Return the jacobian matrix (derivate by the input vector) - * of this projection. - * - * This method only allow a vector-like matrix be input. - * Assume: - * - The dimension of a ball projection is \f$ N \f$ - * - The length of the input vector is \f$ L=\sqrt{x_1^2+x_2^2+...+x_N^2} \f$ - * - The radius of the hyper-sphere is \f$ R \f$ - * . - * Then the jacobian matrix is like below: \n - * \f[ - * \frac{R}{L^3} \times \left[ - * \begin{array}{ccccc} - * L^2-x_1^2 & -x_1x_2 & -x_1x_3 & ... & -x_1x_N \\ - * -x_2x_1 & L^2-x_2^2 & -x_2x_3 & ... & -x_2x_N \\ - * -x_3x_1 & -x_3x_2 & L^2-x_3^2 & ... & -x_3x_N \\ - * . & . & . & & . \\ - * . & . & . & & . \\ - * . & . & . & & . \\ - * -x_Nx_1 & -x_Nx_2 & -x_Nx_3 & ... & L^2-x_N^2 \\ - * \end{array} - * \right] - * \f] - * - * @param [in] x The input matrix. - * @return The output matrix. - */ - Matrix jacobian(Matrix const& x) const { - Scalar sum(0); - for(size_t i = 0, I = dimension(); i < I; ++i) - sum = sum + squ(x(i, 0)); - Scalar len(sqrt(double(sum))); - Matrix ret(dimension(), dimension(), Scalar(0.0)); - for(size_t i = 0, I = dimension(); i < I; ++i) - for(size_t j = 0; j < I; ++j) - if (i == j) { - ret(i, j, radius() * (squ(len) - squ(x(i, 0))) / cub(len)); - } - else { - ret(i, j, radius() * (-x(i, 0) * x(j, 0) / cub(len))); - } - return ret; - } - - /*! - * @brief Return the jacobian matrix (derivate by radius) of this projection. - * - * This method only allow a vector-like matrix be input. - * Assume: - * - The dimension of a ball projection is \f$ N \f$ - * - The length of the input vector is \f$ L=\sqrt{x_1^2+x_2^2+...+x_N^2} \f$ - * - The radius of the hyper-sphere is \f$ R \f$ - * . - * Then the jacobian matrix is like below: \n - * \f[ - * R \times \left[ - * \begin{array}{c} - * \frac{x_1}{L} \\ - * \frac{x_2}{L} \\ - * \frac{x_3}{L} \\ - * . \\ - * . \\ - * . \\ - * \frac{x_N}{L} \\ - * \end{array} - * \right] - * \f] - * - * @param [in] x The input matrix. - * @param [in] i Useless parameter - * @return The output matrix. - */ - Matrix jacobian(Matrix const& x, size_t i) const { - Matrix ret(dimension(), 1, Scalar(0.0)); - Scalar sum(0); - for(size_t i = 0, I = dimension(); i < I; i++) { - sum = sum + squ(x(i, 0)); - } - return ret / Scalar(sqrt(double(sum))); - } - - /*! - * @brief Same as \c copyFrom(b) - */ - BallProjection& operator=(BallProjection const& b) { - return copyFrom(b); - } - - /*! - * @brief Same as \c transformate(v) - */ - Matrix operator()(Matrix const& v) const { - return transformate(v); - } -}; - - -/*! - * @brief A \b photo \b projection is a kind of transformation that project - * point/vector to a flat \b photo - * - * Assume: - * - The dimension of a photo projection is \f$ N \f$ - * - The length of the input vector is \f$ L \f$ - * - The focal length is \f$ f \f$ - * . - * Then transformation is like below: \n - * \f[ - * \left[ - * \begin{array}{c} - * x_1 \\ - * x_2 \\ - * x_3 \\ - * . \\ - * . \\ - * . \\ - * x_N \\ - * \end{array} - * \right] - * \stackrel{transformate}{\rightarrow} - * \left[ - * \begin{array}{c} - * \frac{-x_1 \times f}{x_N} \\ - * \frac{-x_2 \times f}{x_N} \\ - * \frac{-x_3 \times f}{x_N} \\ - * . \\ - * . \\ - * . \\ - * -f \\ - * \end{array} - * \right] \\ - * \f] - * i.e. projecte the vector onto the plane \f$ x_N = -f \f$. - * - * @author cat_leopard - */ -template -class PhotoProjection: public Transformation { -private: - struct Myself { - Scalar focal_; - size_t dimension_; - - Myself() { - } - - Myself(size_t d, Scalar f): focal_(f), dimension_(d) { - } - - Myself(Myself const& b): focal_(b.focal_), dimension_(b.dimension_) { - } - - ~Myself() { - } - }; - - Self const self; -public: - /*! - * Constructor, focal = 1 - */ - PhotoProjection(size_t dimension): - Transformation(dimension, 1, dimension, 1, 1), - self(Myself(dimension, 1)) { - } - - /*! - * Constructor - */ - PhotoProjection(size_t dimension, Scalar const& f): - Transformation(dimension, 1, dimension, 1, 1), - self(Myself(dimension, f)) { - } - - /*! - * Constructor, copy settings from another PhotoProjection. - */ - PhotoProjection(PhotoProjection const& p): Transformation(p), - self(p.self, Self::COPY_FROM) { - } - - /*! - * Copy settings from another one - * @param [in] b another one - * @return \c *this - */ - PhotoProjection& copyFrom(PhotoProjection const& b) { - Transformation::copyFrom(b); - self().copyFrom(b.self); - return *this; - } - - /*! - * Reference settings from another one - * @param [in] b another one - * @return \c *this - */ - PhotoProjection& referenceFrom(PhotoProjection const& b) { - Transformation::referenceFrom(b); - self().referenceFrom(b.self); - return *this; - } - - /*! - * @brief Same as \c focal() - */ - Scalar parameter(size_t i) const { - return focal(); - } - - /*! - * @brief Same as \c focal(s) - */ - Scalar parameter(size_t i, Scalar const& s){ - return focal(s); - } - - /*! - * @brief Get the focal length - * @return Focal length - */ - Scalar focal() const { - return self->focal_; - } - - /*! - * @brief Set the focal length - * - * @param [in] f New focal length - * @return New focal length - */ - Scalar focal(Scalar const& f){ - self()->focal_ = f; - return focal(); - } - - /*! - * @brief Get the dimension of this projection - */ - size_t dimension() const { - return self->dimension_; - } - - /*! - * @brief Project the input vector(s) onto the plane - * - * The equation of the plane is \f$ x_N = -f \f$, where the \f$ N \f$ - * is the dimension of this projection and f is the focal length. \n - * If the number of columns of the input matrix is larger than 1, this - * method will think that you want to transform multiple vector once - * and the number of columns of the output matrix will be the same of - * the number of columns of the input one. - * - * @param [in] x The input matrix. - * @return The output matrix. - * @note Take into account that too much safty checking will lead to - * inefficient, this method will not checking whether the dimension - * of the input vector/matrix is right. So be sure the data is valid - * before you call this method. - */ - Matrix transformate(Matrix const& x) const { - Matrix ret(x); - for (size_t c = 0, C = ret.cols(); c < C; c++) { - for (size_t i = 0, I = dimension(); i < I; ++i) { - ret(i, c, -ret(i, c) * focal() / ret(I - 1, c)); - } - } - return ret; - } - - /*! - * @brief Return the jacobian matrix (derivate by the input vector) - * of this projection. - * - * This method only allow a vector-like matrix be input. - * Assume: - * - The dimension of this projection is \f$ N \f$ - * - The length of the input vector is \f$ L=\sqrt{x_1^2+x_2^2+...+x_N^2} \f$ - * - The focal length of this projection is \f$ f \f$ - * . - * Then the jacobian matrix is like below: \n - * \f[ - * f \times - * \left[ - * \begin{array}{ccccc} - * \frac{-1}{x_N} & 0 & 0 & ... & \frac{1}{x_N^2} \\ - * 0 & \frac{-1}{x_N} & 0 & ... & \frac{1}{x_N^2} \\ - * 0 & 0 & \frac{-1}{x_N} & ... & \frac{1}{x_N^2} \\ - * . & . & . & & . \\ - * . & . & . & & . \\ - * . & . & . & & . \\ - * 0 & 0 & 0 & ... & 0 \\ - * \end{array} - * \right] - * \f] - * - * @param [in] x The input matrix. - * @return The output matrix. - */ - Matrix jacobian(Matrix const& x) const{ - Matrix ret(dimension(), dimension(), Scalar(0.0)); - for(ssize_t i = 0, I = (ssize_t)dimension() - 1; i < I; i++){ - ret(i, i, -focal() / x(I, 0) ); - ret(i, dimension() - 1, focal() / squ(x(I, 0))); - } - return ret; - } - - /*! - * @brief Return the jacobian matrix (derivate by the focus length) - * of this projection. - * - * This method only allow a vector-like matrix be input. - * Assume: - * - The dimension of this projection is \f$ N \f$ - * - The length of the input vector is \f$ L=\sqrt{x_1^2+x_2^2+...+x_N^2} \f$ - * - The focal length of this projection is \f$ f \f$ - * . - * Then the jacobian matrix is like below: \n - * \f[ - * \left[ - * \begin{array}{c} - * \frac{-x_1}{x_N} \\ - * \frac{-x_2}{x_N} \\ - * \frac{-x_3}{x_N} \\ - * . \\ - * . \\ - * . \\ - * -1 \\ - * \end{array} - * \right] - * \f] - * - * @param [in] x The input matrix. - * @param [in] i Useless parameter - * @return The output matrix. - */ - Matrix jacobian(Matrix const& x, size_t i) const{ - Matrix ret(dimension(), 1, Scalar(0.0)); - for(size_t i = 0, I = dimension(); i < I; ++i) { - ret(i, 0, -x(i, 0) / x(I - 1, 0)); - } - return ret; - } - - /*! - * @brief Same as \c copyFrom(b) - */ - PhotoProjection& operator=(PhotoProjection const& b) { - return copyFrom(b); - } - - /*! - * @brief Same as \c transformate(v) - */ - Matrix operator()(Matrix const& v) const { - return transformate(v); - } -}; - -} // meow - -#endif // Transformations_H__ diff --git a/meowpp/math/Vector.h b/meowpp/math/Vector.h deleted file mode 100644 index f72b043..0000000 --- a/meowpp/math/Vector.h +++ /dev/null @@ -1,267 +0,0 @@ -#ifndef math_Vector_H__ -#define math_Vector_H__ - -#include "../Self.h" -#include "Matrix.h" - -#include - -#include - -namespace meow { - -/*! - * @brief \b vector - * - * @author cat_leopard - */ -template -class Vector { -public: - typedef typename Matrix::EntryRefK ScalarRefK; - typedef typename Matrix::EntryRef ScalarRef ; -private: - Matrix matrix_; -public: - /*! - * @brief constructor - * - * With \b dimension=0, which means \b invalid. - */ - Vector() { - } - - /*! - * @brief constructor - * - * Copy from another vector - * - * @param [in] v another vector - */ - Vector(Vector const& v): matrix_(v.matrix_) { - } - - /*! - * @brief constructor - * - * From matrix's first column - * - * @param [in] m matrix - */ - Vector(Matrix const& m): matrix_(m.col(0)) { - } - - /*! - * @brief constructor - * - * Copy from another std::vector - * - * @param [in] v vector - */ - Vector(std::vector const& v): matrix_(v.size(), 1, Scalar(0)) { - for (size_t i = 0, I = v.size(); i < I; i++) { - matrix_.entry(i, 0, v[i]); - } - } - - /*! - * @brief constructor - * - * setup dimension and inital value - * - * @param [in] d dimension - * @param [in] e inital value - */ - Vector(size_t d, Scalar const& e): matrix_(d, 1, e) { - } - - //! @brief destructor - ~Vector() { - } - - //! @brief copy from ... - Vector& copyFrom(Vector const& v) { - matrix_.copyFrom(v.matrix_); - return *this; - } - - //! @brief reference from ... - Vector& referenceFrom(Vector const& v) { - matrix_.referenceFrom(v.matrix_); - return *this; - } - - //! @brief Return a \a dimension x 1 matrix form of it - Matrix matrix() const { - return matrix_; - } - - //! @brief return dimension - size_t dimension() const { - return matrix_.rows(); - } - - /*! - * @brief resize the dimension - * - * @param [in] d new dimension - * @param [in] s inital entry - * @return new dimension - */ - size_t dimension(size_t d, Scalar const& s) { - matrix_.rows(d, s); - return dimension(); - } - - /*! - * @brief Return whether \c dimension>0 is true or not - * @return \c true/false - */ - bool valid() const { - return (dimension() > 0); - } - - //! @brief return \a i -th scalar - Scalar scalar(size_t i) const { - return matrix_.entry(i, 0); - } - - /*! - * @brief change \a i -th scalar - * - * @param [in] i i-th - * @param [in] s new value - */ - Scalar scalar(size_t i, Scalar const& s) { - matrix_.entry(i, 0, s); - return scalar(i); - } - - //! @brief return \a i -th scalar with non-constant type - ScalarRef scalarGet(size_t i) { - return matrix_.entryGet(i); - } - - /*! - * @brief change \a i -th to \a j -th scalars - * - * @param [in] i i-th - * @param [in] j j-th - * @param [in] s new value - */ - void scalars(size_t i, size_t j, Scalar const& s) { - for (size_t it = i; it <= j; ++it) { - matrix_.entry(it, 0, s); - } - } - - //! @brief subvector form i-th to j-th - Vector subVector(size_t i, size_t j) { - return Vector(matrix_.subMatrix(i, 0, j, 0)); - } - - //! @brief return +\a (*this) - Vector positive() const { - return *this; - } - - //! @brief return -\a (*this) - Vector negative() const { - return Vector(matrix_.negative()); - } - - //! @brief return \a (*this)+v - Vector add(Vector const& v) const { - return Vector(matrix_.add(v.matrix_)); - } - - //! @brief return \a (*this)-v - Vector sub(Vector const& v) const { - return Vector(matrix_.sub(v.matrix_)); - } - - //! @brief return \a (*this)*s , where s is a scalar - Vector mul(Scalar const& s) const { - return Vector(matrix_.mul(s)); - } - - //! @brief return \a (*this)/s , where s is a scalar - Vector div(Scalar const& s) const { - return Vector(matrix_.div(s)); - } - - //! @brief dot - Scalar dot(Vector const& v) const { - return matrix_.transpose().mul(v.matrix_).entry(0, 0); - } - - //! @brief sqrt of \a length2 - Scalar length() const { - return Scalar(sqrt((double)length2())); - } - - //! @brief same as \a (*this).dot(*this) - Scalar length2() const { - return dot(*this); - } - - //! @brief return a normalize form of itself - Vector normalize() const { - return div(length()); - } - - //! @brief Let itself be normalize form - Vector& normalized() { - copyFrom(normalize()); - return *this; - } - - //! @brief same as copyFrom - Vector& operator=(Vector const& v) { - return copyFrom(v); - } - - //! @brief same as entry(i) - Scalar operator()(size_t i) const { - return scalar(i); - } - - //! @brief same as positive() - Vector operator+() const { - return positive(); - } - - //! @brief same as negative() - Vector operator-() const { - return negative(); - } - - //! @brief same as add(v) - Vector operator+(Vector const& v) const { - return add(v); - } - - //! @brief same as sub(v) - Vector operator-(Vector const& v) const { - return sub(v); - } - - //! @brief same as dot(v) - Scalar operator*(Vector const& v) const { - return dot(v); - } - - //! @brief same as mul(s) - Vector operator*(Scalar const& s) const { - return mul(s); - } - - //! @brief same as div(s) - Vector operator/(Scalar const& s) const { - return div(s); - } -}; - -} // meow - -#endif // math_Vector_H__ diff --git a/meowpp/math/methods.h b/meowpp/math/methods.h deleted file mode 100644 index 06125b5..0000000 --- a/meowpp/math/methods.h +++ /dev/null @@ -1,230 +0,0 @@ -#ifndef math_methods_H__ -#define math_methods_H__ - -#include "Matrix.h" -#include "Vector.h" -#include "utility.h" - -#include -#include - -namespace meow { - -/*! - * @brief Run the \b RANSAC method to approach the best solution. - * - * \b RANdom \b SAmple \b Consensus is an iterative method to estimate - * parameters of a mathematical model from a set of observed data which - * contains \c outliers. \n - * Each iterator it will choose a subset of elements, the smallest set which can - * form a valid parameters, from the data set. And then calculate how many - * elements in the whole data set is inliers. After iterator much times, - * we just say the best solution is the parameters that has the much - * inliers elements in whole iterators. - * - * Assume: - * - We need at least \f$ N \f$ element to form a valid parameters. - * - The probability of choosing a right element from data set each time is - * \f$ p_0 \f$. - * - We want the probability of our solution actually being the best solution - * be \f$ P \f$. - * - We need to iterator \f$ M \f$ times. - * . - * Then we can estimate the number of iterations \f$ M \f$ : - * \f[ - * \begin{aligned} - * & (1 - p_0^N)^M \leq(1 - P) \\ - * \Rightarrow & M \log(1 - p_0^N) \leq \log(1 - P) \\ - * \Rightarrow & M \geq \frac{\log(1 - p)}{\log(1 - p_0^N)},~~ - * \because (1-p_0^N<1 \Rightarrow \log(1-p_0^N)<0) - * \end{aligned} - * \f] - * - * So in this function we choose - * \f$ M = \lceil \frac{\log(1 - P)}{\log(1 - p_0^N)} \rceil \f$ - * - * @param [in] data The whole data sett - * @param [in] w Weight function to give a floating number for a given - * parameters which means how best this solution is. Negitave - * number means invalid parameters. - * @param [in] N \f$ N \f$, defined above - * @param [in] p0 \f$ p_0 \f$, defined above - * @param [in] P \f$ P \f$, defined above - * @return solution. - * - * @author cat_leopard - */ -template -inline std::vector ransac(std::vector const& data, - WeightingClass const& w, - size_t N, - double p0, double P) { - if (data.size() < N) { - return std::vector(); - } - double ww = -1.0; - std::vector ret; - for (double count = ceil(log(1.0 - P) / log(1.0 - pow(p0, N))); - count > 0.0; count -= 1.0) { - std::vector sample; - std::vector index(N); - for (size_t i = 0; i < N; i++) { - for (bool ok = false; !ok; ) { - index[i] = rand() % data.size(); - ok = true; - for (size_t j = 0; ok && j < i; j++) - if (index[i] == index[j]) - ok = false; - } - sample.push_back(data[index[i]]); - } - double w_now = w(sample, data); - if (w_now < 0) { - count += 0.5; - continue; - } - if (ww < w_now) { - ret = sample; - ww = w_now; - } - } - return ret; -} - - -/* - * @brief Run the \b Levenberg-Marquardt method to solve a non-linear - * least squares problem. - * - * Assume: - * - The function we want to optimize is - * \f$ F: \mathbb{R} ^N \mapsto \mathbb{R}^M \f$ - * - We want to find the best solution \f$ v \f$ such that - * \f$ F(v)^T F(v) = 0\f$. But there is a gived threshold - * \f$ \epsilon \f$, we can just find a \f$ v \f$ such that - * \f$ F(v)^T F(v) < \epsilon \f$, which is mush easier. - * - User gived a initiial vector \f$ v_0 \f$ - * . - * Then we just iteratilly find \f$ v_1, v_2, v_3, v_4... \f$ until a - * vector \f$ v_k \f$ satisified that \f$ F(v_k)^TF(v_k)<\epsilon \f$ . - * And each iterator we have: - * \f[ - * v_{i+1} = v_i + (J(v_i)^TJ(v_i)+\lambda I_{N\times N})^{-1} J(v_i)^T F(v_i) - * \f] - * Where \f$ J(v) \f$ is a jacobian matrix defined below: - * \f[ - * J(v) = \frac{d}{dv}F(v) = - * \left[ \begin{array}{ccccc} - * \frac{\partial F_1(v)}{\partial v_1} & - * \frac{\partial F_1(v)}{\partial v_2} & - * \frac{\partial F_1(v)}{\partial v_3} & - * ... & - * \frac{\partial F_1(v)}{\partial v_N} \\ - * \frac{\partial F_2(v)}{\partial v_1} & - * \frac{\partial F_2(v)}{\partial v_2} & - * \frac{\partial F_2(v)}{\partial v_3} & - * ... & - * \frac{\partial F_2(v)}{\partial v_N} \\ - * \frac{\partial F_3(v)}{\partial v_1} & - * \frac{\partial F_3(v)}{\partial v_2} & - * \frac{\partial F_3(v)}{\partial v_3} & - * ... & - * \frac{\partial F_3(v)}{\partial v_N} \\ - * . & . & . & & . \\ - * . & . & . & & . \\ - * . & . & . & & . \\ - * \frac{\partial F_M(v)}{\partial v_1} & - * \frac{\partial F_M(v)}{\partial v_2} & - * \frac{\partial F_M(v)}{\partial v_3} & - * ... & - * \frac{\partial F_M(v)}{\partial v_N} \\ - * \end{array} \right] - * \f] - * And \f$ \lambda \f$ is a magic number.... - * @param [in] func \f$ F \f$, a function(class with \c operator() ) - * which input a vector and the output the squares errors. - * @param [in] jaco \f$ J \f$, a function which input a vector - * and then output \b func derivate by the vector - * @param [in] iden \f$ \lambda I_{N \times N} \f$, defined above - * @param [in] init \f$ v_0 \f$Initial vector - * @param [in] stop A function return a boolean which means the error is - * acceptable or not, so \f[ - * S_{top}(v) = \begin{cases} - * true & if~F(v)<\epsilon \\ - * false & else - * \end{cases} - * \f] - * @param [in] counter To prevent infinit loop. - * @return a vector which means the best solution this function found. - * - * @author cat_leopard - */ -template -inline Vector levenbergMarquardt(Function const& f, - Vector const& init, - int counter = -1) { - Vector ans(init), residure_v; - for ( ; counter != 0 && !f.accept(residure_v = f.residure(ans)); --counter) { - Matrix m_j (f.jacobian(ans)); - Matrix m_jt(m_j.transpose()); - Matrix m(m_j * m_jt), M; - for (int i = 1; M.valid() == false; i++) { - M = (m + f.diagonal(ans, i)).inverse(); - } - ans = ans - M * m_jt * residure_v; - } - return ans; -} - -// residure -// jacobian -// identity -template -inline Vector levenbergMarquardtTraining(Function & f, - Vector const& init, - Scalar const& init_mu, - Scalar const& mu_pow, - Scalar const& er_max, - int retry_number, - int counter) { - if (retry_number == 0) retry_number = 1; - Vector ans_now(init), rv_now(f.residure(ans_now)); - Vector ans_nxt , rv_nxt; - Scalar er_now(rv_now.length2()); - Scalar er_nxt; - Vector ans_best(ans_now); - Scalar er_best ( er_now); - Matrix m_ja, m_jt, m, iden(f.identity()); - Scalar mu(init_mu); - for ( ; counter != 0 && er_now > er_max; --counter) { - m_ja = f.jacobian(); - m_jt = m_ja.transpose(); - m = m_jt * m_ja; - bool good = false; - for (int i = 0; i != retry_number; ++i, mu = mu * mu_pow) { - ans_nxt = ans_now + (m + iden * mu).inverse() * m_jt * rv_now.matrix(); - rv_nxt = f.residure(ans_nxt); - er_nxt = rv_nxt.length2(); - if (er_nxt <= er_now) { - good = true; - break; - } - } - if (good) { - mu = mu / mu_pow; - } - mu = inRange(0.0000001, 100.0, mu); - ans_now = ans_nxt; - rv_now = rv_nxt; - er_now = er_nxt; - if (er_now < er_best) { - ans_best = ans_now; - er_best = er_now; - } - } - return ans_best; -} - -} // meow - -#endif // math_methods_H__ diff --git a/meowpp/math/utility.h b/meowpp/math/utility.h deleted file mode 100644 index 73efabb..0000000 --- a/meowpp/math/utility.h +++ /dev/null @@ -1,157 +0,0 @@ -#ifndef math_utility_H__ -#define math_utility_H__ - -#include -#include -#include -#include - -namespace meow { - -//! 圓周率... -static const double PI = 3.14159265358979323846264338327950288; - -/*! - * @brief 將角度調整於0~2PI - */ -template -inline T circle(T x) { - while (x < 0) x += 2.0 * PI; - while (2.0 * PI <= x) x -= 2.0 * PI; - return x; -} - -/*! - * @brief 如果abs(輸入的數值) < eps, 則回傳0, 否則回傳輸入的數值 - */ -template -inline T noEPS(T value, T eps = 1e-9) { - T epsp((eps < T(0)) ? -eps : eps); - return ((value < -epsp || value > epsp) ? value : T(0)); -} - -/*! - * @brief \c (value-lower)/(upper-lower) - */ -template -inline T normalize(T lower, T upper, T value) { - return (value - lower) / (upper - lower); -} - -/*! - * @brief \c (lower+_ratio*(upper-lower)) - */ -template -inline T denormalize(T lower, T upper, T _ratio) { - return lower + _ratio * (upper - lower); -} - -/*! - * @brief \c denormalize(l2,u2,normalize(l1,u1,m1)) - */ -template -inline T ratioMapping(T l1, T u1, T m1, T l2, T u2) { - return denormalize(l2, u2, normalize(l1, u1, m1)); -} - -/*! - * @brief \c std::min(mx,std::max(mn,v)) - */ -template -inline T inRange(T const& mn, T const& mx, T const& v) { - return std::min(mx, std::max(mn, v)); -} - -/*! - * @brief (mn <= x && x <= mx) - */ -template -inline T isInRange(T const& mn, T const& mx, T const& x) { - return (mn <= x && x <= mx); -} - -/*! - * @brief \c x*x - */ -template -inline T squ(T const& x) { - return x * x; -} - -/*! - * @brief \c x*x*x - */ -template -inline T cub(T const& x) { - return x * x * x; -} - -/*! - * @brief 只將 \c sigs 個標準差以內的數據拿來取平均 - */ -template -inline double average(T const& beg, T const& end, double sigs) { - int N = 0; - double av = 0; - for (T it = beg; it != end; ++it, ++N) { - av += *it; - } - av /= N; - double sig = 0; - for (T it = beg; it != end; ++it) { - sig += (*it - av) * (*it - av); - } - sig = sqrt(sig / N); - double lower = av - sig * sigs, upper = av + sig * sigs; - double ret = 0, retn = 0; - for (T it = beg; it != end; ++it) { - if (lower <= *it && *it <= upper) { - ret += *it; - retn++; - } - } - return ret / retn; -} - -/*! - * @brief 只將 \c sigs 個標準差以內的數據拿來取平均, 不過這次用 \c p 來加權平均 - */ -template -inline double average(T const& beg, T const& end, T const& p, double sigs) { - int N = 0; - double ps = 0; - for (T it = beg, ip = p; it != end; ++it, ++N, ++ip) { - ps += *ip; - } - double av = 0; - for (T it = beg, ip = p; it != end; ++it, ++ip) { - av += *it * *ip / ps; - } - double sig = 0; - for (T it = beg, ip = p; it != end; ++it, ++ip) { - sig += *ip / ps * (*it - av) * (*it - av); - } - sig = sqrt(sig); - double lower = av - sig * sigs, upper = av + sig * sigs; - double ret = 0, retn = 0; - for (T it = beg, ip = p; it != end; ++it, ++ip) { - if (lower <= *it && *it <= upper) { - ret += *it * *ip; - retn += *ip; - } - } - if (retn <= 1e-10) return av; - return ret / retn; -} - -/*! - * @brief 就只是個取絕對值 - */ -template -inline T tAbs(T const& t) { - return (t < 0 ? -t : t); -} - -} // meow - -#endif // math_utility_H__ diff --git a/meowpp/oo/!readme.asciidoc b/meowpp/oo/!readme.asciidoc deleted file mode 100644 index 2e91ca5..0000000 --- a/meowpp/oo/!readme.asciidoc +++ /dev/null @@ -1,32 +0,0 @@ - -物件相關 - -===== ObjBase.h - -.Classes -* `meow::ObjBase` - -===== ObjTypes.h - -.Classes -* `meow::ObjType` -* `meow::ObjInt` -* `meow::ObjSizeT` -* `meow::ObjDouble` -* `meow::ObjString` - -===== ObjArray.h - -.Classes -* `meow::ObjArray` - -===== ObjDictionary.h - -.Classes -* `meow::ObjDictionary` - -===== ObjSelector.h - -.Classes -* `meow::ObjSelector` - diff --git a/meowpp/oo/ObjArray.h b/meowpp/oo/ObjArray.h deleted file mode 100644 index 804f65f..0000000 --- a/meowpp/oo/ObjArray.h +++ /dev/null @@ -1,168 +0,0 @@ -#ifndef oo_ObjArray_H__ -#define oo_ObjArray_H__ - -#include "ObjBase.h" - -#include "../Self.h" - -#include -#include -#include - -#include -#include - -namespace meow { - -/*! - * @brief 純粹把 \c std::vector 包起來, 變成繼承自 ObjBase - * - * @author cathook - */ -template -class ObjArray: public ObjBase { -private: - struct Myself { - std::vector array_; - - Myself() { - } - - Myself(Myself const& b): array_(b.array_) { - } - - Myself(size_t sz, T const& e): array_(sz, e) { - } - - ~Myself() { - } - }; - Self const self; -public: - ObjArray(): self() { - } - - ObjArray(ObjArray const& a): self(a.self, Self::COPY_FROM) { - } - - ObjArray(std::vector const& a): self(a) { - } - - ObjArray(size_t sz, T const& e): self(Myself(sz, e)) { - } - - ~ObjArray() { - } - - ObjArray& copyFrom(ObjArray const& a) { - self().copyFrom(a.self); - return *this; - } - - ObjArray& referenceFrom(ObjArray const& a) { - self().referenceFrom(a.self); - return *this; - } - - size_t size() const { - return self->array_.size(); - } - bool empty() const { - return self->array_.empty(); - } - - size_t size(size_t res, T const& i) { - self()->array_.resize(res, i); - return size(); - } - - size_t size(size_t res) { - self()->array_.resize(res); - return size(); - } - - void clear() { - self()->array_.clear(); - } - - T entry(size_t i) const { - return self->array_[i]; - } - - T entry(size_t i, T const& e) { - self()->array_[i] = e; - return entry(i); - } - - T putBack(T const& e) { - self()->array_.push_back(e); - return entry(size() - 1); - } - - bool popBack() { - if (empty()) return false; - self()->array_.pop_back(); - return true; - } - - ObjArray& operator=(ObjArray const& a) { - return copyFrom(a); - } - - T operator[](size_t i) const { - return self->array_[i]; - } - - std::vector::reference operator[](size_t i) { - return self()->array_[i]; - } - - bool write(FILE* f, bool bin, unsigned int fg) const { - size_t sz = size(); - if (bin) { - if (fwrite(&sz, sizeof(size_t), 1, f) < 1) return false; - } - else { - if (fprintf(f, "%lu\n", sz) < 1) return false; - } - for (size_t i = 0; i < sz; i++) { - if (self->array_[i].write(f, bin, fg) == false) return false; - } - return true; - } - - bool read(FILE* f, bool bin, unsigned int fg) { - size_t sz; - if (bin) { - if (fread(&sz, sizeof(size_t), 1, f) < 1) return false; - } - else { - if (fscanf(f, "%lu\n", &sz) < 1) return false; - } - size(sz); - for (size_t i = 0; i < sz; i++) { - if (self()->array_[i].read(f, bin, fg) == false) return false; - } - return true; - } - - ObjBase* create() const { - return new ObjArray(); - } - - ObjBase* copyFrom(ObjBase const* b) { - return &(copyFrom(*(ObjArray const*)b)); - } - - char const* ctype() const { - return typeid(*this).name(); - } - - std::string type() const { - return std::string(ctype()); - } -}; - -} // meow - -#endif // oo_ObjArray_H__ diff --git a/meowpp/oo/ObjBase.h b/meowpp/oo/ObjBase.h deleted file mode 100644 index 253afb6..0000000 --- a/meowpp/oo/ObjBase.h +++ /dev/null @@ -1,99 +0,0 @@ -#ifndef oo_ObjBase_H__ -#define oo_ObjBase_H__ - -#include -#include -#include - -namespace meow { - -/*! - * @brief 一切物件的Base, 並要求每個物件都要有read, write, create, ... 等功能 - * - * @author cathook - */ -class ObjBase { -protected: - - /*! - * @brief Constructor with doing nothing - */ - ObjBase() { } -public: - virtual ~ObjBase() { } - - /*! - * @brief 將物件寫入檔案, 預設implement為直接回傳 \c false - * - * @param [in] f 檔案 - * @param [in] bin 是否為binary模式 - * @param [in] fg 使用者自訂的argument - * @return 成功或失敗 - */ - virtual bool write(FILE* f, bool bin, unsigned int fg) const { - return false; - } - - /*! - * @brief 將物件從檔案讀出, 預設implement為直接回傳 \c false - * - * @param [in] f 檔案 - * @param [in] bin 是否為binary模式 - * @param [in] fg 使用者自訂的argument - * @return 成功或失敗 - */ - virtual bool read(FILE* f, bool bin, unsigned int fg) { - return false; - } - - /*! - * @brief 回傳一個new出來的物件, 預設implement為直接回傳 \c NULL - */ - virtual ObjBase* create() const { - return NULL; - } - - /*! - * @brief 複製, 預設使用operator= - * - * @param [in] b 資料來源 - * @return \c this - */ - virtual ObjBase* copyFrom(ObjBase const* b) { - (*this) = (*b); - return this; - } - - /*! - * @brief 用C-style string回傳這個class的type name - */ - virtual char const* ctype() const { - return typeid(*this).name(); - } - - /*! - * @brief 用std::string回傳這個class的type name - */ - virtual std::string type() const { - return std::string(ctype()); - } - - /*! - * @brief 用C-style string回傳base的type name - */ - static char const* ctypeBase() { - return typeid(ObjBase).name(); - } - - /*! - * @brief 用std::string回傳base的type name - */ - static std::string typeBase() { - static std::string s(ctypeBase()); - return s; - } -}; - -} // meow - -#endif // oo_ObjBase_H__ diff --git a/meowpp/oo/ObjDictionary.h b/meowpp/oo/ObjDictionary.h deleted file mode 100644 index f43be58..0000000 --- a/meowpp/oo/ObjDictionary.h +++ /dev/null @@ -1,167 +0,0 @@ -#ifndef oo_ObjDictionary_H__ -#define oo_ObjDictionary_H__ - -#include "ObjBase.h" - -#include "../Self.h" - -#include -#include -#include - -#include -#include - -namespace meow { - -/*! - * @brief 純粹把 \c std::map 包起來, 變成繼承自 ObjBase - * - * @author cathook - */ -template -class ObjDictionary: public ObjBase { -private: - struct Myself { - std::map dictionary_; - - Myself() { - } - - Myself(Myself const& b): dictionary_(b.dictionary_) { - } - - ~Myself() { - } - }; - - Self const self; -public: - ObjDictionary(): self() { - } - - ObjDictionary(ObjDictionary const& d): self(d.self, Self::COPY_FROM) { - self.copyFrom(b.self); - } - - ObjDictionary(std::map const& d): self(Myself(d)) { - } - - ~ObjDictionary() { - } - - ObjDictionary& copyFrom(ObjDictionary const& d) { - self().copyFrom(d.self); - return *this; - } - - ObjDictionary& referenceFrom(ObjDictionary const& d) { - self().referenceFrom(d.self); - return *this; - } - - size_t size() const { - return self->dictionary_.size(); - } - - bool empty() const { - return self->dictionary_.empty(); - } - - void clear() { - self()->dictionary_.clear(); - } - - std::map::const_iterator first() const { - return self()->dictionary_.begin(); - } - - std::map::iterator first() { - return self()->dictionary_.begin(); - } - - std::map::const_iterator end() const { - return self()->dictionary_.end(); // OAO!!! - } - - std::map::iterator end() { - return self()->dictionary_.end(); - } - - std::map::const_iterator find(Key const& k) const { - return self()->dictionary_.find(k); // OAO!!! - } - - std::map::iterator find(Key const& k) { - return self()->dictionary_.find(k); - } - - bool exist(Key const& k) const { - return (find() != end()); - } - - void insert(Key const& k, Value const& v) { - self->dictionary_.insert(std::pair(k, v)); - } - - ObjDictionary& operator=(ObjDictionary const& a) { - return copyFrom(a); - } - - Value operator[](Key const& k) { - return self()->dictionary_[k]; - } - - bool write(FILE* f, bool bin, unsigned int fg) const { - size_t sz = size(); - if (bin) { - if (fwrite(&sz, sizeof(size_t), 1, f) < 1) return false; - } - else { - if (fprintf(f, "%lu\n", sz) < 1) return false; - } - for (std::map::const_iterator it = begin(); it != end(); ++it) { - if (it->first .write(f, bin, fg) == false) return false; - if (it->second.write(f, bin, fg) == false) return false; - } - return true; - } - - bool read(FILE* f, bool bin, unsigned int fg) { - size_t sz; - if (bin) { - if (fread(&sz, sizeof(size_t), 1, f) < 1) return false; - } - else { - if (fscanf(f, "%lu\n", &sz) < 0) return false; - } - for (size_t i = 0; i < sz; i++) { - Key k; - Value v; - if (k.read(f, bin, fg) == false) return false; - if (v.read(f, bin, fg) == false) return false; - insert(k, v); - } - return true; - } - - ObjBase* create() const { - return new ObjDictionary(); - } - - ObjBase* copyFrom(ObjBase const* b) { - return &(copyFrom(*(ObjDictionary const*)b)); - } - - char const* ctype() const { - return typeid(*this).name(); - } - - std::string type() const { - return std::string(ctype()); - } -}; - -} - -#endif // oo_ObjDictionary_H__ diff --git a/meowpp/oo/ObjProperties.h b/meowpp/oo/ObjProperties.h deleted file mode 100644 index 01e01d0..0000000 --- a/meowpp/oo/ObjProperties.h +++ /dev/null @@ -1,55 +0,0 @@ -#ifndef oo_ObjProperties_H__ -#define oo_ObjProperties_H__ - -#include "ObjBase.h" - -#include - -namespace meow { - -template - -//! 目前擺爛中 -class ObjProperties: public ObjBase { -private: -public: - ObjProperties(); - - ObjProperties(ObjProperties const& p); - - virtual ~ObjProperties(); - - size_t propertySize() const; - - bool propertyEmpty() const; - - void propertyClear(); - - ObjBase const* property(std::string name) const; - - ObjBase* property(std::string name); - - bool propertyAdd(std::string name, ObjBase* obj, bool autoRemove); - - bool propertyDel(std::string name); - - ObjProperties& properties() const; - - ObjProperties& properties(ObjProperties const& p); - - bool write(FILE* f, bool bin, unsigned int fg) const; - - bool read(FILE* f, bool bin, unsigned int fg); - - ObjBase* create() const; - - ObjBase* copyFrom(ObjBase const* b); - - char const* ctype() const; - - std::string type() const; -}; - -} - -#endif // oo_ObjProperties_H__ diff --git a/meowpp/oo/ObjSelector.h b/meowpp/oo/ObjSelector.h deleted file mode 100644 index f08cfe4..0000000 --- a/meowpp/oo/ObjSelector.h +++ /dev/null @@ -1,214 +0,0 @@ -#ifndef oo_ObjSelector_H__ -#define oo_ObjSelector_H__ - -#include "ObjBase.h" - -#include -#include -#include -#include - -#include -#include - -namespace meow { - -/*! - * @brief 利用register的概念, 達到runtime用string選擇要new的class - * - * @author cathook - */ -template //!< 讓程式可以有不只一個 \c ObjSelector -class ObjSelector { -private: - struct Info { - ObjSelector* parent_; - ObjBase const* pointer_; - bool autoDelete_; - - Info(ObjSelector* parent, - ObjBase const* ptr, - bool autoDelete) { - parent_ = parent; - pointer_ = ptr; - autoDelete_ = autoDelete; - } - - ~Info() { - if (autoDelete_) { - delete pointer_; - } - if (parent_ != NULL) { - parent_->me_.second = NULL; - } - } - }; - friend struct Info; - - typedef typename std::map Infos; - typedef typename std::map::iterator InfosIterator; - - static Infos& funcs() { - static Infos f; - return f; - } - static Info* add(std::string name, - ObjSelector* parent, - ObjBase* ptr, - bool autoDelete) { - Info* info = new Info(parent, ptr, autoDelete); - del(name); - funcs()[name] = info; - return info; - } - - std::pair me_; -public: - /*! - * @brief 新增(註冊) 一個Class (必須要繼承自 \c ObjBase) 並且給定其Name - */ - static void add(std::string name, ObjBase* obj, bool autoDelete) { - add(name, NULL, obj, autoDelete); - } - - /*! - * @brief 新增(註冊) 一個Class (必須要繼承自 \c ObjBase) 並且默認type為name - */ - static void add(ObjBase* obj, bool autoDelete) { - add(obj->type(), NULL, obj, autoDelete); - } - - /*! - * @brief 依照name刪除之前註冊過得Class - */ - static void del(std::string name) { - if (funcs().find(name) != funcs().end()) { - delete funcs()[name]; - funcs().erase(name); - } - } - - /*! - * @brief 取得之前註冊過得Class - */ - static ObjBase const* get(std::string name) { - if (funcs().find(name) == funcs().end()) return NULL; - return funcs()[name]->pointer_; - } - - /*! - * @brief 回傳一個之前註冊過得Class new出來的實體 - */ - static ObjBase* create(std::string name) { - ObjBase const* ptr = get(name); - if(ptr == NULL) return NULL; - return ptr->create(); - } - - /*! - * @brief 利用type檢查是否有註冊過同種類的Class - */ - static bool exist(ObjBase* obj) { - for (InfosIterator it = funcs().begin(); it != funcs().end(); it++) { - if (it->second->pointer_ == obj || - (it->second->pointer_ != NULL && - it->second->pointer_->type() == obj->type())) { - return true; - } - } - return false; - } - - /*! - * @brief 利用type尋找name - */ - static std::string name(ObjBase* obj) { - for (InfosIterator it = funcs().begin(); it != funcs().end(); it++) { - if (it->second->pointer_ == obj || - (it->second->pointer_ != NULL && - it->second->pointer_->type() == obj->type())) { - return it->first; - } - } - return std::string(); - } - - /*! - * @brief 回傳所有註冊過的name - */ - static std::vector names() { - std::vector ret; - for (InfosIterator it = funcs().begin(); it != funcs().end(); it++) - ret.push_back(it->first); - return ret; - } - - /*! - * @brief 宣告一個ObjSelector實體, 並且註冊一個 ObjBase - */ - ObjSelector(std::string name, ObjBase* obj, bool autoDelete) { - me_.first = name; - me_.second = add(me_.first, this, obj, autoDelete); - } - - /*! - * @brief 宣告一個ObjSelector實體, 並且註冊一個 ObjBase - */ - ObjSelector(ObjBase* obj, bool autoDelete) { - me_.first = obj->type(); - me_.second = add(me_.first, this, obj, autoDelete); - } - - //! 解構子 - ~ObjSelector() { - if (me_.second != NULL) { - del(me_.first); - } - } - - /*! - * @brief 將一個物件寫到檔案裡(該物件必須要有註冊過) - */ - static bool write(FILE* f, bool binary, ObjBase* obj, unsigned int fg) { - if (!exist(obj)) return false; - char const* nme = name(obj).c_str(); - size_t len = strlen(nme); - if (binary) { - if (fwrite(&len, sizeof(size_t ), 1, f) < 1) return false; - if (fwrite(nme , sizeof(char ), len, f) < len) return false; - if (fwrite(&fg , sizeof(unsigned int), 1, f) < 1) return false; - } else { - if (fprintf(f, "%s %u\n", nme, fg) < 2) return false; - } - return obj->write(f, binary, fg); - } - - /*! - * @brief 從檔案中讀取一個物件(該物件必須要有註冊過) - */ - static ObjBase* read(FILE* f, bool binary) { - static char name[2048]; - size_t len; - unsigned int fg; - if (binary) { - if (fread(&len, sizeof(size_t ), 1, f) < 1) return NULL; - if (fread(name, sizeof(char ), len, f) < len) return NULL; - if (fread(&fg , sizeof(unsigned int), 1, f) < 1) return NULL; - name[len] = '\0'; - } else { - if (fscanf(f, "%s %u", name, &fg) < 2) return NULL; - } - ObjBase* ret = create(std::string(name)); - if (ret != NULL && ret->read(f, binary, fg) == false) { - delete ret; - ret = NULL; - } - return ret; - } -}; - -static const size_t kGlobalSeletorID = 0; - -} // meow - -#endif // oo_ObjSelector_H__ diff --git a/meowpp/oo/ObjTypes.h b/meowpp/oo/ObjTypes.h deleted file mode 100644 index ba2d358..0000000 --- a/meowpp/oo/ObjTypes.h +++ /dev/null @@ -1,201 +0,0 @@ -#ifndef oo_ObjType_H__ -#define oo_ObjType_H__ - -#include "../Self.h" -#include "ObjBase.h" - -#include -#include - -namespace meow { - -/*! - * @brief 純粹把給定的 \c Type 包起來, 變成繼承自 ObjBase - * - * @author cathook - */ -template -class ObjType: public ObjBase { -private: - struct Myself { - Type data_; - - Myself() { - } - - Myself(Type const& t): data_(t) { - } - - ~Myself() { - } - }; - Self const self; -public: - //! @brief constructor - ObjType(): self() { - } - - //! @brief constructor, 並且給值 - ObyType(Type const& t): self(Myself(t)) { - } - - //! @brief constructor, 並且copy資料 - ObjType(ObjType const& a): self(a.self, Self::COPY_FROM) { - } - - ~ObjType() { - } - - ObjType& copyFrom(ObjType const& a) { - self().copyFrom(a.self); - return *this; - } - - ObjType& referenceFrom(ObjType const& a) { - self().referenceFrom(a.self); - return *this; - } - - Type access() const { - return self->data_; - } - - Type& modify() { - return self()->data_; - } - - ObjType& operator=(ObjType const& a) { - return copyFrom(a); - } - - Type operator()() const { - return access(); - } - - Type& operator()() { - return modify(); - } - - bool write(FILE* f, bool bin, unsigned int fg) const { - return ReaderWriter::write(f, bin, fg, self->data_); - } - - bool read(FILE* f, bool bin, unsigned int fg) { - return ReaderWriter::read(f, bin, fg, &(self()->data_)); - } - - ObjBase* create() const { - return new ObjType(); - } - - ObjBase* copyFrom(ObjBase const* b) { - return &(copyFrom(*(ObjType const*)b)); - } - - char const* ctype() const { - return typeid(*this).name(); - } - - std::string type() const { - return std::string(ctype()); - } -}; - -class ReaderWriter_int { -public: - static bool write(FILE* f, bool bin, unsigned int fg, int const& k) { - if (bin) { - return (fwrite(&k, sizeof(k), 1, f) == 1); - } - else { - return (fprintf(f, "%d\n", k) == 1); - } - } - static bool read(FILE* f, bool bin, unsigned int fg, int* k) { - if (bin) { - return (fread(k, sizeof(k), 1, f) == 1); - } - else { - return (fscanf(f, "%d", k) == 1); - } - } -}; - -class ReaderWriter_size_t { -public: - static bool write(FILE* f, bool bin, unsigned int fg, size_t const& k) { - if (bin) { - return (fwrite(&k, sizeof(k), 1, f) == 1); - } - else { - return (fprintf(f, "%lu\n", k) == 1); - } - } - static bool read(FILE* f, bool bin, unsigned int fg, size_t* k) { - if (bin) { - return (fread(k, sizeof(k), 1, f) == 1); - } - else { - return (fscanf(f, "%lu", k) == 1); - } - } -}; - -class ReaderWriter_double { -public: - static bool write(FILE* f, bool bin, unsigned int fg, double const& k) { - if (bin) { - return (fwrite(&k, sizeof(k), 1, f) == 1); - } - else { - return (fprintf(f, "%.15f\n", k) == 1); - } - } - static bool read(FILE* f, bool bin, unsigned int fg, double* k) { - if (bin) { - return (fread(k, sizeof(k), 1, f) == 1); - } - else { - return (fscanf(f, "%lf", k) == 1); - } - } -}; - -class ReaderWriter_string { -public: - static bool write(FILE* f, bool bin, unsigned int fg, std::string const& k) { - size_t len = k.size(); - char const* buf = k.c_str(); - if (bin) { - if (fwrite(&len, sizeof(len) , 1, f) < 1) return false; - if (fwrite( buf, sizeof(char), len, f) < len) return false; - } - else { - if (fprintf(f, "%s\n", buf) < 1) return false; - } - return true; - } - static bool read(FILE* f, bool bin, unsigned int fg, std::string* k) { - size_t len; - char buf[81920]; - if (bin) { - if (fread(&len, sizeof(len) , 1, f) < 1) return false; - if (fread( buf, sizeof(char), len, f) < len) return false; - buf[len] = '\0'; - } - else { - if (fscanf(f, "%s", buf) < 1) return false; - } - (*k) = buf; - return true; - } -}; - -typedef ObjType ObjInt; -typedef ObjType ObjSizeT; -typedef ObjType ObjDouble; -typedef ObjType ObjString; - -} // meow - -#endif // oo_ObjType_H__ diff --git a/meowpp/self.h b/meowpp/self.h deleted file mode 100644 index f58ef35..0000000 --- a/meowpp/self.h +++ /dev/null @@ -1,346 +0,0 @@ -#ifndef MEOWPP_SELF_H_ -#define MEOWPP_SELF_H_ - -#include -#include - -namespace meow { - -/*! - *@brief For developer to pack the attributes of a class. - * - * The idaa comes from python. - * Default C++'s reference machanism is very unflexible because a reference - * variable can only reference to an object without changing to other object. - * - * With this technique, it can achieve Copy-On-Write(COR) mechanism at - * background and have a reference mechanism which much more flexible - * then the one C++ has. - * - * Sample code: - *@code{.cpp} - * class A { - * private: - * struct Myself { - * int data; - * - * Myself() { // Necessary - * data = 0; - * } - * - * Myself(Myself const& b): data(b.data) { // Necessary, copy constructor - * } - * - * ~Myself() { - * } - * - * bool operator==(Myself const& b) const { // Optional (this method will - * // be called only if you use - * // Self::equal() method) - * return (data == b.data); - * } - * }; - * - * Self const self; // Here we use 'constant' data type in - * // order to have a coutious coding style - * // and allow the COR mechanism to clone - * // data only when we really want to - * // modify them. - * public: - * A(): self() { } // Default constructor - * - * A(A const& a): self(a.self, COPY_FROM) { } // Copy constructor. You must - * // tell me which way of - * // duplicating should I use. - * // It strongly recommended you - * // use COYP_FROM for keeping the - * // C++'s original behavior. - * ~A() { } - * - * int getMemember(int wh) const { - * return self->data; // Use 'operator->()' to get the pointer of the data - * // The pointer is constant or not will depend on - * // whether the left side variable of '->' is - * // constant or not. - * // If we just want to read the data, use - * // 'self' instead of 'self()' - * } - * void setMemeber(int k) { - * self()->data = k; // As a result of 'self()' returning a non-constant - * // reference of itself, here we get the permission - * // for modiying data. - * // So now we can observe that if you type - * // 'Self self' instead of the one above, - * // 'self' and 'self()' will become the same one and - * // both of them allow you using '->' for getting - * // writing permission. At the same time, the COR - * // machanism will become useless because everytime - * // you want to access the date, Self will copy the - * // data to prevent you to modify it no matter that - * // you might just want to read it. - * } - * - * A referenceFrom(A const& a) { - * self.referenceFrom(a.self); - * } - * - * A copyFrom(A const& a) { - * self.copyFrom(a.self); - * } - * - * A& operator=(A const& b) { // If you really like to use operator=, it - * // strongly recommended you use 'copyFrom()' for - * // keeping C++'s original behavior. - * copyFrom(b); - * } - * }; - *@endcode - * Note that 'referenceFrom()' will cause the two object become the same one, - * Which means that if you do something like '\c a.referenceFrom(b); - * \c a.copyFrom(c); ', the result is that the value of \c a,b,c will all the - * same one. - * - *@author cathook - * - *@warning This class disabled the method \c operator= and copy constructor - * in order to prevent unexplicit default behavior, so if you want - * to have one of them (or both), you must implement yourself - */ -template -class Self { -public: - /*! - * @brief Kind of ways of duplicating - */ - enum DuplicateType { - COPY_FROM, //!< Normal copy operation - REFERENCE_FROM //!< By reference, much like pointer's copy operation - }; -private: - class Body { - private: - struct Kernel { - Data* data_; - size_t counter_; - Body const* master_; - - Kernel(Body const* master): - data_(new Data( )), counter_(1), master_(master) { - } - - Kernel(Body const* master, Data const& d): - data_(new Data(d)), counter_(1), master_(master) { - } - - ~Kernel() { - delete data_; - } - }; - - Kernel* pointer_; - size_t counter_; - - void clear() { - --(pointer_->counter_); - if (pointer_->counter_ <= 0) { - delete pointer_; - } - else if (pointer_->master_ == this) { - pointer_->master_ = NULL; - } - } - public: - Body( ): pointer_(new Kernel(this )), counter_(1) { } - Body(Data const& d): pointer_(new Kernel(this, d)), counter_(1) { } - Body(Body const& b): pointer_(b.pointer_ ), counter_(1) { - ++(pointer_->counter_); - } - - ~Body() { - clear(); - } - - Body& copyFrom(Body const& b) { - clear(); - pointer_ = b.pointer_; - ++(pointer_->counter_); - return *this; - } - - Data const* access() const { - return pointer_->data_; - } - - Data* modify() { - if (pointer_->counter_ > 1) { - --(pointer_->counter_); - Kernel* dupl = new Kernel(this, *pointer_->data_); - if (pointer_->master_ == this) { - std::swap(pointer_->data_, dupl->data_); - pointer_->master_ = NULL; - } - pointer_ = dupl; - } - else if (pointer_->master_ == NULL) { - pointer_->master_ = this; - } - return pointer_->data_; - } - - int attach() { - return ++counter_; - } - - int detach() { - return --counter_; - } - }; - - Body* body_; - - void clear() { - if (body_->detach() <= 0) { - delete body_; - } - } -public: - /*! - * @brief constructor with a real entity - */ - Self(): body_(new Body()) { - } - - /*! - * @brief connstructor with a real entity with it using its copy constructor - * - * @param [in] d Inital data - */ - Self(Data const& d): body_(new Body(d)) { - } - - /*! - * @brief constructor with given another Self - * - * @param [in] b Another Self object. - * @param [in] d To indicate type of way of duplicating - */ - Self(Self const& b, DuplicateType d) { - switch(d) { - case COPY_FROM: - body_ = new Body(*b.body_); - break; - case REFERENCE_FROM: - body_ = b.body_; - body_->attach(); - break; - } - } - - //! @brief Disallow copy constructor - Self(Self const& b); - - //! @brief destructor - ~Self() { - clear(); - } - - //! @brief Return the constant pointer to the data - Data const* operator->() const { - return body_->access(); - } - - /*! @brief Return the non-constant pointer to the data (COR's clone might - * occure here. - */ - Data* operator->() { - return body_->modify(); - } - - //! @brief Return the non-constant reference of \c *this - Self& operator()() const { - return *((Self*)this); - } - - /*! - * @brief Copy the gived \c Self to myself - * - * @param [in] s gived \c Self - * @return *this - */ - Self const& copyFrom(Self const& s) { - if (body_->access() != s.body_->access()) { - body_->copyFrom(*s.body_); - } - return *this; - } - - /*! - * @brief Reference myself from given \c Self object. - * - * @param [in] s given \c Self - * @return *this - */ - Self const& referenceFrom(Self const& s) { - if (body_ != s.body_) { - clear(); - body_ = s.body_; - body_->attach(); - } - return *this; - } - - /*! - * @brief call \c copyFrom() or \c referenceFrom() depend on your instruction - * - * @param [in] s gived \c Self object - * @param [in] t instruction - * @return *this - */ - Self const& duplicateFrom(Self const& s, DuplicateType t) { - switch(t) { - case COPY_FROM : return copyFrom(s); - case REFERENCE_FROM: return referenceFrom(s); - } - return *this; - } - - /*! - * @brief Compare tht if the gived \c Self object is reference from the same - * object of me - * - * @param [in] s gived \c Self object - * @return \c true if we are referenced to the same object. - */ - bool same(Self const& s) const { - return (body_ == s.body_); - } - - /*! - * @brief Compare that the data are the same. - * - * @param [in] s another \c Self object - * @return \c true if the data are same. - * - * @note This will need the method 'Data::equal()' - */ - bool equal(Self const& s) const { - if (same(s) || body_->access() == s.body_->access()) return true; - return (*body_->access() == *s.body_->access()); - } - - /*! - * @brief Order compare by reference pointer. - * - * @param [in] s another \c Self object - */ - bool referenceLess(Self const& s) const { - return (body_ < s.body_); - } - - //! @brief Disallow default \c 'operator=' - void operator=(Self const& a); -}; - -} // meow - -#endif // MEOWPP_SELF_H_ diff --git a/meowpp/utility.h b/meowpp/utility.h deleted file mode 100644 index 02cf6a2..0000000 --- a/meowpp/utility.h +++ /dev/null @@ -1,204 +0,0 @@ -#ifndef utility_H__ -#define utility_H__ - -#include -#include -#include -#include - -#include - -namespace meow { - -/*! - * @brief A structur with memember \c .from.first , \c .from.second , - * \c .to.first , \c .to.second - * - * @author cathook - */ -template -struct PairToPair { - std::pair from; - std::pair to; - - PairToPair() { - } - PairToPair(PairToPair const& pp): from(pp.from), to(pp.to) { - } - PairToPair(F1 const& f1, F2 const& f2, T1 const& t1, T2 const& t2): - from(f1, f2), to(t1, t2) { - } - bool operator==(PairToPair const& p) const { - return (from == p.from && to == p.to); - } -}; - -/*! - * @brief 類似C的printf, 不過是將格式化的字串丟到 \c std::string 裡回傳 - * - * @param [in] fmt,... 同printf - * @return 一個 \c std::string - * @warning 目前格式化字串最長只支援8191個字元 - */ -inline std::string stringPrintf(char const * fmt, ...) { - char str[8192]; - va_list args; - va_start(args, fmt); - vsnprintf(str, 8192, fmt, args); - va_end(args); - return std::string(str); -} - -/*! - * @brief 將輸入字串中的某個pattern取代成另一個pattern - * - * @param [in] str 輸入的字串 - * @param [in] from 要被取代的pattern - * @param [in] to 將要取代的pattern - * @return 取代後的字串 - * @warning 有礙於目前實作方法很低級暴力, 時間複雜度神高 - */ -inline std::string stringReplace(std::string str, - std::string const& from, - std::string const& to) { - std::string out = str; - int len = from.length(); - for (size_t pos; (pos = out.find(from)) != std::string::npos; ) { - out.replace(pos, len, to); - } - return out; -} - -/*! - * @brief 檢查給定字串的結尾是否符合給定的數個patterns中的一個 - * - * @param [in] str 愈檢查的字串 - * @param [in] n pattern數 - * @param [in] ... 各種pattern - * @return \c true/false 表示 \b 是否有符合 - * @note 參數中所有的字串都是用\c cstring 來傳遞, - * 也就是 \c char \c const* 型態 - */ -inline bool cstringEndWith(char const* str, int n, ...) { - int len = strlen(str); - va_list args; - va_start(args, n); - for (int i = 0; i < n; i++) { - char const* arg = va_arg(args, char const*); - int arglen = strlen(arg); - if (arglen <= len && strcmp(str + len - arglen, arg) == 0) { - return true; - } - } - va_end(args); - return false; -} - -/*! - * @brief 若DEBUG有被define過, 將字串印到stderr, 並且附上檔名行號與所在函數名 - * - * @param [in] str 要輸出的字串, 必須是c string, 即 \c char \c const* 型態 - * @return 無 - * @note 這是一個 \b macro - */ -#define debugPrintf(str) \ -debugPrintf_(\ - __FILE__,\ - __FUNCTION__,\ - __LINE__,\ - str) -inline void debugPrintf_(char const* file, - char const* func, - size_t line, - char const* msg) { -#ifdef DEBUG - fprintf(stderr, "%s[%d] %s >> %s", file, line, func, msg); -#endif // DEBUG -} - -/*! - * @brief 階層式輸出 - * - * 像是printf, 但多了一個 \b 巢狀 的概念, 例如: - * - * @code - * message1(level = 0) - * message2(level = 1) - * information1(level = 2) - * information2(level = 2) - * ... ok(for message2) - * message3(level = 1) ... ok - * information3(level = 1) - * message4(level = 1) - * message5(level = 2) ... ok - * message6(level = 2) ... ok - * information4(level = 2) - * ... ok(for message4) - * ... ok(for message5) - * @endcode - * @param [in] level_change 分以下三種情況: - * - == 0, 只是印出一個information - * - == 1, 印出一個message, 並且level++ - * - == -1, 表示此訊息相對應最近一次level++的那個message - * @param [in] fmt, ... 跟printf一樣 - * @return 無 - */ -inline void messagePrintf(int level_change, char const* fmt, ...) { - static int level = 0; - static int last_level = -5; - char str[8192]; - va_list args; - va_start(args, fmt); - vsnprintf(str, 8192, fmt, args); - va_end(args); - if (last_level == 1 && level_change == -1) { - printf(" ...%s\n", str); - } - else { - if (last_level == 1) printf("\n"); - int level2 = level + (level_change == -1 ? -1 : 0); - for (int i = 0; i < level2; i++) printf("| "); - printf("%s%s", (level_change == -1 ? "..." : ""), str); - if (level_change != 1) printf("\n"); - } - level += level_change; - last_level = level_change; - fflush(stdout); -} - -/*! - * @brief 將兩個字串用人類習慣的檔名排序方式排序 - * - * 例如 a1 \< a2 \< a3 \< a10 \< a12 \< a20, - * 而不是 a1 \< a10 \< a12 \< a2 \< a20 \< a3 - * - * @param [in] f1 第一個字串 - * @param [in] f2 第二個字串 - * @return \c true/false 表 \b f1是否該排在f2前面 - */ -inline bool filenameCompare(std::string const& f1, std::string const& f2) { - char const* s1 = f1.c_str(); - char const* s2 = f2.c_str(); - int l1 = f1.length(); - int l2 = f2.length(); - int i1, i2; - for (i1 = i2 = 0; i1 < l1 || i2 < l2; i1++, i2++) { - if (isdigit(s1[i1]) && isdigit(s2[i2])) { - int n1 = atoi(s1 + i1); - int n2 = atoi(s2 + i2); - if (n1 != n2) - return (n1 < n2); - while(i1 + 1 < l1 && isdigit(s1[i1 + 1])) i1++; - while(i2 + 1 < l2 && isdigit(s2[i2 + 1])) i2++; - } - else { - if(s1[i1] != s2[i2]) - return s1[i1] < s2[i2]; - } - } - return false; -} - -} // meow - -#endif // utility_H__ diff --git a/meowpp/utility/factory.h b/meowpp/utility/factory.h new file mode 100644 index 0000000..8e350a0 --- /dev/null +++ b/meowpp/utility/factory.h @@ -0,0 +1,383 @@ +/*! + * @file factory.h + * @brief Contains a base class for a factory. + * + * A factory contains an array of inputs, an array of outputs and an operation. + * You can update some elements in the array of inputs and then call + * `Factory::Update()` to update the outputs (it will run the operation only if + * some input elements are changed since last update). + * + * @author cathook + */ + +#ifndef __MEOWPP_UTILITY_FACTORY_H__ +#define __MEOWPP_UTILITY_FACTORY_H__ + +#include "operation.h" +#include "pointer.h" +#include "self.h" + + +namespace meow { + +namespace factory_types { + + +/*! + * @brief A base class for kinds of factory classes. + */ +class Base { + protected: + struct BaseData { + Pointer oper; + Pointer> inputs; + Pointer> outputs; + + //! An array with each elements points to the input elements with + //! non-constant type. + Pointer> non_const_inputs; + + //! An array with each elements points to the output elements with + //! constant type. + Pointer> const_outputs; + + /*! + * @brief Constructor. + * @param [in] arg_oper The operation this factory should run. + * @param [in] arg_inputs A pointer points to the array of the input + * elements. + * @param [in] arg_outputs A pointer points to the array of the output + * elements. + */ + BaseData(Pointer const& arg_oper, + Pointer> const& arg_inputs, + Pointer> const& arg_outputs): + oper(arg_oper), + inputs(arg_inputs), + outputs(arg_outputs), + non_const_inputs(new Pointer[oper->inputs_size()], ARRAY, true), + const_outputs( + new Pointer[oper->outputs_size()], ARRAY, true) { + for (int i = 0, i_max = oper->inputs_size(); i < i_max; ++i) { + non_const_inputs[i] = Pointer( + const_cast(inputs[i].address()), SINGLE, false); + } + for (int i = 0, i_max = oper->outputs_size(); i < i_max; ++i) { + const_outputs[i] = Pointer( + outputs[i].address(), SINGLE, false); + } + }; + }; + + Base() {} + + public: + virtual ~Base() {} + + /*! + * @brief Updates the output elements by re-run the operation. + */ + virtual State Update() const = 0; + + /*! + * @brief Returns whether the last time calling `Update()` did update really + * or not. + * + * If the input elements were not changed before `Update()` be called, it + * might be returns false (depends on how it implements). + */ + virtual bool HasRedo() const = 0; + + /*! + * @brief Gets the operation. + */ + virtual Pointer operation() const = 0; + + /*! + * @brief Gets the pointer points to the array of input elements. + */ + virtual Pointer> inputs() const = 0; + + /*! + * @brief Gets the pointer points to the array of output elements. + */ + virtual Pointer> outputs() const = 0; +}; + + +/*! + * An implement of the factory class. + * + * When the function `Update()` be called, no matter whether the input elements + * has changed or not, it will do the operation. + */ +class CheckOff : public Base { + private: + struct Data : Base::BaseData { + Data(Pointer const& arg_oper, + Pointer> const& arg_inputs, + Pointer> const& arg_outputs) : + BaseData(arg_oper, arg_inputs, arg_outputs) {} + }; + + Self const self_; + + public: + + /*! + * @brief Constructor. + * @param [in] arg_oper The operation for this factory to run. + * @param [in] arg_inputs A pointer points to the array of the pointer points + * to the input elements. + * @param [in] arg_outputs A pointer points to the array of the pointer points + * to the output elements. + */ + CheckOff(Pointer const& arg_oper, + Pointer> const& arg_inputs, + Pointer> const& arg_outputs) : + self_(Data(arg_oper, arg_inputs, arg_outputs)) {} + + /*! + * @brief Updates the output elements by running the operation. + */ + State Update() const { + return self_->oper->Operate(self_->inputs, self_->outputs); + } + + /*! + * @brief It will always return true. + */ + bool HasRedo() const { + return true; + } + + /*! + * @brief Gets the operation. + */ + virtual Pointer operation() const { + return self_->oper; + } + + /*! + * @brief Gets the pointer points to the array of input elements. + */ + Pointer> inputs() const { + return self_->non_const_inputs; + } + + /*! + * @brief Gets the pointer points to the array of output elements. + */ + Pointer> outputs() const { + return self_->const_outputs; + } + +}; + + +/*! + * An implement of the factory class. + * + * It will check whether the input elements has changed before running the + * operation. + */ +class CheckOn : public Base { + private: + struct Data : Base::BaseData { + //! Stores the last input elements which are using to check whether the + //! input elements have changed or not. + Pointer> old_inputs; + + //! Stores the state returned by the operation last time. + State last_state; + + //! Stores whether the last `Update()` run the operation or not. + bool has_redo; + + //! Stores whether it has not run the `Update()` yet. + bool first_time; + + Data(Pointer const& arg_oper, + Pointer> const& arg_inputs, + Pointer> const& arg_outputs) : + BaseData(arg_oper, arg_inputs, arg_outputs), + old_inputs(new Pointer[oper->inputs_size()], ARRAY, true), + has_redo(false), + first_time(true) { + for (int i = 0, i_max = oper->inputs_size(); i < i_max; ++i) { + old_inputs[i] = Pointer(inputs[i]->Copy(), SINGLE, true); + } + } + }; + + Self const self_; + + public: + + /*! + * @brief Constructor. + * @param [in] arg_oper The operation this factory should run. + * @param [in] arg_inputs A pointer points to the array of the input + * elements. + * @param [in] arg_outputs A pointer points to the array of the output + * elements. + */ + CheckOn(Pointer const& arg_oper, + Pointer> const& arg_inputs, + Pointer> const& arg_outputs) : + self_(Data(arg_oper, arg_inputs, arg_outputs)) {} + + /*! + * @brief Updates the output elements if needs. + * + * It will check whether the input elements different from the old ones first. + */ + State Update() const { + bool needs_to_update = self_->first_time; + if (!needs_to_update) { + for (int i = 0, i_max = self_->oper->inputs_size(); i < i_max; ++i) { + Object const* old = self_->old_inputs[i].address(); + Object const* cur = self_->inputs[i].address(); + if (!old->Equals(cur)) { + needs_to_update = true; + break; + } + } + } + if (!needs_to_update) { + self_()->has_redo = false; + } else { + for (int i = 0, i_max = self_->oper->inputs_size(); i < i_max; ++i) { + Object* old = self_->old_inputs[i].address(); + Object const* cur = self_->inputs[i].address(); + old->CopyFrom(cur); + } + self_()->last_state = self_->oper->Operate(self_->inputs, self_->outputs); + self_()->has_redo = true; + } + self_()->first_time = false; + return self_->last_state; + } + + /*! + * @brief Returns whether the output elements have been re-generated by + * running the operation again. + * + * It will check whether the input elements different from the old ones first. + */ + bool HasRedo() const { + return self_->has_redo; + } + + /*! + * @brief Gets the operation. + */ + virtual Pointer operation() const { + return self_->oper; + } + + /*! + * @brief Gets the array of the input elements. + */ + Pointer> inputs() const { + return self_->non_const_inputs; + } + + /*! + * @brief Gets the array of the output elements. + */ + Pointer> outputs() const { + return self_->const_outputs; + } + +}; + +} // factory_types + + +/*! + * @brief A class which contains input elements, output elements and an + * operation. + */ +class Factory : public Object { + private: + + Pointer factory_; + + public: + + /*! + * @brief Constructor. + */ + Factory(Pointer const& arg_oper, + Pointer> const& arg_inputs, + Pointer> const& arg_outputs, + bool arg_check_before_update) { + if (arg_check_before_update) { + factory_ = Pointer( + new factory_types::CheckOn( + arg_oper, arg_inputs, arg_outputs), SINGLE, true); + } else { + factory_ = Pointer( + new factory_types::CheckOff( + arg_oper, arg_inputs, arg_outputs), SINGLE, true); + } + } + + /*! + * @brief Updates the output elements. + */ + State Update() const { + return factory_->Update(); + } + + /*! + * @brief Returns whether the output elements have been re-generated by + * running the operation again. + */ + bool HasRedo() const { + return factory_->HasRedo(); + } + + /*! + * @brief Gets the operation. + */ + Pointer operation() const { + return factory_->operation(); + } + + /*! + * @brief Gets the array of the input elements. + */ + Pointer> inputs() const { + return factory_->inputs(); + } + + /*! + * @brief Gets the array of the output elements. + */ + Pointer> outputs() const { + return factory_->outputs(); + } + + Object* Copy() const { + return NULL; + } + + Object* CopyFrom(Object const* another_factory) { + return NULL; + } + + bool Equals(Object const* another_factory) { + return false; + } + +#ifdef MEOWPP_UTILITY_FACTORY_TESTING + friend class FactoryTest; +#endif + +}; + +} // meow + +#endif // __MEOWPP_UTILITY_FACTORY_H__ diff --git a/meowpp/utility/object.h b/meowpp/utility/object.h new file mode 100644 index 0000000..630ab6e --- /dev/null +++ b/meowpp/utility/object.h @@ -0,0 +1,154 @@ +/*! + * @file object.h + * @brief Contains a base class for most of all the classes in meowpp. + * + * @author cathook + */ + +#ifndef __MEOWPP_UTILITY_OBJECT_H__ +#define __MEOWPP_UTILITY_OBJECT_H__ + +#include +#include + +namespace meow { + + +/*! + * @brief The base class. + */ +class Object { + protected: + + /*! + * @brief A protected constructor to prevent developers create an instance of + * Object directly. + */ + Object() {} + + /*! + * @brief Disable the copy operation. + */ + Object(Object const& b); + + public: + + /*! + * @brief Virtual destructor. + */ + virtual ~Object() {} + + /*! + * @brief Creates a copy of itself and return the pointer to it. + */ + virtual Object* Copy() const { + return NULL; + } + + /*! + * @brief Copies data from another object. + * @param [in] ptr Points to another object. + */ + virtual Object* CopyFrom(Object const* ptr) { + return NULL; + } + + /*! + * @brief Returns whether it equals to another object or not. + * @param [in] ptr Points to another object. + */ + virtual bool Equals(Object const* ptr) const { + return false; + } + + /*! + * @brief Disable the copy operator. + */ + Object& operator=(Object const& b); +}; + + +/*! + * @brief A class for number base object. + * + * It contains bitwise operations. + */ +template +class BaseNumberType : public Object { + private: + DataType value_; + public: + BaseNumberType() : BaseNumberType(static_cast(0)) {} + BaseNumberType(BaseNumberType const& b) : BaseNumberType(b.value_) {} + BaseNumberType(DataType const& arg_init_value) : value_(arg_init_value) {} + ~BaseNumberType() {} + Object* Copy() const { return new BaseNumberType(value_); } + Object* CopyFrom(Object const* ptr) { + value_ = static_cast(ptr)->value_; + return this; + } + bool Equals(Object const* ptr) const { + return (value_ == static_cast(ptr)->value_); + } + operator DataType() const { return value_; } + BaseNumberType& operator=(DataType const& b) { value_ = b; return *this; } + BaseNumberType& operator+=(DataType const& b) { value_ += b; return *this; } + BaseNumberType& operator-=(DataType const& b) { value_ -= b; return *this; } + BaseNumberType& operator*=(DataType const& b) { value_ *= b; return *this; } + BaseNumberType& operator/=(DataType const& b) { value_ /= b; return *this; } + BaseNumberType& operator&=(DataType const& b) { value_ &= b; return *this; } + BaseNumberType& operator|=(DataType const& b) { value_ |= b; return *this; } + BaseNumberType& operator^=(DataType const& b) { value_ ^= b; return *this; } + BaseNumberType& operator<<=(int64_t const& b) { value_ <<= b; return *this; } + BaseNumberType& operator>>=(int64_t const& b) { value_ >>= b; return *this; } +}; + + +/*! + * @brief A class for floating-point base object. + * + * It don't contain bitwise operations. + */ +template +class BaseFloatingType : public Object { + private: + DataType value_; + public: + BaseFloatingType() : BaseFloatingType(static_cast(0)) {} + BaseFloatingType(BaseFloatingType const& b) : BaseFloatingType(b.value_) {} + BaseFloatingType(DataType const& arg_init_value) : value_(arg_init_value) {} + ~BaseFloatingType() {} + Object* Copy() const { return new BaseFloatingType(value_); } + Object* CopyFrom(Object const* ptr) { + value_ = static_cast(ptr)->value_; + return this; + } + bool Equals(Object const* ptr) const { + return (value_ == static_cast(ptr)->value_); + } + operator DataType() const { return value_; } + BaseFloatingType& operator=(DataType const& b) { value_ = b; return *this; } + BaseFloatingType& operator+=(DataType const& b) { value_ += b; return *this; } + BaseFloatingType& operator-=(DataType const& b) { value_ -= b; return *this; } + BaseFloatingType& operator*=(DataType const& b) { value_ *= b; return *this; } + BaseFloatingType& operator/=(DataType const& b) { value_ /= b; return *this; } +}; + + +typedef BaseNumberType Int8; //!< 8 bits integer. +typedef BaseNumberType Int16; //!< 16 bits integer. +typedef BaseNumberType Int32; //!< 32 bits integer. +typedef BaseNumberType Int64; //!< 64 bits integer. + +typedef BaseNumberType UInt8; //!< 8 bits unsigned integer. +typedef BaseNumberType UInt16; //!< 16 bits unsigned integer. +typedef BaseNumberType UInt32; //!< 32 bits unsigned integer. +typedef BaseNumberType UInt64; //!< 64 bits unsigned integer. + +typedef BaseFloatingType Float; //!< Float. +typedef BaseFloatingType Double; //!< Double. +typedef BaseFloatingType LDouble; //!< Long double. + +} // meow + +#endif // __MEOWPP_UTILITY_OBJECT_H__ diff --git a/meowpp/utility/operation.h b/meowpp/utility/operation.h new file mode 100644 index 0000000..d595668 --- /dev/null +++ b/meowpp/utility/operation.h @@ -0,0 +1,80 @@ +/*! + * @file operation.h + * @brief Contains a base class for most of all operations in meowpp. + * + * @author cathook + */ + +#ifndef __MEOWPP_UTILITY_OPERATION_H__ +#define __MEOWPP_UTILITY_OPERATION_H__ + +#include "../debug/assert.h" +#include "object.h" +#include "pointer.h" +#include "state.h" + +namespace meow { + + +/*! + * @brief Base class for operations. + */ +class Operation : public Object { + private: + int inputs_size_; + int outputs_size_; + + protected: + + /*! + * @brief A protected constructor to prevent developers create an instance of + * Operation directly. + * @param arg_inputs_size Number of inputs for the operation. + * @param arg_outputs_size Number of outputs for the operation. + */ + Operation(int arg_inputs_size, int arg_outputs_size) : + inputs_size_(arg_inputs_size), outputs_size_(arg_outputs_size) {} + + public: + + /*! + * @brief Virtual destructor. + */ + virtual ~Operation() {} + + /*! + * @brief Pure virtual method for running the operation. + * @param [in] inputs_ptr An array with each elements being a pointer points + * to the input elements. + * @param [out] outputs_ptr An array with each elements being a pointer points + * to the output elements. + * @return The state of the operation (ex: fail, success, ...) + */ + virtual State Operate(Pointer const * inputs_ptr, + Pointer const * outputs_ptr) const = 0; + + /*! + * @brief Gets the number of inputs for the operation. + * @return Number of inputs. + */ + int inputs_size() const { + return inputs_size_; + } + + /*! + * @brief Gets the number of outputs for the operation. + * @return Number of outputs. + */ + int outputs_size() const { + return outputs_size_; + } + +#ifdef MEOWPP_UTILITY_OPERATION_TESTING + friend class OperationTest; +#endif // MEOWPP_UTILITY_OPERATION_TESTING + +}; + +} // meow + +#endif // __MEOWPP_UTILITY_OPERATION_H__ diff --git a/meowpp/utility/pointer.h b/meowpp/utility/pointer.h new file mode 100644 index 0000000..3b4d08d --- /dev/null +++ b/meowpp/utility/pointer.h @@ -0,0 +1,174 @@ +/*! + * @file pointer.h + * @brief Contains a pointer class which has a counter-mechanism to prevent + * memory leak. + * + * @author cathook + */ + +#ifndef __MEOWPP_UTILITY_POINTER_H__ +#define __MEOWPP_UTILITY_POINTER_H__ + +#include +#include + +#include "object.h" + +namespace meow { + + +/*! + * @brief Types of pointer. + */ +enum PointerType { + SINGLE = 0, + ARRAY = 1 +}; + + +/*! + * @brief A pointer points to the template `Type`. + */ +template +class Pointer : public Object { + private: + struct RealPointer { + Type* address; + + //! The type of the address. + PointerType type; + + //! Whether the address should be deleted when no one points to it. + bool auto_delete; + + //! Stores number of pointers point to it. + int counter; + + RealPointer(Type* arg_address, + PointerType arg_type, + bool arg_auto_delete, + int arg_counter) : + address(arg_address), + type(arg_type), + auto_delete(arg_auto_delete), + counter(arg_counter) {} + + ~RealPointer() { + if (auto_delete) { + switch (type) { + case SINGLE: + delete address; + break; + case ARRAY: + delete [] address; + break; + } + } + } + }; + + RealPointer* ptr_; + + void Attach(RealPointer* arg_ptr2) { + ptr_ = arg_ptr2; + ptr_->counter += 1; + } + + void Detach() { + ptr_->counter -= 1; + if (ptr_->counter == 0) { + delete ptr_; + } + } + public: + /*! + * @brief Default constructor, let the pointer points to NULL. + */ + Pointer() : Pointer(NULL, SINGLE, false) {} + + /*! + * @brief Copy constructor. + */ + Pointer(Pointer const& arg_ptr) { + Attach(arg_ptr.ptr_); + } + + /*! + * @brief Constructor with gived address to point. + * + * If `arg_auto_delete` is `true`, it will automatically delete it when + * there are no instance of Pointer\ points to that `address` + * + * @param [in] arg_address Points to the address. + * @param [in] arg_type + * @param [in] arg_auto_delete + */ + Pointer(Type* arg_address, PointerType arg_type, bool arg_auto_delete) : + ptr_(new RealPointer(arg_address, arg_type, arg_auto_delete, 1)) {} + + /*! + * @brief Destructor. + */ + ~Pointer() { Detach(); } + + /*! + * @brief Gets whether it will delete the address automatically or not. + */ + bool auto_delete() const { + return ptr_->auto_delete; + } + + /*! + * @brief Gets the address it points to. + */ + Type* address() const { + return ptr_->address; + } + + /*! + * @brief Same as `address()` + */ + operator Type*() const { + return address(); + } + + /*! + * @brief Gets the pointer points to the body. + */ + Type* operator->() const { + return address(); + } + + /*! + * @brief Points to another instance of Pointer. + */ + Pointer& operator=(Pointer const& b) { + Detach(); + Attach(b.ptr_); + return *this; + } + + Object* Copy() const { + return new Pointer(*this); + } + + Object* CopyFrom(Object const* another_pointer) { + (*this) = *dynamic_cast(another_pointer); + return this; + } + + bool Equals(Object const* another_pointer) { + return (ptr_->address == + dynamic_cast(another_pointer)->ptr_->address); + } + +#ifdef MEOWPP_UTILITY_POINTER_TESTING + friend class PointerTest; +#endif // MEOWPP_UTILLITY_POINTER_TESTING + +}; + +} // meow + +#endif // __MEOWPP_UTILITY_POINTER_H__ + diff --git a/meowpp/utility/self.h b/meowpp/utility/self.h new file mode 100644 index 0000000..a98a53c --- /dev/null +++ b/meowpp/utility/self.h @@ -0,0 +1,244 @@ +/*! + * @file self.h + * @brief Contains a class for implementing a reference mechanism which allows + * variables referencing to another object anytime. + * + * @author cathook + */ + +#ifndef __MEOWPP_UTILITY_SELF_H__ +#define __MEOWPP_UTILITY_SELF_H__ + +#include + +namespace meow { + + +/*! + * @brief An implementation for the reference mechanism. + * + * Some example code: + * @code{.cpp} + * #include + * + * class A { + * private: + * + * // Data members of this class. You can also move the methods of class A + * // into this structure if you like. + * struct DataMember { + * int var1; + * int var2; + * int counter; + * + * // The constructor "Self::Self()" will call the constructor + * // "DataMember::DataMember()" + * DataMember() : var1(0), var2(0), counter(0) {} + * + * // The constructor "Self::Self(DataMember const&)" will call + * // the constructor "DataMember::DataMember(DataMember const&)" + * DataMember(DataMember const& b) : + * var1(b.var1), var2(b.var2), counter(0) {} + * + * // Customize constructor. + * DataMember(int var1_init_value) : + * var1(var1_init_value), var2(0), counter(0) {} + * + * // Destructor, will be called when nobody references to it. + * ~DataMember() {} + * + * // The "Self::CopyFrom(Self const&)" will call + * // "DataMember::CopyFrom(DataMember const&)" to copy data. + * DataMember const& CopyFrom(DataMember const& b) { + * var1 = b.var1; + * var2 = b.var2; + * } + * }; + * + * meow::Self const self_; // Use constant type to reduce the + * // protential error caused by typing + * // wrong. + * + * public: + * + * // Here the "Self::Self()" will be called. + * A() {} + * + * // Notice! "Self::Self(Self const& another_self)" will let + * // itself reference to the gived object instead of creating a new one. + * // So here the copy constructor will not copy from the gived object, it + * // will just reference from it. + * A(A const& another_class_a) : self_(another_class_a.self_) {} + * + * // Customize constructor. + * A(int var1_init_value) : self_(DataMember(var1_init_value)) {} + * + * // You don't need to call some extra function in destructor, because + * // there's a counter in the Self class. + * ~A() {} + * + * // A constant method. + * int GetVar1() const { + * return self_->var1; // Use the operator "->" to access the address of + * // the DataMember. Because we declare self_ be a + * // constant type, here "self_->var1" will also be + * // a constant. + * } + * + * // A non-constant method. + * void SetVar1(int new_value) { + * int old_value = self_->var1; + * self_()->var1 = new_value; // Use operator "()" (i.e. self_()) to + * // access the object with non-constant type, + * // so here "self_()->var1" will be a + * // non-constant variable. + * if (old_value != new_value) { + * self_()->var2 = old_value; + * //self_->var2 = old_value; // !! It cause an error because operator "()" + * // is missed if you want to modify the member + * // in the DataMember. + * } + * } + * + * int GetVar2() const { + * self_()->counter += 1; // !! It will not cause an error. Actually, + * // the "const" keyword of a method will become + * // more meanless, because inside the method, you + * // can just use self_-> or self_()-> to determind + * // whether you want to access the DataMember in + * // constant mode or not. It might be dangerous + * // but giving developer more flexable. + * return self_->var2; + * } + * }; + * @endcode + */ +template +class Self { + private: + struct Body { + int counter; + SelfType body; + + Body() : counter(1) {} + Body(SelfType const& arg_another_body) : + counter(1), body(arg_another_body) {} + }; + + Body* body_; + + /*! + * @brief Attaches to another body. + * @param arg_another_body Pointer to another body. + */ + void Attach(Body* arg_another_body) { + body_ = arg_another_body; + body_->counter += 1; + } + + /*! + * @brief Detaches from the current body. + */ + void Detach() { + body_->counter -= 1; + if (body_->counter == 0) { + delete body_; + } + } + public: + /*! + * @brief Creates a new one. + */ + Self() : body_(new Body()) {} + + /*! + * @brief Creates a new one with specifying a initial value for SelfType + * object. + * @param arg_body The initial value of the SelfType object. + */ + Self(SelfType const& arg_body) : body_(new Body(arg_body)) {} + + /*! + * @brief References from another one. + * + * @param arg_another_self Another Self object. + */ + Self(Self const& arg_another_self) { Attach(arg_another_self.body_); } + + /*! + * @brief Detatches. + * + * It will automatically clear the SelfType object when no one refernece from + * it. + */ + ~Self() { Detach(); } + + /*! + * @brief References from another Self object. + * @param arg_another_self Another Self object. + */ + Self const& ReferenceFrom(Self const& arg_another_self) { + Detach(); + Attach(arg_another_self.body_); + return *this; + } + + /*! + * @brief Copies the data in SelfType object from another Self object. + * @param arg_another_self Another Self object. + */ + Self const& CopyFrom(Self const& arg_another_self) { + body_->body.CopyFrom(arg_another_self.body_->body); + return *this; + } + + /*! + * @brief Creates a copy one of itself. + */ + Self Copy() const { return Self(body_->body); } + + /*! + * @brief Checks whether the gived instance of Self references + * from the same SelfType with me or not. + * @param arg_another_self Another instance of Self. + * @return true if we references from the same thing. + */ + bool Is(Self const& arg_another_self) const { + return (body_ == arg_another_self.body_); + } + + /*! + * @brief Access the instance of SelfType by address + */ + SelfType* operator->() { + return &(body_->body); + } + + /*! + * @brief Access the instance of SelfType by constant address + */ + SelfType const* operator->() const { + return &(body_->body); + } + + /*! + * @brief Access itself in non-constant mode. + */ + Self& operator()() const { + return *const_cast(this); + } + + /*! + * @brief Disallows the "operator=" so develops need to explicitly use + * CopyFrom/RefernceFrom. + */ + Self& operator=(Self const& b); + +#ifdef MEOWPP_UTILITY_SELF_TESTING + friend class SelfTest; +#endif // MEOWPP_UTILITY_SELF_TESTING +}; + +} // meow + +#endif // __MEOWPP_UTILITY_SELF_H__ diff --git a/meowpp/utility/state.h b/meowpp/utility/state.h new file mode 100644 index 0000000..00b79dc --- /dev/null +++ b/meowpp/utility/state.h @@ -0,0 +1,108 @@ +/*! + * @file state.h + * @brief Contains a base class for a state (in meowpp, most of all the return + * value of a function (or to say, an "operation") will be a state). + * + * @author cathook + */ + +#ifndef __MEOWPP_UTILITY_STATE_H__ +#define __MEOWPP_UTILITY_STATE_H__ + +#include "object.h" + +namespace meow { + + +/*! + * @brief The base class for state. + * + * Some example code: + * @code{.cpp} + * #include + * #include + * + * using namespace meow; + * + * class Func1State : public State { + * public: + * static const int SAME = 0; + * static const int DIFF = 1; + * }; + * + * State Func1(int a, int b) { + * if (a == b) { + * return Func1State::SAME; + * } else { + * return Func1State::DIFF; + * } + * } + * + * int main() { + * if (Func1(3, 5) == Func1State::SAME) { + * printf("same!\n"); + * } else { + * printf("diff\n"); + * } + * return 0; + * } + * @endcode + */ +class State : public Object { + private: + int value_; //!< Stores the current state. + + public: + + /*! + * @brief Default constructor. + */ + State() {} + + /*! + * @brief Copy constructor. + */ + State(State const& arg_another_state) : State(arg_another_state.value_) {} + + /*! + * @brief Constructor. + */ + State(int arg_init_value) : value_(arg_init_value) {} + + /*! + * @brief Virtual destructor. + */ + virtual ~State() {} + + /*! + * @brief Gets the integer value of the state. + */ + operator int() const { + return value_; + } + + /*! + * @brief Sets the integer value of the state. + */ + State& operator=(State const& arg_new_state) { + value_ = arg_new_state.value_; + return *this; + } + + Object* Copy() const { + return new State(value_); + } + + Object* CopyFrom(Object const* another_state) { + value_ = dynamic_cast(another_state)->value_; + return this; + } + + bool Equals(Object const* another_state) { + return (value_ == dynamic_cast(another_state)->value_); + } +}; + +} // meow + +#endif // __MEOWPP_UTILITY_STATE_H__ -- cgit v1.2.3