aboutsummaryrefslogtreecommitdiffstats
path: root/meowpp
diff options
context:
space:
mode:
authorcathook <b01902109@csie.ntu.edu.tw>2014-09-24 13:37:42 +0800
committercathook <b01902109@csie.ntu.edu.tw>2014-09-29 16:55:57 +0800
commit8b76fbb408f8eedab24195655c45c891af01eaab (patch)
tree414d7fc87885cb77e181a3ab99e334b837621036 /meowpp
parentef9af0d577c3a6b5d11fdeed7a9149d09973171b (diff)
downloadmeow-8b76fbb408f8eedab24195655c45c891af01eaab.tar
meow-8b76fbb408f8eedab24195655c45c891af01eaab.tar.gz
meow-8b76fbb408f8eedab24195655c45c891af01eaab.tar.bz2
meow-8b76fbb408f8eedab24195655c45c891af01eaab.tar.lz
meow-8b76fbb408f8eedab24195655c45c891af01eaab.tar.xz
meow-8b76fbb408f8eedab24195655c45c891af01eaab.tar.zst
meow-8b76fbb408f8eedab24195655c45c891af01eaab.zip
Big change, detail see README.
Diffstat (limited to 'meowpp')
-rw-r--r--meowpp/!readme.asciidoc20
-rw-r--r--meowpp/Usage.h478
-rw-r--r--meowpp/colors/!readme.asciidoc78
-rw-r--r--meowpp/colors/Color3_Space.h148
-rw-r--r--meowpp/colors/HSL_Space.h195
-rw-r--r--meowpp/colors/HSV_Space.h195
-rw-r--r--meowpp/colors/RGB_Space.h182
-rw-r--r--meowpp/colors/YUV_Space.h138
-rw-r--r--meowpp/debug/assert.h76
-rw-r--r--meowpp/dsa/!readme.asciidoc57
-rw-r--r--meowpp/dsa/BinaryIndexTree.h102
-rw-r--r--meowpp/dsa/DisjointSet.h135
-rw-r--r--meowpp/dsa/HashTable.h217
-rw-r--r--meowpp/dsa/KD_Tree.h303
-rw-r--r--meowpp/dsa/MergeableHeap.h168
-rw-r--r--meowpp/dsa/SegmentTree.h194
-rw-r--r--meowpp/dsa/SplayTree.h1151
-rw-r--r--meowpp/dsa/VP_Tree.h337
-rw-r--r--meowpp/geo/!readme.asciidoc12
-rw-r--r--meowpp/geo/Vectors.h505
-rw-r--r--meowpp/gra/Bitmap.h437
-rw-r--r--meowpp/gra/BitmapDescript.h51
-rw-r--r--meowpp/gra/BundleAdjustment.h105
-rw-r--r--meowpp/gra/BundleAdjustment_LM.h376
-rw-r--r--meowpp/gra/Camera.h261
-rw-r--r--meowpp/gra/Eye.h174
-rw-r--r--meowpp/gra/FeaturePoint.h262
-rw-r--r--meowpp/gra/FeaturePointsDetector.h25
-rw-r--r--meowpp/gra/FeaturePointsDetector_Harris.h365
-rw-r--r--meowpp/gra/FeaturePointsMatch.h46
-rw-r--r--meowpp/gra/FeaturePointsMatch_K_Match.h180
-rw-r--r--meowpp/gra/IdentityPoints.h392
-rw-r--r--meowpp/gra/Photo.h446
-rw-r--r--meowpp/gra/ViewPort.h19
-rw-r--r--meowpp/gra/WatchBall.h252
-rw-r--r--meowpp/math/!readme.asciidoc73
-rw-r--r--meowpp/math/LinearTransformation.h110
-rw-r--r--meowpp/math/LinearTransformations.h404
-rw-r--r--meowpp/math/Matrix.h536
-rw-r--r--meowpp/math/Transformation.h237
-rw-r--r--meowpp/math/Transformations.h550
-rw-r--r--meowpp/math/Vector.h267
-rw-r--r--meowpp/math/methods.h230
-rw-r--r--meowpp/math/utility.h157
-rw-r--r--meowpp/oo/!readme.asciidoc32
-rw-r--r--meowpp/oo/ObjArray.h168
-rw-r--r--meowpp/oo/ObjBase.h99
-rw-r--r--meowpp/oo/ObjDictionary.h167
-rw-r--r--meowpp/oo/ObjProperties.h55
-rw-r--r--meowpp/oo/ObjSelector.h214
-rw-r--r--meowpp/oo/ObjTypes.h201
-rw-r--r--meowpp/self.h346
-rw-r--r--meowpp/utility.h204
-rw-r--r--meowpp/utility/factory.h383
-rw-r--r--meowpp/utility/object.h154
-rw-r--r--meowpp/utility/operation.h80
-rw-r--r--meowpp/utility/pointer.h174
-rw-r--r--meowpp/utility/self.h244
-rw-r--r--meowpp/utility/state.h108
59 files changed, 1219 insertions, 12056 deletions
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 <cstdlib>
-
-#include <algorithm>
-#include <string>
-#include <vector>
-#include <map>
-
-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<String> 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>", 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<Value> 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_,
- "<type>",
- value_type_),
- "<values>",
- 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<String, Option> 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 \<name\> 都會被代換成空字串
- */
- Usage() {
- }
-
- /*!
- * @brief constructor
- *
- * 所有說明文字中 \a "<name>" 都會被代換成空字串 \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<String, Option>(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<String, Option>(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<String, Option>(
- 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>", name_));
- }
-
- /*!
- * @brief 新增一段usage document於每個選項逐條說明之後
- *
- * @param [in] des 要新增的usage document
- */
- void usageEndAdd(String const& des) {
- usage_end_.push_back(stringReplace(des, "<name>", 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<T>` *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 <cstdlib>
-
-namespace meow {
-
-/*!
- * @brief Base class of color space with 3 channels.
- *
- * @author cat_leopard
- */
-template<class T>
-class Color3_Space {
-protected:
- Vector3D<T> min_;
- Vector3D<T> max_;
- Vector3D<T> 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<T> const& min_bound,
- Vector3D<T> const& max_bound,
- Vector3D<T> 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<T>& copyFrom(Color3_Space<T> const& b) {
- val_ = b.val_;
- return *this;
- }
-public:
- //! @brief Destructor
- virtual ~Color3_Space() { }
-
- //! @brief minimum bound of each channels.
- Vector3D<T> const& minV() const {
- return min_;
- }
-
- //! @brief maximum bound of each channels.
- Vector3D<T> const& maxV() const {
- return max_;
- }
-
- //! @brief value of each channels.
- Vector3D<T> const& valV() const {
- return val_;
- }
-
- /*!
- * @brief Set the value of each channels.
- *
- * @param [in] vv new value
- * @return new value
- */
- Vector3D<T> const& valV(Vector3D<T> const& vv) {
- val_ = vv;
- return val();
- }
-
- //! @brief Get the non-constant reference of each channels.
- Vector3D<T>& 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 <cstdlib>
-
-namespace meow {
-
-/*!
- * @brief 以浮點數\b Y(亮度), \b U(色度), \b V(濃度) 三個值所組成的色彩空間
- *
- * 其中範圍都介於0.0~1.0之間
- *
- * @author cat_leopard
- */
-class HSLf_Space: public Color3_Space<double> {
-public:
- HSLf_Space(): Color3_Space<double>(Vector3D<double>( 0.0, 0.0, 0.0),
- Vector3D<double>(PI * 2.0, 1.0, 1.0),
- Vector3D<double>( 0.0, 0.0, 0.0)) {
- }
- HSLf_Space(double c): Color3_Space<double>(Vector3D<double>( 0.0, 0.0, 0.0),
- Vector3D<double>(PI*2.0, 1.0, 1.0),
- Vector3D<double>( c, c, c))
- { }
- HSLf_Space(Vector3D<double> const& v):
- Color3_Space<double>(Vector3D<double>(0.0, 0.0, 0.0),
- Vector3D<double>(1.0, 1.0, 1.0),
- Vector3D<double>(v)) {
- }
- HSLf_Space(HSL_Space const& b): Color3_Space<double>(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 <cstdlib>
-
-namespace meow {
-
-/*!
- * @brief 以浮點數\b Y(亮度), \b U(色度), \b V(濃度) 三個值所組成的色彩空間
- *
- * 其中範圍都介於0.0~1.0之間
- *
- * @author cat_leopard
- */
-class HSVf_Space: public Color3_Space<double> {
-public:
- HSVf_Space(): Color3_Space<double>(Vector3D<double>( 0.0, 0.0, 0.0),
- Vector3D<double>(PI*2.0, 1.0, 1.0),
- Vector3D<double>( 0.0, 0.0, 0.0)) {
- }
- HSVf_Space(double c): Color3_Space<double>(Vector3D<double>( 0.0, 0.0, 0.0),
- Vector3D<double>(PI*2.0, 1.0, 1.0),
- Vector3D<double>( c, c, c))
- { }
- HSVf_Space(Vector3D<double> const& v):
- Color3_Space<double>(Vector3D<double>(0.0, 0.0, 0.0),
- Vector3D<double>(1.0, 1.0, 1.0),
- Vector3D<double>(v)) {
- }
- HSVf_Space(HSV_Space const& b): Color3_Space<double>(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 <cstdlib>
-
-namespace meow {
-
-/*!
- * @brief 以整數 \b Red, \b Green, \b Blue 三個值所組成的色彩空間
- *
- * 其中範圍都介於0~255之間
- *
- * @author cat_leopard
- */
-class RGBi_Space: public Color3_Space<int> {
-public:
- RGBi_Space(): Color3_Space<int>(Vector3D<int>( 0, 0, 0),
- Vector3D<int>(255, 255, 255),
- Vector3D<int>( 0, 0, 0)) {
- }
- RGBi_Space(int c): Color3_Space<int>(Vector3D<int>( 0, 0, 0),
- Vector3D<int>(255, 255, 255),
- Vector3D<int>( c, c, c)) {
- }
- RGBi_Space(Vector3D<int> const& v):
- Color3_Space<int>(Vector3D<int>( 0, 0, 0),
- Vector3D<int>(255, 255, 255),
- Vector3D<int>(v)) {
- }
- RGBi_Space(RGBi_Space const& b): Color3_Space<int>(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<double> {
-public:
- RGBf_Space(): Color3_Space<double>(Vector3D<double>(0.0, 0.0, 0.0),
- Vector3D<double>(1.0, 1.0, 1.0),
- Vector3D<double>(0.0, 0.0, 0.0)) {
- }
- RGBf_Space(double c): Color3_Space<double>(Vector3D<double>(0.0, 0.0, 0.0),
- Vector3D<double>(1.0, 1.0, 1.0),
- Vector3D<double>( c, c, c)) {
- }
- RGBf_Space(Vector3D<double> const& v):
- Color3_Space<double>(Vector3D<double>(0.0, 0.0, 0.0),
- Vector3D<double>(1.0, 1.0, 1.0),
- Vector3D<double>(v)) {
- }
- RGBf_Space(RGBf_Space const& b): Color3_Space<double>(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<double>(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<double>(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 <cstdlib>
-
-namespace meow {
-
-/*!
- * @brief 以浮點數\b Y(亮度), \b U(色度), \b V(濃度) 三個值所組成的色彩空間
- *
- * 其中範圍都介於0.0~1.0之間
- *
- * @author cat_leopard
- */
-class YUVf_Space: public Color3_Space<double> {
-public:
- YUVf_Space(): Color3_Space<double>(Vector3D<double>(0.0, 0.0, 0.0),
- Vector3D<double>(1.0, 1.0, 1.0),
- Vector3D<double>(0.0, 0.0, 0.0)) {
- }
- YUVf_Space(double c): Color3_Space<double>(Vector3D<double>(0.0, 0.0, 0.0),
- Vector3D<double>(1.0, 1.0, 1.0),
- Vector3D<double>( c, c, c)) {
- }
- YUVf_Space(Vector3D<double> const& v):
- Color3_Space<double>(Vector3D<double>(0.0, 0.0, 0.0),
- Vector3D<double>(1.0, 1.0, 1.0),
- Vector3D<double>(v)) {
- }
- YUVf_Space(YUV_Space const& b): Color3_Space<double>(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 <cstdio>
+#include <cstdlib>
+
+
+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<Value>`
-
-===== DisjointSet.h
-
-用來維護一堆互斥集的資訊.
-
-.Classes
-* `meow::DisjointSet`
-
-===== HashTable.h
-
-就是傳說中的HashTable
-
-.Classes
-* `meow::HashTableList<Data, HashFunc>`
-
-===== KD_Tree.h
-
-查詢第k近鄰居用的
-
-.Classes
-* `meow::KD_Tree<Vector>`
-
-===== MergeableHeap.h
-
-可合併Heap
-
-.Classes
-* `meow::MergeableHeap<Element>`
-
-===== SegmentTree.h
-
-線段樹
-.Classes
-* `meow::SegmentTree<Value>`
-
-===== SplayTree.h
-
-伸展樹, 比一般平衡樹稍強的東東
-* `meow::SplayTree<Key, Value>`
-* `meow::SplayTree_Range<Key, Value>`
-
-===== VP_Tree.h
-
-查詢第k近鄰居用的
-
-.Classes
-* `meow::VP_Tree<Vector>`
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 <cstdlib>
-
-#include <vector>
-#include <algorithm>
-
-namespace meow {
-
-template<class Value>
-/*!
- * @brief 極度簡化的 \c SegmentTree 已無區間更新的操作
- *
- * 一般來說只能用在維護區間總和, 維護區間最大值只有在特殊情況才可以, 即
- * \b 針對每個元素, \b 每次update() \b 的值一定會大於等於原本的值 .
- * 若要用區間最大值 , 則 \a Value 的 \c operator+ 要寫成 \c std::max(...)
- *
- * @author cat_leopard
- */
-class BinaryIndexTree {
-private:
- std::vector<Value> 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 <vector>
-#include <cstdlib>
-#include <cstdio>
-
-namespace meow {
-/*!
- * @brief 用來維護一堆互斥集的資訊
- *
- * DisjointSet 是個 \b 輕量級Data \b Dtructure, 用來維護一堆互斥集的資訊. \n
- * 相關資料可參考
- * <a href="http://www.csie.ntnu.edu.tw/~u91029/DisjointSets.html">
- * 演算法筆記
- * </a>
- *
- * @note
- * - 時間複雜度 \b 非常快 表示它真的算的超級快, 可以視為常數時間
- * - 預設值所有 \a number 所在的集合的編號就是 \a number 本身,
- * 即沒有任兩個數在同一個set裡面
- *
- * @author cat_leopard
- */
-class DisjointSet {
-private:
- size_t n_;
- std::vector<size_t> father_;
- std::vector<size_t> 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 <vector>
-#include <list>
-
-namespace meow {
-
-/*!
- * @brief 一個當key相撞時會用list解決的hash_table
- *
- * @author cat_leopard
- */
-template<class Data, class HashFunc>
-class HashTableList {
-private:
- std::vector<std::list<Data> > 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<Data>::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<Data>::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<Data>::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<Data>::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<Data>::const_iterator
- it = table_[index].begin(); it != table_[index].end(); ++it) {
- if ((*it) == e)
- return true;
- }
- return false;
- }
-
- /*!
- * @brief 回傳所有存下來的資料
- */
- std::vector<Data> all() const {
- std::vector<Data> ret;
- for (size_t i = 0, I = table_.size(); i < I; i++) {
- for (std::list<Data>::const_iterator
- it = table_[i].begin(); it != table_[i].end(); ++it) {
- ret.push_back(*it);
- }
- }
- return ret;
- }
-
- /*!
- * @brief 回傳所有存下來且key為index的資料
- */
- std::vector<Data> all(size_t index) const {
- index %= table_.size();
- std::vector<Data> ret;
- for (std::list<Data>::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 <cstdlib>
-
-#include <vector>
-#include <algorithm>
-#include <queue>
-
-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 <sup>K</sup> 時才比較有優勢,
- * 當 K 逐漸變大時, 所花時間會跟暴搜沒兩樣
- *
- * @author cat_leopard
- */
-template<class Vector, class Scalar>
-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<Node> 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<Answer> AnswerV;
- typedef std::priority_queue<Answer, AnswerV, AnswerCompare> 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<Scalar>& 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<size_t>* 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<Vector>
- typedef typename std::vector<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<size_t> *orders = new std::vector<size_t>[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 v1<v2 來決定誰在前面. 最後回傳一陣列包含所有解.
- */
- Vectors query(Vector const& v,
- size_t nearestNumber,
- bool compareWholeVector) const {
- ((KD_Tree*)this)->build();
- AnswerCompare answer_compare(&nodes_, compareWholeVector);
- Answers answer_set(answer_compare);
- std::vector<Scalar> 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 <cstdlib>
-#include <algorithm>
-
-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 Element>
-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 <vector>
-#include <algorithm>
-
-#include <cstdlib>
-
-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 Value>
-class SegmentTree {
-private:
- struct Node {
- Value value_;
- Value offset_;
- bool sameFlage_;
- };
- //
- size_t size_;
- std::vector<Node> 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 <cstdlib>
-#include <utility>
-
-#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 Key, class Value>
-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<Key const&, Value&> 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<Key \c const&,\c Value&>*
- Entry* operator->() {
- return entry_;
- }
-
- //! @brief 重導至\c std::pair<Key \c const&,\c Value&>&
- 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 Key, class Value>
-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<Key const&, Value&> 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<Key \c const&,\c Value&>*
- Entry* operator->() {
- return entry_;
- }
-
- //! @brief 重導至\c std::pair<Key \c const&,\c Value&>&
- 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 <cstdlib>
-
-#include <list>
-#include <vector>
-#include <stack>
-#include <queue>
-
-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 Vector, class Scalar>
-class VP_Tree {
-public:
- typedef std::vector<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<Answer> AnswerV;
- typedef std::priority_queue<Answer, AnswerV, AnswerCompare> 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<Scalar> 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 v1<v2 來決定誰在前面. 最後回傳一陣列包含所有解.
- */
- Vectors query(Vector const& vector,
- size_t nearestNumber,
- bool compareWholeVector) const {
- ((VP_Tree*)this)->build();
- AnswerCompare cmp(&vectors_, compareWholeVector);
- Answers answers(cmp);
- query(vector, nearestNumber, cmp, root_, &answers);
- std::stack<Answer> 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<Scalar>`
-* `meow::Vector3D<Scalar>`
-
-
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 <cmath>
-
-namespace meow {
-
-/*!
- * @brief 2D's vector
- *
- * @author cat_leopard
- */
-template<class Scalar>
-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<Scalar> const& v): x_(v(0)), y_(v(1)) {
- }
-
- //! @brief constructor (from another Vector, i-th)
- Vector2D(Vector<Scalar> const& v, size_t i): x_(v(i)), y_(v(i + 1)) {
- }
-
- //! @brief constructor (from a Matrix)
- Vector2D(Matrix<Scalar> const& m): x_(m(0, 0)), y_(m(1, 0)) {
- }
-
- //! @brief constructor (from a Matrix, i-th row, j-th col)
- Vector2D(Matrix<Scalar> 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<Scalar> 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<Scalar> matrix() const {
- static Matrix<Scalar> ret(2, 1, Scalar(0));
- ret(0, 0, x());
- ret(1, 0, y());
- return ret;
- }
-
- //! @brief return a 3x1 matrix form of itself
- Matrix<Scalar> matrix(Scalar const& homo) const {
- static Matrix<Scalar> 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 Scalar>
-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<Scalar> const& v): x_(v(0)), y_(v(1)), z_(v(2)) {
- }
-
- //! @brief constructor (from another Vector, i-th)
- Vector3D(Vector<Scalar> const& v, size_t i): x_(v(i)), y_(v(i+1)), z_(v(i+2)){
- }
-
- //! @brief constructor (from a Matrix)
- Vector3D(Matrix<Scalar> 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<Scalar> 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<Scalar> matrix() const {
- static Matrix<Scalar> 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<Scalar> matrix(Scalar const& homo) const {
- static Matrix<Scalar> 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 <vector>
-#include <cmath>
-#include <string>
-#include <typeinfo>
-#include <cstdlib>
-
-namespace meow {
-
-const unsigned int kBitmapReadWritePixels = 0x1;
-
-/*!
- * @brief 二維點陣資料
- *
- * @author cat_leopard
- */
-template<class Pixel>
-class Bitmap: public ObjBase {
-private:
- Matrix<Pixel> matrix_;
-
- //! 回傳高斯模糊的權重
- static std::vector<double> gaussianFactor1(double sigma) {
- double sigma2 = squ(sigma);
- size_t width = std::max(ceil((double)(sigma * 2)), 0.0);
- std::vector<double> 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<double> gradianceFactor1(double sigma) {
- double sigma2 = squ(sigma), ss = sigma * 2;
- size_t width = std::max(ceil(ss), 1.0);
- std::vector<double> 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<double> 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<Pixel> 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<Pixel> matrix() const {
- return matrix_;
- }
-
- /*!
- * @brief 回傳矩陣形式 (non-constant form)
- */
- Matrix<Pixel>& matrixGet() {
- return matrix_;
- }
-
- /*!
- * @brief 直接設定
- */
- Matrix<Pixel> matrix(Matrix<Pixel> 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<Pixel>& 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<Pixel> 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<Pixel>& 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<Pixel>
- */
- 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<Myself const> 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<class Pixel>
-struct EyesReferenceInfo {
- unsigned long flag; //!< Flag, 定義如EyesReferenceInfoFlags
- Eye<Pixel> 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<Pixel>& 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 Pixel>
-class BundleAdjustment: public ObjBase {
-protected:
- BundleAdjustment() {
- }
-public:
- virtual ~BundleAdjustment() {
- }
-
- /*!
- * @brief 推算相機資訊
- *
- * @param [in] seq 給定一系列場景
- * @return 成功與否
- */
- virtual
- bool adjustEyes(std::vector<EyesReferenceInfo<Pixel> > seq) const {
- return false;
- }
-
- /*!
- * @brief 推算場景中的物體資訊
- *
- * 會將fixedPoints2D推算倒fixedPoints3D
- *
- * @param [in] seq 一系列場景(這裡的場景是有時間先後順序的)
- * @brief 成功與否
- */
- virtual
- bool adjustFixedPoints(std::vector<EyesReferenceInfo<Pixel> > 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 <algorithm>
-
-namespace meow {
-
-/*!
- * @brief 利用 Levenberg-Marquardt Method去推估相機旋轉角度與焦距
- *
- * @note 此方法目前只能針對相機都固定在同一點的情況下作調整
- */
-template<class Pixel>
-class BundleAdjustment_LM: public BundleAdjustment<Pixel> {
-private:
- /*
- struct MatchPair {
- size_t from_i;
- Matrix<double> from_m;
- size_t to_i;
- Matrix<double> to_m;
- };
-
- class NoOffsetController {
- private:
- std::vector<MatchPair >* pairs_;
- std::vector<Rotation3D <double> >* rot_;
- std::vector<PhotoProjection<double> >* pho_;
- BallProjection<double> bll_;
- bool flag;
- public:
- NoOffsetController(std::vector<MatchPair >* pairs,
- std::vector<Rotation3D<double> >* rot,
- std::vector<PhotoProjection<double> >* pho,
- bool fg):
- pairs_(pairs), rot_(rot), pho_(pho), bll_(3.0, 1.0), flag(fg) {
- }
- Vector<double> init() {
- if (flag == false) {
- Vector<double> 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<double> 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<double> residure(Vector<double> 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<MatchPair>::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<double> ret((*pairs_).size() * 2, 0.0);
- size_t n = 0;
- for (typename std::vector<MatchPair>::iterator
- it = (*pairs_).begin(), ed = (*pairs_).end(); it != ed; ++it, ++n) {
- Matrix<double> 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<double> jacobian() const {
- Matrix<double> 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<MatchPair>::iterator
- it = (*pairs_).begin(), ed = (*pairs_).end(); it != ed; ++it, ++n) {
- Matrix<double> tr_A( bll_ .transformate((*it).from_m));
- Matrix<double> tr_B((*rot_)[(*it).from_i].transformateInv(tr_A));
- Matrix<double> tr_C((*rot_)[(*it). to_i].transformate (tr_B));
- Matrix<double> ja_A((*pho_)[(*it). to_i].jacobian (tr_C));
- Matrix<double> ja_B((*rot_)[(*it). to_i].jacobian (tr_B));
- Matrix<double> ja_C((*rot_)[(*it).from_i].jacobianInv(tr_A));
- Matrix<double> 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<double> identity() const {
- if (flag == false) {
- Matrix<double> ret(4, 4, 0.0);
- ret.identitied();
- return ret;
- }
- Matrix<double> 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<Myself> const self;
-
-public:
- BundleAdjustment_LM(): self() {
- }
-
- BundleAdjustment_LM(BundleAdjustment_LM const& b):
- self(b.self, Self<Myself>::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<EyesReferenceInfo<Pixel> > 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<std::vector<Vector3D<double> > > points;
- // reference
- std::vector<Rotation3D <double> > rots(N);
- std::vector<PhotoProjection<double> > phos(N, PhotoProjection<double>(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<Pixel>::FixedPoints2D::IdentityPointsMapIterK FPS_K;
- std::vector<FPS_K> 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<std::vector<std::vector<MatchPair> > > 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<MatchPair > pairs;
- std::vector<Rotation3D <double> > rot;
- std::vector<PhotoProjection<double> > pho;
- std::vector<int > sum (N, 0);
- std::vector<int > big (N, 0);
- std::vector<int > real(N);
- std::vector<int > 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<EyesReferenceInfo<Pixel> > 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 Pixel>
-class Camera: public ObjBase {
-public:
- typedef IdentityPoints<int, double, Vector2D<double> > FixedPoints2D;
-private:
- struct Myself {
- Photo<Pixel> photo_;
- Rotation3D<double> rot_;
- FixedPoints2D fixed2D_;
-
- Myself(): fixed2D_(2) {
- }
-
- Myself(Myself const& v):
- photo_(v.photo_), rot_(v.rot_), fixed2D_(v.fixed2D_) {
- }
-
- ~Myself() {
- }
- };
-
- Self<Myself> const self;
-public:
- /*!
- * @brief constructor
- */
- Camera(): self() {
- }
-
- /*!
- * @brief copy constructor
- */
- Camera(Camera const& b): self(b.self, Self<Myself>::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<Pixel> photo() const {
- return self->photo_;
- }
-
- /*!
- * @brief 取得 photo (non-constant)
- */
- Photo<Pixel>& photoGet() {
- return self()->photo_;
- }
-
- /*!
- * @brief 設定 photo
- */
- Photo<Pixel> photo(Photo<Pixel> const& pho) {
- self()->photo_.copyFrom(pho);
- return photo();
- }
-
- /*!
- * @brief 取得rotation
- */
- Rotation3D<double> rotation() const {
- return self->rot_;
- }
-
- /*!
- * @brief 取得rotation (non-constant)
- */
- Rotation3D<double>& rotationGet() {
- return self()->rot_;
- }
-
- /*!
- * @brief 設定rotation
- */
- Rotation3D<double> rotation(Rotation3D<double> 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<double> fixedPoint2D(int i) {
- return self->fixed2D_.identityPoint(i);
- }
-
- /*!
- * @brief 詢問某點是否在底片範圍內
- */
- bool inside(Vector3D<double> const& p) const {
- return self->photo_.inside(
- Vector3D<double>(rotation().transformate(p.matrix())));
- }
-
- /*!
- * @brief 取得底片color
- */
- Pixel color(Vector3D<double> const& p) const {
- return self->photo_.color(
- Vector3D<double>(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 Pixel>
-class Eye: public ObjBase {
-private:
- struct Myself {
- Camera<Pixel> cam_;
- Vector3D<double> ofs_;
-
- Myself(): cam_(), ofs_(0.0, 0.0, 0.0) {
- }
-
- Myself(Camera<Pixel> const& c, Vector3D<double> const& o): cam_(c), ofs_(o){
- }
-
- Myself(Myself const& b): cam_(b.cam_), ofs_(b.ofs_) {
- }
-
- ~Myself() {
- }
- };
-
- Self<Myself> const self;
-public:
- Eye(): self() {
- }
-
- Eye(Eye const& b): self(b.self(), Self<Myself>::COPY_FROM) {
- }
-
- Eye(Camera<Pixel> const& c, Vector3D<double> 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<Pixel> camera() const {
- return self->cam_;
- }
-
- Camera<Pixel>& cameraGet() {
- return self()->cam_;
- }
-
- Camera<Pixel> camera(Camera<Pixel> const& c) {
- self()->cam_.copyFrom(c);
- return camera();
- }
-
- Vector3D<double> offset() const {
- return self->ofs_;
- }
-
- Vector3D<double>& offsetGet() {
- return self()->ofs_;
- }
-
- Vector3D<double> offset(Vector3D<double> const& ofs) {
- self()->ofs_ = ofs;
- return offset();
- }
-
- bool inside(Vector3D<double> 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 <string>
-#include <typeinfo>
-#include <cstdlib>
-#include <cstdio>
-
-namespace meow {
-
-/*!
- * @brief 特徵點
- *
- * @author cat_leopard
- */
-template <class Scalar, class Description,
- class Position = Vector<Scalar >,
- class Feature = Vector<Description> >
-
-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 <vector>
-
-namespace meow {
-
-template <class Pixel, class MyFP = FeaturePoint<double, double> >
-class FeaturePointsDetector: public ObjBase {
-protected:
- FeaturePointsDetector() { }
-public:
- virtual ~FeaturePointsDetector() { }
-
- virtual std::vector<MyFP> detect(Bitmap<Pixel> 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 <vector>
-#include <algorithm>
-
-namespace meow {
-
-/*!
- * @brief Harris-Corner-Detect algorithm for finding feature points.
- *
- * @author cat_leopard
- */
-template <class Pixel, class MyFP = FeaturePoint<double, double> >
-class FeaturePointsDetector_Harris: public FeaturePointsDetector<Pixel, MyFP> {
-# 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<Myself> const self;
-public:
- //! @brief constructor 使用預設參數
- FPD_Harris(): self() {
- }
-
- //! @brief constructor 參數複製自另一個 FeaturePointsDetector_Harris
- FPD_Harris(FPD_Harris const& fps): self(fps.self, Self<Myself>::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<FeaturePoint<double,double>> 型態的一堆特徵點
- */
- std::vector<MyFP> detect(Bitmap<Pixel> const& bmp) const {
- // blur for feature, gradiance
- Bitmap<Pixel> input (bmp.gaussian (self->featureG_, self->featureG_));
- Bitmap<Pixel> input_gx(bmp.gradianceX(0 , self->noiseN_ ));
- Bitmap<Pixel> input_gy(bmp.gradianceY(self->noiseN_ , 0 ));
-
- // get Matrix Ixx, Iyy, Ixy for each pixel
- Bitmap<Vector3D<double> > Ixys(input.height(), input.width(),
- Vector3D<double>(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<double>(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<double> R(input.height(), input.width(), 0.0);
- Bitmap<bool> 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<size_t> 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<int>(std::max<int>(self->boundB_,
- 2 * self->sizeW_),
- 2 * self->noiseN_);
- std::vector<MyFP> ret;
- Vector<double> 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<double> 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<double>(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<MyFP> operator()(Bitmap<Pixel> 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<Pixel>
- */
- ObjBase* create() const {
- return (ObjBase*)new FPD_Harris<Pixel>();
- }
-
- /*! @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 <cstdlib>
-
-namespace meow {
-
-typedef PairToPair<size_t, size_t, size_t, size_t> FeaturePointIndexPair ;
-typedef std::vector<FeaturePointIndexPair> FeaturePointIndexPairs;
-
-template<class FeaturePoint = FeaturePoint<double, double> >
-class FeaturePointsMatch: public ObjBase {
-protected:
- FeaturePointsMatch() {
- }
-public:
- typedef std::vector<FeaturePoint > FeaturePoints;
- typedef std::vector<FeaturePoints> 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 <cstdlib>
-
-namespace meow {
-
-template <class Scalar, class Description,
- class FeaturePoint = FeaturePoint<Scalar, Description> >
-class FeaturePointsMatch_K_Match: public FeaturePointsMatch<FeaturePoint> {
-# define FPMKM FeaturePointsMatch_K_Match
-public:
- typedef std::vector<FeaturePoint > FeaturePoints ;
- typedef std::vector<FeaturePoints> 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<Myself> const self;
-public:
- FPMKM(): self() {
- }
-
- FPMKM(FPMKM const& m): self(m.self, Self<Myself>::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<Node, Description> 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<Node> 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 <map>
-#include <set>
-#include <utility>
-
-#include <cstdlib>
-
-namespace meow {
-
-/*!
- * @brief 把一個 \c std::map<Identity, Point > 包起來
- *
- * @author cat_leopard
- */
-template<class Identity, class Scalar, class Point = Vector<Scalar> >
-class IdentityPoints: public ObjBase {
-public:
-
- typedef typename std::vector<Identity> Identities;
- typedef typename std::vector<Point> Points;
-
- typedef typename std::pair<Identity, Point> IdentityPointPair;
- typedef typename std::vector<IdentityPointPair> IdentityPointPairs;
-
- typedef typename std::pair<Point, Point> PointPair;
- typedef typename std::vector<PointPair> PointPairs;
-
-private:
- typedef typename std::map<Identity, Point> 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<Myself> const self;
-public:
- /*!
- * @brief setup dimension
- */
- IdentityPoints(size_t d): self(Myself(d)) {
- }
-
- /*!
- * @brief constructor, 並且複製資料
- */
- IdentityPoints(IdentityPoints const& b):
- self(b.self, Self<Myself>::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<Pixel>
- */
- 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 <vector>
-#include <cmath>
-#include <string>
-#include <typeinfo>
-#include <cstdlib>
-
-namespace meow {
-
-/*!
- * @brief 底片
- *
- * 基本上就是一個 \c Bitmap 加上 \c focal
- *
- * @author cat_leopard
- */
-template<class Pixel>
-class Photo: public ObjBase {
-private:
- struct Myself {
- Bitmap<Pixel> bmp_;
- Vector2D<double> c_;
- PhotoProjection<double> proj_;
-
- Myself(): proj_(3) {
- }
-
- Myself(Myself const& b): bmp_(b.bmp_), c_(b.c_), proj_(b.proj_) {
- }
-
- ~Myself() {
- }
- };
-
- Self<Myself> const self;
-
- /*!
- * @brief 取得bitmap座標
- */
- Vector2D<double> bitmapCoord(Vector2D<double> const& yx) const {
- return Vector2D<double>(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<Myself>::COPY_FROM) {
- }
-
- /*!
- * @brief constructor
- *
- * 直接給定圖片, 焦距用猜的
- *
- * @param [in] bmp 給定的圖片
- */
- Photo(Bitmap<Pixel> const& bmp): self() {
- reset(bmp);
- }
-
- /*!
- * @brief constructor
- *
- * 直接給定圖片與焦距
- *
- * @param [in] bmp 給定的圖片
- * @param [in] f 給定的焦距
- */
- Photo(Bitmap<Pixel> const& bmp, double f): self() {
- reset(bmp, f);
- }
-
- /*!
- * @brief constructor
- *
- * 直接給定圖片, 焦距與中心點位置
- *
- * @param [in] bmp 給定的圖片
- * @param [in] f 給定的焦距
- * @param [in] c 中心點作標
- */
- Photo(Bitmap<Pixel> const& bmp, double f, Vector2D<double> 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<Pixel> const& bmp) {
- bitmap(bmp);
- focal(sqrt(squ(width()) + squ(height())));
- center(Vector2D<double>(bmp.width() / 2, bmp.height() / 2));
- }
-
- /*!
- * @brief 重設bitmap, focal
- *
- * center代bitmap中心點
- *
- * @param [in] bmp 新的 \c bitmap
- * @param [in] f 新的 \c focal
- */
- void reset(Bitmap<Pixel> const& bmp, double f) {
- bitmap(bmp);
- focal(f);
- center(Vector2D<double>(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<Pixel> const& bmp, double f, Vector2D<double> const& c) {
- bitmap(bmp);
- focal(f);
- center(c);
- }
-
- /*!
- * @brief 回傳\c bitmap
- */
- Bitmap<Pixel> bitmap() const {
- return self->bmp_;
- }
-
- /*!
- * @brief 回傳\c bitmap 的參照(非constant)
- */
- Bitmap<Pixel>& bitmapGet() {
- return self()->bmp_;
- }
-
- /*!
- * @brief 設定bitmap
- *
- * @param [in] bmp 新的 bitmap
- * @return 新的 \c bitmap
- */
- Bitmap<Pixel> bitmap(Bitmap<Pixel> 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<double> projection() const {
- return self->proj_;
- }
-
- /*!
- * @brief 設定 photo projection
- */
- PhotoProjection<double> projection(PhotoProjection<double> const& p) {
- if (p.dimension() == 3) {
- self()->proj_ = p;
- }
- return projection();
- }
-
- /*!
- * @brief 取得照片中心點底片座標
- *
- * @return 一個二維vector
- */
- Vector2D<double> center() const {
- return self->c_;
- }
-
- /*!
- * @brief 取得照片中心點底片座標 (non-constant reference)
- *
- * @return 一個二維vector
- */
- Vector2D<double>& centerGet() {
- return self()->c_;
- }
-
- /*!
- * @brief 設定照片中心點底片座標
- *
- * @param [in] c 新的座標
- *
- * @return 新的座標
- */
- Vector2D<double> center(Vector2D<double> 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<double> const& yx) const {
- Vector2D<double> 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<double> const& p) const {
- if (p.z() > 0) return false;
- return inside(Vector2D<double>(self->proj_.transformate(p.matrix())));
- }
-
- /*!
- * @brief 取得給照片座標中某點的色彩
- *
- * 用浮點數vector傳入, 所以色彩是經過渲染過的
- *
- * @param [in] yx 底片座標(原點為center)
- *
- * @return pixel
- */
- Pixel color(Vector2D<double> const& yx) const {
- if (!inside(yx)) return Pixel(0);
- Vector2D<double> 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<double> const& p) const {
- return color(Vector2D<double>(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<Pixel>
- */
- 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 <cmath>
-#include <vector>
-
-namespace meow {
-
-/*!
- * @brief \b 多個camera, 一個offset, 一個rotation
- *
- * @author cat_leopard
- */
-template<class Pixel>
-class WatchBall: public ObjBase {
-public:
- typedef std::vector<Camera<Pixel> > Cameras;
-private:
- struct Myself {
- Cameras cameras_;
- Vector3D<double> offset_;
-
- Myself() {
- }
-
- Myself(Myself const& b): cameras_(b.cameras_), offset_(b.offset_) {
- }
-
- ~Myself() {
- }
- };
-
- Self<Myself> const self;
-public:
- /*!
- * @brief constructor
- */
- WatchBall(): self() {
- }
-
- /*!
- * @brief copy constructor
- */
- WatchBall(WatchBall const& b): self(b.self, Self<Myself>::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<Pixel> camera(size_t i) const {
- return cameras()[i];
- }
-
- /*!
- * @brief 取得第i個camera (non-constant reference)
- */
- Camera<Pixel>& cameraGet(size_t i) {
- return cameras()[i];
- }
-
- /*!
- * @brief 設定第i個camera
- */
- Camera<Pixel> camera(size_t i, Camera<Pixel> const& c) {
- cameras()[i] = c;
- return camera(i);
- }
-
- /*!
- * @brief 取得offset
- */
- Vector3D<double> offset() const {
- return self->offset_;
- }
-
- /*!
- * @brief 取得offset (non-constant reference)
- */
- Vector3D<double>& offsetGet() {
- return self()->offset_;
- }
-
- /*!
- * @brief 設定offset
- */
- Vector3D<double> offset(Vector3D<double> const& ofs) {
- self()->offset_ = ofs;
- return offset();
- }
-
- /*!
- * @brief 取得底片color
- */
- Pixel color(Vector3D<double> p) const {
- Vector3D<double> 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<Pixel> expand(double radius) const {
- radius = std::max(radius, 0.5);
- size_t height = std::max<size_t>(1, 2.0 * radius);
- size_t width = 2.0* PI * radius;
- Bitmap<Pixel> 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<double>(
- 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<Entry>`
-
-===== Vector.h
-
-實作上將 *Matrix* 重新包裝
-
-.Classes
-* `meow::Vector<Scalar>`
-
-===== Transformation.h
-
-各種轉換的 Base Class, 這裡所謂的 *Transformation* 形式上不一定要是 Linear,
-但原則上都是 *input a vector, output a vector* 其中input/output的dimension可以
-不同.
-
-.Classes
-* `meow::Transformation<Scalar>`
-
-===== Transformations.h
-
-包含各種 *Non-Linear* transformation
-
-.Classes
-* `meow::BallProjection<Scalar>`
-* `meow::PhotoProjection<Scalar>`
-
-===== LinearTransformation.h
-
-各種 LinearTransformation 的Base Class, 繼承自 `meow::Transformation`
-
-.Classes
-* `meow::LinearTransformation<Scalar>`
-
-===== LinearTransformations.h
-
-各種 *Linear* Transformation
-
-.Classes
-* `meow::Rotation3D<Scalar>`
-
-===== 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 <cstdlib>
-
-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 Scalar>
-class LinearTransformation: public Transformation<Scalar> {
-private:
- Matrix<Scalar> matrix_;
-protected:
- /*!
- * Constructor with input/output size gived
- */
- LinearTransformation(size_t inputRows, size_t outputRows, size_t psize):
- Transformation<Scalar>(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<Scalar> const& m):
- Transformation<Scalar>(inputRows, 1u, outputRows, 1u, psize),
- matrix_(m) {
- }
-
- /*!
- * Constructor with another LinearTransformation
- *
- * @param [in] b another LinearTransformation
- */
- LinearTransformation(LinearTransformation const& b):
- Transformation<Scalar>(b),
- matrix_(b.matrix_) {
- }
-
- /*!
- * @brief Copy settings, matrix from another LinearTransformation
- *
- * @param [in] b another LinearTransformation
- */
- LinearTransformation& copyFrom(LinearTransformation const& b) {
- Transformation<Scalar>::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<Scalar>::referenceFrom(b);
- matrix_.referenceFrom(b.matrix_);
- return *this;
- }
-
- /*!
- * @brief setup the matrix
- */
- virtual Matrix<Scalar> const& matrix(Matrix<Scalar> const& m) {
- matrix_.copyFrom(m);
- return matrix();
- }
-
-public:
- /*!
- * Destructor
- */
- virtual ~LinearTransformation() {
- }
-
- /*!
- * @brief Return the matrix form of this transformation
- *
- * @return A matrix
- */
- virtual Matrix<Scalar> const& matrix() const {
- return matrix_;
- }
-
- /*!
- * @brief Return the inverse of the matrix form of this transformate
- *
- * @return A matrix (may be invalid)
- */
- virtual Matrix<Scalar> 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 <cstdlib>
-
-namespace meow {
-
-/*!
- * @brief Rotation a point/vector alone an axis with given angle in 3D world.
- *
- * @author cat_leopard
- */
-template<class Scalar>
-class Rotation3D: public LinearTransformation<Scalar> {
-private:
- struct Myself {
- Vector3D<Scalar> theta_;
- bool need_;
-
- Myself(): theta_(0, 0, 0), need_(true) {
- }
-
- Myself(Myself const& b): theta_(b.theta_), need_(b.need_) {
- }
-
- ~Myself() {
- }
- };
-
- Self<Myself> const self;
-
- void calcMatrix() const {
- if (self->need_) {
- Matrix<Scalar> tmp(3, 3, 0.0);
- if (noEPS(self->theta_.length2()) == 0) {
- tmp.identitied();
- }
- else {
- Vector3D<double> 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<Scalar>::matrix(tmp);
- self()->need_ = false;
- }
- }
-
-public:
- /*!
- * Constructor with no rotation
- */
- Rotation3D(): LinearTransformation<Scalar>(3u, 3u, 3u), self() {
- }
-
- /*!
- * Constructor and copy data
- */
- Rotation3D(Rotation3D const& b): LinearTransformation<Scalar>(b),
- self(b.self, Self<Myself>::COPY_FROM) {
- }
-
- /*!
- * Destructor
- */
- ~Rotation3D() {
- }
-
- /*!
- * @brief Copy data
- *
- * @param [in] b another Rotation3D class.
- * @return \c *this
- */
- Rotation3D& copyFrom(Rotation3D const& b) {
- LinearTransformation<Scalar>::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<Scalar>::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<Scalar> const& axis, Scalar const& angle) {
- Vector<Scalar> 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<Scalar> transformate(Matrix<Scalar> const& x) const {
- calcMatrix();
- return LinearTransformation<Scalar>::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<Scalar> jacobian(Matrix<Scalar> const& x) const {
- calcMatrix();
- return LinearTransformation<Scalar>::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<Scalar> jacobian(Matrix<Scalar> const& x, size_t i) const {
- calcMatrix();
- Matrix<Scalar> 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<Scalar>::matrix() * x;
- }
-
- /*!
- * @brief Do the inverse transformate
- *
- * @param [in] x the input vector
- * @return the output vector
- */
- Matrix<Scalar> transformateInv(Matrix<Scalar> 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<Scalar> jacobianInv(Matrix<Scalar> 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<Scalar> jacobianInv(Matrix<Scalar> const& x, size_t i) const {
- calcMatrix();
- Matrix<Scalar> 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<Scalar> matrixInv() const {
- calcMatrix();
- return LinearTransformation<Scalar>::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 <vector>
-#include <algorithm>
-
-#include <cstdlib>
-
-namespace meow {
-/*!
- * @brief \b matrix
- *
- * @author cat_leopard
- */
-template<class Entry>
-class Matrix {
-public:
- typedef typename std::vector<Entry>::reference EntryRef ;
- typedef typename std::vector<Entry>::const_reference EntryRefK;
-private:
- struct Myself {
- size_t rows_;
- size_t cols_;
- std::vector<Entry> 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<Entry> tmp(entries_);
- entries_.swap(tmp);
- }
- };
-
- Self<Myself> 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<Myself>::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<Myself> const old(self, Self<Myself>::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<Entry>();
- 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<Entry>();
- 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<Entry> 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 <list>
-#include <cstdlib>
-
-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 Scalar>
-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<Myself> 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<Myself>::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<Scalar> transformate(Matrix<Scalar> 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<Scalar> jacobian(Matrix<Scalar> const& x) const {
- return Matrix<Scalar>();
- }
-
- /*!
- * @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<Scalar> jacobian(Matrix<Scalar> const& x, size_t i) const {
- return Matrix<Scalar>();
- }
-
- /*!
- * @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<Scalar> transformateInv(Matrix<Scalar> const& x) const {
- return Matrix<Scalar>();
- }
-
- /*!
- * @brief Return the jacobian matrix of the inverse transformation
- *
- * @param [in] x The input matirx
- * @return An empty matrix
- */
- virtual Matrix<Scalar> jacobianInv(Matrix<Scalar> const& x) const {
- return Matrix<Scalar>();
- }
-
- /*!
- * @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<Scalar> jacobianInv(Matrix<Scalar> const& x, size_t i) const {
- return Matrix<Scalar>();
- }
-};
-
-} // 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 <cstdlib>
-
-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 Scalar>
-class BallProjection: public Transformation<Scalar> {
-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<Myself> const self;
-public:
- /*!
- * Constructor, copy settings from given BallProjection
- * @param [in] b another ball projection class
- */
- BallProjection(BallProjection const& b): Transformation<Scalar>(b),
- self(b.self, Self<Myself>::COPY_FROM) {
- }
-
- /*!
- * Constructor and setup, radius = 1
- * @param [in] d Dimension of the input/output vector
- */
- BallProjection(size_t d): Transformation<Scalar>(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<Scalar>(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<Scalar>::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<Scalar>::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<Scalar> transformate(Matrix<Scalar> const& x) const {
- Matrix<Scalar> 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<Scalar> jacobian(Matrix<Scalar> 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<Scalar> 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<Scalar> jacobian(Matrix<Scalar> const& x, size_t i) const {
- Matrix<Scalar> 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<Scalar> operator()(Matrix<Scalar> 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 Scalar>
-class PhotoProjection: public Transformation<Scalar> {
-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<Myself> const self;
-public:
- /*!
- * Constructor, focal = 1
- */
- PhotoProjection(size_t dimension):
- Transformation<Scalar>(dimension, 1, dimension, 1, 1),
- self(Myself(dimension, 1)) {
- }
-
- /*!
- * Constructor
- */
- PhotoProjection(size_t dimension, Scalar const& f):
- Transformation<Scalar>(dimension, 1, dimension, 1, 1),
- self(Myself(dimension, f)) {
- }
-
- /*!
- * Constructor, copy settings from another PhotoProjection.
- */
- PhotoProjection(PhotoProjection const& p): Transformation<Scalar>(p),
- self(p.self, Self<Myself>::COPY_FROM) {
- }
-
- /*!
- * Copy settings from another one
- * @param [in] b another one
- * @return \c *this
- */
- PhotoProjection& copyFrom(PhotoProjection const& b) {
- Transformation<Scalar>::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<Scalar>::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<Scalar> transformate(Matrix<Scalar> const& x) const {
- Matrix<Scalar> 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<Scalar> jacobian(Matrix<Scalar> const& x) const{
- Matrix<Scalar> 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<Scalar> jacobian(Matrix<Scalar> const& x, size_t i) const{
- Matrix<Scalar> 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<Scalar> operator()(Matrix<Scalar> 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 <vector>
-
-#include <cmath>
-
-namespace meow {
-
-/*!
- * @brief \b vector
- *
- * @author cat_leopard
- */
-template<class Scalar>
-class Vector {
-public:
- typedef typename Matrix<Scalar>::EntryRefK ScalarRefK;
- typedef typename Matrix<Scalar>::EntryRef ScalarRef ;
-private:
- Matrix<Scalar> 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<Scalar> const& m): matrix_(m.col(0)) {
- }
-
- /*!
- * @brief constructor
- *
- * Copy from another std::vector
- *
- * @param [in] v vector
- */
- Vector(std::vector<Scalar> 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<Scalar> 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 <cstdlib>
-#include <vector>
-
-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<class Data, class WeightingClass>
-inline std::vector<Data> ransac(std::vector<Data> const& data,
- WeightingClass const& w,
- size_t N,
- double p0, double P) {
- if (data.size() < N) {
- return std::vector<Data>();
- }
- double ww = -1.0;
- std::vector<Data> ret;
- for (double count = ceil(log(1.0 - P) / log(1.0 - pow(p0, N)));
- count > 0.0; count -= 1.0) {
- std::vector<Data> sample;
- std::vector<int> 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<class Scalar, class Function>
-inline Vector<Scalar> levenbergMarquardt(Function const& f,
- Vector<Scalar> const& init,
- int counter = -1) {
- Vector<Scalar> ans(init), residure_v;
- for ( ; counter != 0 && !f.accept(residure_v = f.residure(ans)); --counter) {
- Matrix<Scalar> m_j (f.jacobian(ans));
- Matrix<Scalar> m_jt(m_j.transpose());
- Matrix<Scalar> 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<class Scalar, class Function>
-inline Vector<Scalar> levenbergMarquardtTraining(Function & f,
- Vector<Scalar> 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<Scalar> ans_now(init), rv_now(f.residure(ans_now));
- Vector<Scalar> ans_nxt , rv_nxt;
- Scalar er_now(rv_now.length2());
- Scalar er_nxt;
- Vector<Scalar> ans_best(ans_now);
- Scalar er_best ( er_now);
- Matrix<Scalar> 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 <cstdlib>
-#include <vector>
-#include <algorithm>
-#include <cmath>
-
-namespace meow {
-
-//! 圓周率...
-static const double PI = 3.14159265358979323846264338327950288;
-
-/*!
- * @brief 將角度調整於0~2PI
- */
-template<class T>
-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<class T>
-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<class T>
-inline T normalize(T lower, T upper, T value) {
- return (value - lower) / (upper - lower);
-}
-
-/*!
- * @brief \c (lower+_ratio*(upper-lower))
- */
-template<class T>
-inline T denormalize(T lower, T upper, T _ratio) {
- return lower + _ratio * (upper - lower);
-}
-
-/*!
- * @brief \c denormalize(l2,u2,normalize(l1,u1,m1))
- */
-template<class T>
-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<class T>
-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<class T>
-inline T isInRange(T const& mn, T const& mx, T const& x) {
- return (mn <= x && x <= mx);
-}
-
-/*!
- * @brief \c x*x
- */
-template<class T>
-inline T squ(T const& x) {
- return x * x;
-}
-
-/*!
- * @brief \c x*x*x
- */
-template<class T>
-inline T cub(T const& x) {
- return x * x * x;
-}
-
-/*!
- * @brief 只將 \c sigs 個標準差以內的數據拿來取平均
- */
-template<class T>
-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<class T>
-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<class T>
-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<SID>`
-
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 <vector>
-#include <string>
-#include <typeinfo>
-
-#include <cstdio>
-#include <cstdlib>
-
-namespace meow {
-
-/*!
- * @brief 純粹把 \c std::vector 包起來, 變成繼承自 ObjBase
- *
- * @author cathook
- */
-template<class T>
-class ObjArray: public ObjBase {
-private:
- struct Myself {
- std::vector<T> array_;
-
- Myself() {
- }
-
- Myself(Myself const& b): array_(b.array_) {
- }
-
- Myself(size_t sz, T const& e): array_(sz, e) {
- }
-
- ~Myself() {
- }
- };
- Self<Myself> const self;
-public:
- ObjArray(): self() {
- }
-
- ObjArray(ObjArray const& a): self(a.self, Self<Myself>::COPY_FROM) {
- }
-
- ObjArray(std::vector<T> 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<T>::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 <cstdio>
-#include <typeinfo>
-#include <string>
-
-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 <string>
-#include <typeinfo>
-#include <map>
-
-#include <cstdio>
-#include <cstdlib>
-
-namespace meow {
-
-/*!
- * @brief 純粹把 \c std::map 包起來, 變成繼承自 ObjBase
- *
- * @author cathook
- */
-template<class Key, class Value>
-class ObjDictionary: public ObjBase {
-private:
- struct Myself {
- std::map<Key, Value> dictionary_;
-
- Myself() {
- }
-
- Myself(Myself const& b): dictionary_(b.dictionary_) {
- }
-
- ~Myself() {
- }
- };
-
- Self<Myself> const self;
-public:
- ObjDictionary(): self() {
- }
-
- ObjDictionary(ObjDictionary const& d): self(d.self, Self<Myself>::COPY_FROM) {
- self.copyFrom(b.self);
- }
-
- ObjDictionary(std::map<Key, Value> 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<Key, Value>::const_iterator first() const {
- return self()->dictionary_.begin();
- }
-
- std::map<Key, Value>::iterator first() {
- return self()->dictionary_.begin();
- }
-
- std::map<Key, Value>::const_iterator end() const {
- return self()->dictionary_.end(); // OAO!!!
- }
-
- std::map<Key, Value>::iterator end() {
- return self()->dictionary_.end();
- }
-
- std::map<Key, Value>::const_iterator find(Key const& k) const {
- return self()->dictionary_.find(k); // OAO!!!
- }
-
- std::map<Key, Value>::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<Key, Value>(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<Key, Value>::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 <cstdlib>
-
-namespace meow {
-
-template<size_t SID>
-
-//! 目前擺爛中
-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 <utility>
-#include <vector>
-#include <string>
-#include <map>
-
-#include <cstdlib>
-#include <cstdio>
-
-namespace meow {
-
-/*!
- * @brief 利用register的概念, 達到runtime用string選擇要new的class
- *
- * @author cathook
- */
-template<size_t id> //!< 讓程式可以有不只一個 \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<std::string, Info*> Infos;
- typedef typename std::map<std::string, Info*>::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<std::string, Info*> 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<std::string> names() {
- std::vector<std::string> 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 <cstdlib>
-#include <cstdio>
-
-namespace meow {
-
-/*!
- * @brief 純粹把給定的 \c Type 包起來, 變成繼承自 ObjBase
- *
- * @author cathook
- */
-template<class Type, class ReaderWriter>
-class ObjType: public ObjBase {
-private:
- struct Myself {
- Type data_;
-
- Myself() {
- }
-
- Myself(Type const& t): data_(t) {
- }
-
- ~Myself() {
- }
- };
- Self<Type> 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<Type>::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<int , ReaderWriter_int > ObjInt;
-typedef ObjType<size_t , ReaderWriter_size_t> ObjSizeT;
-typedef ObjType<double , ReaderWriter_double> ObjDouble;
-typedef ObjType<std::string, ReaderWriter_string> 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 <cstdlib>
-#include <algorithm>
-
-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<Myself> 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<Myself> 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 Data>
-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 <cstdlib>
-#include <cstring>
-#include <cstdio>
-#include <cstdarg>
-
-#include <string>
-
-namespace meow {
-
-/*!
- * @brief A structur with memember \c .from.first , \c .from.second ,
- * \c .to.first , \c .to.second
- *
- * @author cathook
- */
-template<class F1, class F2 = F1, class T1 = F1, class T2 = T1>
-struct PairToPair {
- std::pair<F1, F2> from;
- std::pair<T1, T2> 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<Operation const> oper;
+ Pointer<Pointer<Object const>> inputs;
+ Pointer<Pointer<Object>> outputs;
+
+ //! An array with each elements points to the input elements with
+ //! non-constant type.
+ Pointer<Pointer<Object>> non_const_inputs;
+
+ //! An array with each elements points to the output elements with
+ //! constant type.
+ Pointer<Pointer<Object const>> 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<Operation const> const& arg_oper,
+ Pointer<Pointer<Object const>> const& arg_inputs,
+ Pointer<Pointer<Object>> const& arg_outputs):
+ oper(arg_oper),
+ inputs(arg_inputs),
+ outputs(arg_outputs),
+ non_const_inputs(new Pointer<Object>[oper->inputs_size()], ARRAY, true),
+ const_outputs(
+ new Pointer<Object const>[oper->outputs_size()], ARRAY, true) {
+ for (int i = 0, i_max = oper->inputs_size(); i < i_max; ++i) {
+ non_const_inputs[i] = Pointer<Object>(
+ const_cast<Object*>(inputs[i].address()), SINGLE, false);
+ }
+ for (int i = 0, i_max = oper->outputs_size(); i < i_max; ++i) {
+ const_outputs[i] = Pointer<Object const>(
+ 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> operation() const = 0;
+
+ /*!
+ * @brief Gets the pointer points to the array of input elements.
+ */
+ virtual Pointer<Pointer<Object>> inputs() const = 0;
+
+ /*!
+ * @brief Gets the pointer points to the array of output elements.
+ */
+ virtual Pointer<Pointer<Object const>> 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<Operation const> const& arg_oper,
+ Pointer<Pointer<Object const>> const& arg_inputs,
+ Pointer<Pointer<Object>> const& arg_outputs) :
+ BaseData(arg_oper, arg_inputs, arg_outputs) {}
+ };
+
+ Self<Data> 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<Operation const> const& arg_oper,
+ Pointer<Pointer<Object const>> const& arg_inputs,
+ Pointer<Pointer<Object>> 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> operation() const {
+ return self_->oper;
+ }
+
+ /*!
+ * @brief Gets the pointer points to the array of input elements.
+ */
+ Pointer<Pointer<Object>> inputs() const {
+ return self_->non_const_inputs;
+ }
+
+ /*!
+ * @brief Gets the pointer points to the array of output elements.
+ */
+ Pointer<Pointer<Object const>> 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<Pointer<Object>> 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<Operation const> const& arg_oper,
+ Pointer<Pointer<Object const>> const& arg_inputs,
+ Pointer<Pointer<Object>> const& arg_outputs) :
+ BaseData(arg_oper, arg_inputs, arg_outputs),
+ old_inputs(new Pointer<Object>[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<Object>(inputs[i]->Copy(), SINGLE, true);
+ }
+ }
+ };
+
+ Self<Data> 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<Operation const> const& arg_oper,
+ Pointer<Pointer<Object const>> const& arg_inputs,
+ Pointer<Pointer<Object>> 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> operation() const {
+ return self_->oper;
+ }
+
+ /*!
+ * @brief Gets the array of the input elements.
+ */
+ Pointer<Pointer<Object>> inputs() const {
+ return self_->non_const_inputs;
+ }
+
+ /*!
+ * @brief Gets the array of the output elements.
+ */
+ Pointer<Pointer<Object const>> 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_types::Base> factory_;
+
+ public:
+
+ /*!
+ * @brief Constructor.
+ */
+ Factory(Pointer<Operation const> const& arg_oper,
+ Pointer<Pointer<Object const>> const& arg_inputs,
+ Pointer<Pointer<Object>> const& arg_outputs,
+ bool arg_check_before_update) {
+ if (arg_check_before_update) {
+ factory_ = Pointer<factory_types::Base>(
+ new factory_types::CheckOn(
+ arg_oper, arg_inputs, arg_outputs), SINGLE, true);
+ } else {
+ factory_ = Pointer<factory_types::Base>(
+ 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> operation() const {
+ return factory_->operation();
+ }
+
+ /*!
+ * @brief Gets the array of the input elements.
+ */
+ Pointer<Pointer<Object>> inputs() const {
+ return factory_->inputs();
+ }
+
+ /*!
+ * @brief Gets the array of the output elements.
+ */
+ Pointer<Pointer<Object const>> 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 <cstdlib>
+#include <cstdint>
+
+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<typename DataType>
+class BaseNumberType : public Object {
+ private:
+ DataType value_;
+ public:
+ BaseNumberType() : BaseNumberType(static_cast<DataType>(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<BaseNumberType const*>(ptr)->value_;
+ return this;
+ }
+ bool Equals(Object const* ptr) const {
+ return (value_ == static_cast<BaseNumberType const*>(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<typename DataType>
+class BaseFloatingType : public Object {
+ private:
+ DataType value_;
+ public:
+ BaseFloatingType() : BaseFloatingType(static_cast<DataType>(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<BaseFloatingType const*>(ptr)->value_;
+ return this;
+ }
+ bool Equals(Object const* ptr) const {
+ return (value_ == static_cast<BaseFloatingType const*>(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_t> Int8; //!< 8 bits integer.
+typedef BaseNumberType<int16_t> Int16; //!< 16 bits integer.
+typedef BaseNumberType<int32_t> Int32; //!< 32 bits integer.
+typedef BaseNumberType<int64_t> Int64; //!< 64 bits integer.
+
+typedef BaseNumberType<uint8_t> UInt8; //!< 8 bits unsigned integer.
+typedef BaseNumberType<uint16_t> UInt16; //!< 16 bits unsigned integer.
+typedef BaseNumberType<uint32_t> UInt32; //!< 32 bits unsigned integer.
+typedef BaseNumberType<uint64_t> UInt64; //!< 64 bits unsigned integer.
+
+typedef BaseFloatingType<float> Float; //!< Float.
+typedef BaseFloatingType<double> Double; //!< Double.
+typedef BaseFloatingType<long double> 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<Object const> const * inputs_ptr,
+ Pointer<Object> 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 <cstddef>
+#include <cstdlib>
+
+#include "object.h"
+
+namespace meow {
+
+
+/*!
+ * @brief Types of pointer.
+ */
+enum PointerType {
+ SINGLE = 0,
+ ARRAY = 1
+};
+
+
+/*!
+ * @brief A pointer points to the template `Type`.
+ */
+template<typename Type>
+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\<Type\> 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<Pointer const*>(another_pointer);
+ return this;
+ }
+
+ bool Equals(Object const* another_pointer) {
+ return (ptr_->address ==
+ dynamic_cast<Pointer const*>(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 <cstdlib>
+
+namespace meow {
+
+
+/*!
+ * @brief An implementation for the reference mechanism.
+ *
+ * Some example code:
+ * @code{.cpp}
+ * #include <meowpp/utility/self.h>
+ *
+ * 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<DataMember>::Self()" will call the constructor
+ * // "DataMember::DataMember()"
+ * DataMember() : var1(0), var2(0), counter(0) {}
+ *
+ * // The constructor "Self<DataMember>::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<DataMember>::CopyFrom(Self<DataMember> const&)" will call
+ * // "DataMember::CopyFrom(DataMember const&)" to copy data.
+ * DataMember const& CopyFrom(DataMember const& b) {
+ * var1 = b.var1;
+ * var2 = b.var2;
+ * }
+ * };
+ *
+ * meow::Self<DataMember> const self_; // Use constant type to reduce the
+ * // protential error caused by typing
+ * // wrong.
+ *
+ * public:
+ *
+ * // Here the "Self<DataMember>::Self()" will be called.
+ * A() {}
+ *
+ * // Notice! "Self<DataMember>::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<typename SelfType>
+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<Self*>(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 <meowpp/utility/state.h>
+ * #include <cstdio>
+ *
+ * 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<State const*>(another_state)->value_;
+ return this;
+ }
+
+ bool Equals(Object const* another_state) {
+ return (value_ == dynamic_cast<State const*>(another_state)->value_);
+ }
+};
+
+} // meow
+
+#endif // __MEOWPP_UTILITY_STATE_H__