- 二维平面中二维向量的叉乘 得到的向量,x、y方向上的分量必定为0,
所以可以用z的值判断一个向量在另一个向量的左侧还是右侧。

- 推导(其实这个是二维上的定义,先用二维的推出来的三维,我用三维反过来理解二维。。):
由于z1 = z2 = 0,那么 axb = k(x1y2 - y1x2)
只存在z轴上的分量。
#define _VecTypeName double
class Solution {
public:
template <typename T>
T dot(vector<T>& vec2_1 ,vector<T>& vec2_2){
return vec2_1[0] * vec2_2[0] + vec2_1[1] * vec2_2[1];
}
template <typename T>
T cross(vector<T>& vec2_1 ,vector<T>& vec2_2){
return vec2_1[0] * vec2_2[1] - vec2_1[1] * vec2_2[0];
}
void normalize(vector<_VecTypeName>& vec2){
if (vec2[0] == 0 || vec2[1] == 0)
return;
_VecTypeName sqx = vec2[0] * vec2[0];
_VecTypeName sqy = vec2[1] * vec2[1];
vec2[0] = sqrt(sqx / (sqx + sqy)) * (vec2[0] / abs(vec2[0]));
vec2[1] = sqrt(sqy / (sqx + sqy)) * (vec2[1] / abs(vec2[1]));
}
template <typename T>
void makeVec2(vector<T>& vec2, vector<int>& point1, vector<int>& point2){
vec2[0] = T(point2[0] - point1[0]);
vec2[1] = T(point2[1] - point1[1]);
}
void addVec(vector<_VecTypeName>& vec2,vector<_VecTypeName>& vec2_1 ,vector<_VecTypeName>& vec2_2){
vec2[0] = vec2_1[0] + vec2_2[0];
vec2[1] = vec2_1[1] + vec2_2[1];
}
void getXMinPoint(vector<int>& point,vector<vector<int>>& trees){
int xmin = INT_MAX;
for (unsigned int i = 0; i < trees.size(); ++i){
int x = trees[i][0];
if (xmin > x){
xmin = x;
point[0] = trees[i][0];
point[1] = trees[i][1];
}
}
}
template <typename T>
void getPolarCoordinates(vector<T>& vec2){
vec2[0] = 1;
vec2[1] = 0;
}
template <typename T>
bool equalVec2(T& point1, T& point2){
return point1[0] == point2[0] and point1[1] == point2[1];
}
template <typename T>
int setLevelFromDotAndCross(T& dotdata, T& crossdata){
int leveldata = 0;
if (crossdata < 0)
leveldata = 5;
else if (crossdata == 0 && dotdata > 0)
leveldata = 4;
else if (crossdata > 0)
leveldata = 3;
else if (crossdata == 0 && dotdata <= 0)
leveldata = 2;
return leveldata;
}
template <typename T>
bool compareDotAndCross(T& dotdata1, T& crossdata1, T& dotdata2, T& crossdata2, T& ori_dotdata1, T& ori_dotdata2){
int leveldata1 = setLevelFromDotAndCross<T>(dotdata1,crossdata1);
int leveldata2 = setLevelFromDotAndCross<T>(dotdata2,crossdata2);
if (leveldata1 != leveldata2)
return leveldata1 > leveldata2;
if (leveldata1 == 5)
return dotdata1 < dotdata2;
if (leveldata1 == 4)
return ori_dotdata1 < ori_dotdata2;
if (leveldata1 == 2)
return ori_dotdata1 > ori_dotdata2;
return dotdata1 > dotdata2;
}
vector<vector<int>> outerTrees(vector<vector<int>>& trees) {
if (trees.size() <= 2) return trees;
vector<vector<int>> cp_tree;
for (unsigned int i = 0; i < trees.size(); ++i){
vector<int> cp_data(2,0);
cp_data[0] = trees[i][0];
cp_data[1] = trees[i][1];
cp_tree.push_back(cp_data);
}
vector<vector<int>> res;
vector<_VecTypeName> axis_x(2,0);
getPolarCoordinates<_VecTypeName>(axis_x);
vector<int> point(2,0);
getXMinPoint(point,trees);
res.push_back(point);
while(!(
res.size() > 1 and equalVec2<vector<int>>(*(res.end() - 1),*(res.begin()))
)){
_VecTypeName crossdata1 = 1;
_VecTypeName dotdata1 = -999;
_VecTypeName ori_dotdata1 = 0;
vector<int> pi(2,0);
int index = -1;
for (unsigned int i = 0; i < trees.size(); ++i){
if (equalVec2<vector<int>>(*(res.end() - 1),trees[i])){
continue;
}
vector<_VecTypeName> vecp(2,0);
makeVec2<_VecTypeName>(vecp,*(res.end() - 1),trees[i]);
_VecTypeName ori_dotdata2 = dot<_VecTypeName>(axis_x,vecp);
normalize(vecp);
_VecTypeName crossdata2 = cross<_VecTypeName>(axis_x,vecp);
_VecTypeName dotdata2 = dot<_VecTypeName>(axis_x,vecp);
if (!compareDotAndCross<_VecTypeName>(dotdata1,crossdata1,dotdata2,crossdata2,ori_dotdata1,ori_dotdata2)){
crossdata1 = crossdata2;
dotdata1 = dotdata2;
ori_dotdata1 = ori_dotdata2;
pi[0] = trees[i][0];
pi[1] = trees[i][1];
index = i;
}
}
if (index >= 0){
makeVec2<_VecTypeName>(axis_x,*(res.end() - 1),pi);
normalize(axis_x);
res.push_back(pi);
cout << index << " " << trees.size() << endl;
trees.erase(trees.begin() + index);
}
else{
return cp_tree;
}
}
res.erase(res.end()-1);
return res;
}
};