You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

180 lines
5.8 KiB
C++

#include "StdAfx.h"
#include "ObjFill.h"
#include "GlobalFunction.h"
#include "GlobalDrawMgr.h"
#include "LogMgr.h"
#define MAX_FILL_LINE_LEN 500 //最大填充范围
CObjFill::CObjFill(vector<CSequentialPoint> &Vec)
:m_SequentialPointVec(Vec)
{
}
CObjFill::~CObjFill(void)
{
}
//根据obj 传入的数据点来创建填充数据
void CObjFill::CreatFill(vector<vector<Dbxy>> &LinesVec,DbRect rect)
{
if(m_FillPar.bFill ==false)
return;
Dbxy Pt1,Pt2,Offset;
int ScanTimes = 0;
//获取用于扫描的线(Pt1,Pt2是第一条线),并计算出扫描线的次数
GetScanLine(rect,Pt1,Pt2,Offset,ScanTimes);
//往回缩一点,照顾第一条线
Pt1.x -= Offset.x/2;
Pt2.x -= Offset.x/2;
Pt1.y -= Offset.y/2;
Pt2.y -= Offset.y/2;
//调整第一条线,保证多区域之间的间隔一致
for(int i=0;i<ScanTimes;i++)
{
//计算扫描线的所有交点
vector<Dbxy> IntersectionVec;
if(GetIntersection(LinesVec,Pt1,Pt2,IntersectionVec,rect))
{
//对计算出的交点排序
SortIntersection(IntersectionVec);
//保存扫描结果
SaveScanResult(IntersectionVec);
}
//扫描线偏移
Pt1.x += Offset.x;
Pt1.y += Offset.y;
Pt2.x += Offset.x;
Pt2.y += Offset.y;
}
}
#if 1//创建
//获取用于扫描的线(ScanTimes 是扫描线偏移的次数)
void CObjFill::GetScanLine(DbRect rect,Dbxy &Pt1,Dbxy &Pt2,Dbxy &Offset,int &ScanTimes)
{
//创建一条足够长的线段
double R = MAX_FILL_LINE_LEN;//这里会限制填充的范围
Dbxy CenterPt(rect.L,rect.T);
Pt1.y = Pt2.y = rect.T;
Pt1.x = rect.L-R;
Pt2.x = rect.R+R;
double FillGap = m_FillPar.m_FillGap;//填充间隔
Dbxy Pt(Pt1.x,Pt1.y-FillGap);//用来计算扫描线每次的偏移
//旋转扫描线
double Angle = _360ToAngle(m_FillPar.m_FillAngle);
Pt1 = RotatoPt(Pt1,Angle,CenterPt);
Pt2 = RotatoPt(Pt2,Angle,CenterPt);
Pt = RotatoPt(Pt,Angle,CenterPt);
double len = CalDistance(Dbxy(rect.L,rect.T),Dbxy(rect.R,rect.B));
ScanTimes = len/FillGap;
//每次扫描线的偏移
Offset.x = Pt.x - Pt1.x;
Offset.y = Pt.y - Pt1.y;
}
//计算连续线段和pt1,pt2 线段的交点(结果保存到IntersectionVec)
//交点需要在rect 范围内
bool CObjFill::GetIntersection(vector<vector<Dbxy>> &LinesVec,Dbxy pt1,Dbxy pt2,vector<Dbxy> &IntersectionVec,DbRect rect)
{
IntersectionVec.clear();
if(pt1.x>3.66 && pt1.x<4.44)
{
int a = 0;
}
vector<vector<Dbxy>>::iterator iter = LinesVec.begin();
vector<vector<Dbxy>>::iterator iter_end = LinesVec.end();
for(;iter!=iter_end;iter++)
{
int size = (*iter).size();
for(int i=0;i<size-1;i++)
{
Dbxy u1((*iter)[i].x,(*iter)[i].y);//当前线段的两个点
Dbxy u2((*iter)[i+1].x,(*iter)[i+1].y);
if((u1.x>7.974 && u1.x<7.976)&&(u2.x>4.04 && u2.x<4.06))
{
int a=0;
}
//处理正好是端点的情况
if(dot_online_in(u1,pt1,pt2) && dot_online_in(u2,pt1,pt2))//两个点都在pt1,pt2 上
{
//将扫描线稍微回撤一点点再算一次,过滤掉这种情况
double offset = 0.0001;
pt1.x -= offset;
pt2.x -= offset;
pt1.y -= offset;
pt2.y -= offset;
//递归函数(注意)
return GetIntersection(LinesVec,pt1,pt2,IntersectionVec,rect);
}
else if(dot_online_in(u1,pt1,pt2))//第一个点在pt1,pt2 上
{
continue;
}
else if(dot_online_in(u2,pt1,pt2))//第二个点在pt1,pt2 上
{
//后一条线段的第二个点在另外一端时,才算交点
if((i+2)<size)
{
Dbxy u3((*iter)[i+2].x,(*iter)[i+2].y);
if(!dot_online_in(u3,pt1,pt2) && IsTwoLineIntersect(u1,u3,pt1,pt2))
{
if(IsPointInRect(u2,rect))
{
IntersectionVec.push_back(u2);
}
}
}
else if(i==(size-2))//正好是最后一个点的情况(2018-10-15)
{
if(IsPointInRect(u2,rect))
{
IntersectionVec.push_back(u2);
}
}
}
else if(IsTwoLineIntersect(u1,u2,pt1,pt2))//交点在u1,u2 中间
{
Dbxy pt = CalIntersection(u1,u2,pt1,pt2);//计算交点
if(IsPointInRect(pt,rect))
{
IntersectionVec.push_back(pt);
}
}
}
}
return !IntersectionVec.empty();
}
//对计算出的交点排序
void CObjFill::SortIntersection(vector<Dbxy> &IntersectionVec)
{
if(m_FillPar.m_FillAngle<=45)
{
sort(IntersectionVec.begin(),IntersectionVec.end(),CompareDbxyByX);
}
else
{
sort(IntersectionVec.begin(),IntersectionVec.end(),CompareDbxyByY);
}
}
//保存扫描结果
void CObjFill::SaveScanResult(vector<Dbxy> &IntersectionVec)
{
int size = IntersectionVec.size();
int idx = 1;
for(int i=1;i<size;i++)
{
if(idx%2 !=0)//把交点组成线段,奇数位才创建线段
{
CSequentialPoint SequentialPoint;
m_SequentialPointVec.push_back(SequentialPoint);
int size1 = m_SequentialPointVec.size();
m_SequentialPointVec[size1-1].AddDataPoint(IntersectionVec[i-1]);
m_SequentialPointVec[size1-1].AddDataPoint(IntersectionVec[i]);
}
idx++;
}
}
#endif