首页 > 代码库 > FindSmallestPolygon

FindSmallestPolygon

#include <string>
#include <sstream>
#include <iostream>
#include <fstream>
#include "GenMif.h"

using namespace std; 

POINT_STRU FindStartPoint(vector<POINT_STRU> points)
{
    POINT_STRU point = points[0];
    for (size_t i = 1; i < points.size(); i++)
    {
        if (points[i].Lower(point))
        {
            point = points[i];
        }
    }
    return point;
}

int FindNextPoint(vector<POINT_STRU> points, vector<int> searched, POINT_STRU start, double& bottomAngle)
{
    double localMinAngle = 2 * PI;
    double angle = 2 * PI;
    int stopIdx = -1;
    for (size_t i = 0; i < points.size(); i++)
    {
        if (searched[i])
        {
            continue;
        }
        angle = start.GetAngle(points[i]);  // if self, got 2 * PI
        //cout << "Start: " << start.x << ", " << start.y << "  stop: " << points[i].x << ", " << points[i].y << " -- " << angle * 180 / PI << endl;
        if ((angle <= localMinAngle) && ( angle >= bottomAngle) )  // 防 0
        {
            localMinAngle = angle;
            stopIdx = i;
        }
    }
    bottomAngle = localMinAngle;
    //cout << points.size() << " " << stopIdx << "localMinAngle: " << localMinAngle * 180 / PI << "bottomAngle: " << bottomAngle * 180 / PI << endl;
    return stopIdx;
}

void GenCycle(POINT_STRU center, vector<POINT_STRU>& cycle, double radius, int count)
{
    double delta = 2 * PI / count;
    for (double angle = 0; angle <= 2 * PI; angle+=delta)
    {
        POINT_STRU edge;
        edge.x = center.x + radius * cos(angle);
        edge.y = center.y + radius * sin(angle);
        cycle.push_back(edge);
    }
    return;
}

bool FindSmallestPolygon(vector<POINT_STRU> orig, vector<POINT_STRU>& boundary)
{
    vector<int> searched(orig.size());
    POINT_STRU startPoint = FindStartPoint(orig);
    //cout << startPoint.x << ", " << startPoint.y << endl;
    boundary.push_back(startPoint);
    int nextIdx;
    double minAngle = 0.0;
    nextIdx = FindNextPoint(orig, searched, startPoint, minAngle);
    while( !orig[nextIdx].Equals(startPoint) )
    {
        if (nextIdx < 0)
        {
            return false;
        }
        boundary.push_back(orig[nextIdx]);
        searched[nextIdx] = 1;
        //cout << orig[nextIdx].x << ", " << orig[nextIdx].y << endl;
        nextIdx = FindNextPoint(orig, searched, orig[nextIdx], minAngle);
    }
    return true;
}

int CMifObject::count = 0;

CMifObject::CMifObject()
{
    header << "Version 300\n"
           << "Charset \"WindowsSimpChinese\"\n"
           << "Delimiter \",\"\n"
           << "CoordSys Earth Projection 1, 0\n"
           << "Columns 2\n"
           << "Lon Float\n"
           << "Lat Float\n"
           << "Data\n";
    content << header.str();
}

string CMifObject::getContent()
{
    return content.str();
}

/*
    0 - 2 pi
    cout <<  "0.0, 0.0 " << GetAngle(0.0, 0.0) << "\n";
    cout <<  "1.0, 0.0 " << GetAngle(1.0, 0.0) << "\n";
    cout <<  "1.0, 1.0 " << GetAngle(1.0, 1.0) << "\n";
    cout <<  "0.0, 1.0 " << GetAngle(0.0, 1.0) << "\n";
    cout <<  "-1.0, 1.0 " << GetAngle(-1.0, 1.0) << "\n";
    cout <<  "-1.0, 0.0 " << GetAngle(-1.0, 0.0) << "\n";
    cout <<  "-1.0, -1.0 " << GetAngle(-1.0, -1.0) << "\n";
    cout <<  "0.0, -1.0 " << GetAngle(0.0, -1.0) << "\n";
    cout <<  "1.0, -1.0 " << GetAngle(1.0, -1.0) << "\n";
*/
   
void CMifObject::AddRegion(std::vector<POINT_STRU> coords)
{
    ostringstream ostr;
    ostr << "Region 1\n"
         << "    " << coords.size() << "\n" ;
    for(size_t i = 0; i < coords.size(); i++)
    {
        ostr << coords[i].x << " " << coords[i].y << "\n";
    }
    content << ostr.str();
}

bool CMifObject::toFile(string filename)
{
    ofstream fout;
    fout.open(filename, ios::out);
    fout << content.str();
    fout.close();
    return true;
}
#include <string>
#include <sstream>
#include <iostream>
#include <vector>

#include "MathUtil.h"

using namespace std;

POINT_STRU FindStartPoint(vector<POINT_STRU> points);
int FindNextPoint(vector<POINT_STRU> points, vector<int> searched, POINT_STRU start, double& bottomAngle);

void GenCycle(POINT_STRU center, vector<POINT_STRU>& cycle, double radius, int count);
bool FindSmallestPolygon(vector<POINT_STRU> orig, vector<POINT_STRU>& boundary);

class CMifObject
{
public:
    CMifObject();
    void AddRegion(std::vector<POINT_STRU> coords);
    string getContent();
    bool toFile(string filename);
private:
    ostringstream header;
    ostringstream content;
    static int count;
};
#include <cmath>

const double PRECISION = 0.000000000000001;
const double PI = 3.1415926535;

bool IsZero(double value);

typedef struct POINT_STRU
{
    double x;
    double y;

    POINT_STRU()
    {

        x = 0.0;
        y = 0.0;
    }
    POINT_STRU(double x0, double y0)
    {
        x = x0;
        y = y0;
    }
    bool Equals(POINT_STRU point)
    {
        return IsZero(x - point.x) && IsZero(y - point.y);
    }
    double GetAngle(POINT_STRU point)
    {
        if (Equals(point))
        {
            return 2 * PI;
        }
        double deltaX = point.x - x;
        double deltaY = point.y - y;
        if (IsZero(deltaY))
        {
            return deltaX > 0 ? 0 : PI;
        }
        double dist = sqrt(deltaX * deltaX + deltaY * deltaY);
        double angle = acos(deltaX / dist);
        return deltaY > 0 ? angle : ( 2 * PI - angle);
    }
    bool Lower(POINT_STRU point)
    {
        return (y < point.y) || ((point.y == y) && (x < point.x));
    }
}POINT_STRU;
#include "GenMif.h"
#include <vector>
using namespace std; 

int main()
{
    vector<POINT_STRU> orig;
    orig.push_back(POINT_STRU(1.1, 1.1));
    orig.push_back(POINT_STRU(5.1, 5.1));
    orig.push_back(POINT_STRU(1.1, 5.1));
    //orig.push_back(POINT_STRU(2.1, 3.1));
    orig.push_back(POINT_STRU(5.1, 1.1));
    //orig.push_back(POINT_STRU(-1.1, 3.1));
    //orig.push_back(POINT_STRU(1.1, 0.1));

    double radius = 1.0;
    int pointsOfCycle = 50;

    vector<POINT_STRU> expand;
    CMifObject* tt = new CMifObject();
    for (size_t i = 0; i < orig.size(); i ++)
    {
        GenCycle(orig[i], expand, radius, pointsOfCycle);
    }
    vector<POINT_STRU> boundary;
    bool res = FindSmallestPolygon(expand, boundary);
    //tt->AddRegion(orig);
    //tt->AddRegion(expand);
    tt->AddRegion(boundary);
    tt->toFile("C:\\Users\\ywx193642\\Desktop\\output\\boundaryTest.mif");
    return 0;
}