我有一套2d points .他们是 X,Y coordinates在标准笛卡尔网格系统上(在本例中为 UTM zone )。我需要在该点集中找到孔,最好具有设置找到这些孔的算法的灵敏度的能力。通常,这些点集非常密集,但有些点集的密度要小得多。
它们是什么,如果有帮助的话,是对田间土壤进行采样的点,以获得农业人员显然认为有用的各种特性。有时在这些点样本中有巨大的岩石或沼泽地或充满小湖泊和池塘。
他们希望我从点集中找到大致定义这些孔的凹多边形。
我已经编写了找到外部凹边界多边形的算法,并允许他们设置算法形成的多边形的粗糙度或平滑度的灵敏度。在那次运行之后,他们想找到洞并将这些洞作为凹多边形给他们,我猜在某些情况下可能是凸多边形,但这将是边缘情况而不是常态。
问题是我听说过的关于这个主题的唯一论文是那些想要在太空中找到大片空洞的天文学家所做的论文,而我从来没有找到他们的一篇论文,其中显示了实际算法除了粗略的概念描述之外的任何内容。
我尝试过谷歌和各种学术论文搜索等,但到目前为止我还没有发现很多有用的东西。这让我想知道这种问题是否有一个名字,我不知道,所以我正在寻找错误的东西或什么?
因此,经过冗长的解释之后,我的问题是:有没有人知道我应该搜索什么来找到最好使用定义明确的算法的论文,或者是否有人知道他们可以指出我的算法可以做到这一点?
任何能帮助我解决这个问题的东西都会非常有用并且非常感谢,即使只是正确的搜索词组也会出现潜在的算法或论文。
这将被实现的语言将是 C#,但从 Mathematica 包到 MATLAB or ASM, C, C++, Python, Java or MathCAD 的任何例子中都有例子。只要示例中没有一些调用像 FindTheHole 这样的调用,等等就可以了。等哪里FindTheHole未定义或专用于实现软件,例如MathCAD示例通常有很多。
以下是实际点集的两个示例,一个密集的和一个稀疏的以及我需要找到的区域:


最佳答案
一些怎么样位图+矢量方法如下:
O(N)循环遍历所有点。 map[N][N]该地区的area(x,y) -> map[i][j] 创建投影例如简单的规模。网格尺寸 N 也是精度 输出和 必须大于平均点距离!!! 所以每个电池内map[][]覆盖区域至少有一个点(如果不在孔区域内)。 map[][] 的每个单元格的数据密度map[][].cnt (积分计数器)到 zero并通过简单的计算 O(N)循环在哪里做map[i][j].cnt++所有 points(x,y) (map[][].cnt==0)或 (map[][].cnt<=treshold) void main_compute(int N)
{
// cell storage for density computation
struct _cell
{
double x0,x1,y0,y1; // bounding area of points inside cell
int cnt; // points inside cell
_cell(){}; _cell(_cell& a){ *this=a; }; ~_cell(){}; _cell* operator = (const _cell *a) { *this=*a; return this; }; /*_cell* operator = (const _cell &a) { ...copy... return this; };*/
};
// line storage for hole area
struct _line
{
double x0,y0,x1,y1; // line edge points
int id; // id of hole for segmentation/polygonize
int i0,i1,j0,j1; // index in map[][]
_line(){}; _line(_line& a){ *this=a; }; ~_line(){}; _line* operator = (const _line *a) { *this=*a; return this; }; /*_line* operator = (const _line &a) { ...copy... return this; };*/
};
int i,j,k,M=N*N; // M = max N^2 but usualy is much much less so dynamic list will be better
double mx,my; // scale to map
_cell *m; // cell ptr
glview2D::_pnt *p; // point ptr
double x0,x1,y0,y1; // used area (bounding box)
_cell **map=NULL; // cell grid
_line *lin=NULL; // temp line list for hole segmentation
int lins=0; // actual usage/size of lin[M]
// scan point cloud for bounding box (if it is known then skip it)
p=&view.pnt[0];
x0=p->p[0]; x1=x0;
y0=p->p[1]; y1=y0;
for (i=0;i<view.pnt.num;i++)
{
p=&view.pnt[i];
if (x0>p->p[0]) x0=p->p[0];
if (x1<p->p[0]) x1=p->p[0];
if (y0>p->p[1]) y0=p->p[1];
if (y1<p->p[1]) y1=p->p[1];
}
// compute scale for coordinate to map index conversion
mx=double(N)/(x1-x0); // add avoidance of division by zero if empty point cloud !!!
my=double(N)/(y1-y0);
// dynamic allocation of map[N][N],lin[M]
lin=new _line[M];
map=new _cell*[N];
for (i=0;i<N;i++) map[i]=new _cell[N];
// reset map[N][N]
for (i=0;i<N;i++)
for (j=0;j<N;j++)
map[i][j].cnt=0;
// compute point cloud density
for (k=0;k<view.pnt.num;k++)
{
p=&view.pnt[k];
i=double((p->p[0]-x0)*mx); if (i<0) i=0; if (i>=N) i=N-1;
j=double((p->p[1]-y0)*my); if (j<0) j=0; if (j>=N) j=N-1;
m=&map[i][j];
if (!m->cnt)
{
m->x0=p->p[0];
m->x1=p->p[0];
m->y0=p->p[1];
m->y1=p->p[1];
}
if (m->cnt<0x7FFFFFFF) m->cnt++; // avoid overflow
if (m->x0>p->p[0]) m->x0=p->p[0];
if (m->x1<p->p[0]) m->x1=p->p[0];
if (m->y0>p->p[1]) m->y0=p->p[1];
if (m->y1<p->p[1]) m->y1=p->p[1];
}
// find holes (map[i][j].cnt==0) or (map[i][j].cnt<=treshold)
// and create lin[] list of H,V lines covering holes
for (j=0;j<N;j++) // search lines
{
for (i=0;i<N;)
{
int i0,i1;
for (;i<N;i++) if (map[i][j].cnt==0) break; i0=i-1; // find start of hole
for (;i<N;i++) if (map[i][j].cnt!=0) break; i1=i; // find end of hole
if (i0< 0) continue; // skip bad circumstances (edges or no hole found)
if (i1>=N) continue;
if (map[i0][j].cnt==0) continue;
if (map[i1][j].cnt==0) continue;
_line l;
l.i0=i0; l.x0=map[i0][j].x1;
l.i1=i1; l.x1=map[i1][j].x0;
l.j0=j ; l.y0=0.25*(map[i0][j].y0+map[i0][j].y1+map[i1][j].y0+map[i1][j].y1);
l.j1=j ; l.y1=l.y0;
lin[lins]=l; lins++;
}
}
for (i=0;i<N;i++) // search columns
{
for (j=0;j<N;)
{
int j0,j1;
for (;j<N;j++) if (map[i][j].cnt==0) break; j0=j-1; // find start of hole
for (;j<N;j++) if (map[i][j].cnt!=0) break; j1=j; // find end of hole
if (j0< 0) continue; // skip bad circumstances (edges or no hole found)
if (j1>=N) continue;
if (map[i][j0].cnt==0) continue;
if (map[i][j1].cnt==0) continue;
_line l;
l.i0=i ; l.y0=map[i][j0].y1;
l.i1=i ; l.y1=map[i][j1].y0;
l.j0=j0; l.x0=0.25*(map[i][j0].x0+map[i][j0].x1+map[i][j1].x0+map[i][j1].x1);
l.j1=j1; l.x1=l.x0;
lin[lins]=l; lins++;
}
}
// segmentate lin[] ... group lines of the same hole together by lin[].id
// segmentation based on vector lines data
// you can also segmentate the map[][] directly as bitmap during hole detection
for (i=0;i<lins;i++) lin[i].id=i; // all lines are separate
for (;;) // join what you can
{
int e=0,i0,i1;
_line *a,*b;
for (a=lin,i=0;i<lins;i++,a++)
{
for (b=a,j=i;j<lins;j++,b++)
if (a->id!=b->id)
{
// do 2D lines a,b intersect ?
double xx0,yy0,xx1,yy1;
double kx0,ky0,dx0,dy0,t0;
double kx1,ky1,dx1,dy1,t1;
double x0=a->x0,y0=a->y0;
double x1=a->x1,y1=a->y1;
double x2=b->x0,y2=b->y0;
double x3=b->x1,y3=b->y1;
// discart lines with non intersecting bound rectangles
double a0,a1,b0,b1;
if (x0<x1) { a0=x0; a1=x1; } else { a0=x1; a1=x0; }
if (x2<x3) { b0=x2; b1=x3; } else { b0=x3; b1=x2; }
if (a1<b0) continue;
if (a0>b1) continue;
if (y0<y1) { a0=y0; a1=y1; } else { a0=y1; a1=y0; }
if (y2<y3) { b0=y2; b1=y3; } else { b0=y3; b1=y2; }
if (a1<b0) continue;
if (a0>b1) continue;
// compute intersection
kx0=x0; ky0=y0; dx0=x1-x0; dy0=y1-y0;
kx1=x2; ky1=y2; dx1=x3-x2; dy1=y3-y2;
t1=divide(dx0*(ky0-ky1)+dy0*(kx1-kx0),(dx0*dy1)-(dx1*dy0));
xx1=kx1+(dx1*t1);
yy1=ky1+(dy1*t1);
if (fabs(dx0)>=fabs(dy0)) t0=divide(kx1-kx0+(dx1*t1),dx0);
else t0=divide(ky1-ky0+(dy1*t1),dy0);
xx0=kx0+(dx0*t0);
yy0=ky0+(dy0*t0);
// check if intersection exists
if (fabs(xx1-xx0)>1e-6) continue;
if (fabs(yy1-yy0)>1e-6) continue;
if ((t0<0.0)||(t0>1.0)) continue;
if ((t1<0.0)||(t1>1.0)) continue;
// if yes ... intersection point = xx0,yy0
e=1; break;
}
if (e) break; // join found ... stop searching
}
if (!e) break; // no join found ... stop segmentation
i0=a->id; // joid ids ... rename i1 to i0
i1=b->id;
for (a=lin,i=0;i<lins;i++,a++)
if (a->id==i1)
a->id=i0;
}
// visualize lin[]
for (i=0;i<lins;i++)
{
glview2D::_lin l;
l.p0.p[0]=lin[i].x0;
l.p0.p[1]=lin[i].y0;
l.p1.p[0]=lin[i].x1;
l.p1.p[1]=lin[i].y1;
// l.col=0x0000FF00;
l.col=(lin[i].id*0x00D00C10A)+0x00800000; // color is any function of ID
view.lin.add(l);
}
// dynamic deallocation of map[N][N],lin[M]
for (i=0;i<N;i++) delete[] map[i];
delete[] map;
delete[] lin;
}
//---------------------------------------------------------------------------
glview2D东西(这是我的几何图形渲染引擎)view.pnt[]是您的点的动态列表(由随机生成)view.lin[]是动态列表输出 H、V 线 仅用于可视化 lin[]是你的线路输出
O(N)和用于孔搜索/分割 ~O((M^2)+(U^2))在哪里:N是点数 M是 map 网格大小U是 H、V 线 计数取决于孔... M << N, U << M*M 3783积分30x30上图中的网格几乎花了9ms在我的设置上
//---------------------------------------------------------------------------
class holes
{
public:
int xs,ys,n; // cell grid x,y - size and points count
int **map; // points density map[xs][ys]
// i=(x-x0)*g2l; x=x0+(i*l2g);
// j=(y-y0)*g2l; y=y0+(j*l2g);
double mg2l,ml2g; // scale to/from global/map space (x,y) <-> map[i][j]
double x0,x1,y0,y1; // used area (bounding box)
struct _line
{
int id; // id of hole for segmentation/polygonize
int i0,i1,j0,j1; // index in map[][]
_line(){}; _line(_line& a){ *this=a; }; ~_line(){}; _line* operator = (const _line *a) { *this=*a; return this; }; /*_line* operator = (const _line &a) { ...copy... return this; };*/
};
List<_line> lin;
int lin_i0; // start index for perimeter lines (smaller indexes are the H,V lines inside hole)
struct _point
{
int i,j; // index in map[][]
int p0,p1; // previous next point
int used;
_point(){}; _point(_point& a){ *this=a; }; ~_point(){}; _point* operator = (const _point *a) { *this=*a; return this; }; /*_point* operator = (const _point &a) { ...copy... return this; };*/
};
List<_point> pnt;
// class init and internal stuff
holes() { xs=0; ys=0; n=0; map=NULL; mg2l=1.0; ml2g=1.0; x0=0.0; y0=0.0; x1=0.0; y1=0.0; lin_i0=0; };
holes(holes& a){ *this=a; };
~holes() { _free(); };
holes* operator = (const holes *a) { *this=*a; return this; };
holes* operator = (const holes &a)
{
xs=0; ys=0; n=a.n; map=NULL;
mg2l=a.mg2l; x0=a.x0; x1=a.x1;
ml2g=a.ml2g; y0=a.y0; y1=a.y1;
_alloc(a.xs,a.ys);
for (int i=0;i<xs;i++)
for (int j=0;j<ys;j++) map[i][j]=a.map[i][j];
return this;
}
void _free() { if (map) { for (int i=0;i<xs;i++) if (map[i]) delete[] map[i]; delete[] map; } xs=0; ys=0; }
void _alloc(int _xs,int _ys) { int i=0; _free(); xs=_xs; ys=_ys; map=new int*[xs]; if (map) for (i=0;i<xs;i++) { map[i]=new int[ys]; if (map[i]==NULL) { i=-1; break; } } else i=-1; if (i<0) _free(); }
// scann boundary box interface
void scann_beg();
void scann_pnt(double x,double y);
void scann_end();
// dynamic allocations
void cell_size(double sz); // compute/allocate grid from grid cell size = sz x sz
// scann holes interface
void holes_beg();
void holes_pnt(double x,double y);
void holes_end();
// global(x,y) <- local map[i][j] + half cell offset
inline void l2g(double &x,double &y,int i,int j) { x=x0+((double(i)+0.5)*ml2g); y=y0+((double(j)+0.5)*ml2g); }
// local map[i][j] <- global(x,y)
inline void g2l(int &i,int &j,double x,double y) { i= double((x-x0) *mg2l); j= double((y-y0) *mg2l); }
};
//---------------------------------------------------------------------------
void holes::scann_beg()
{
x0=0.0; y0=0.0; x1=0.0; y1=0.0; n=0;
}
//---------------------------------------------------------------------------
void holes::scann_pnt(double x,double y)
{
if (!n) { x0=x; y0=y; x1=x; y1=y; }
if (n<0x7FFFFFFF) n++; // avoid overflow
if (x0>x) x0=x; if (x1<x) x1=x;
if (y0>y) y0=y; if (y1<y) y1=y;
}
//---------------------------------------------------------------------------
void holes::scann_end()
{
}
//---------------------------------------------------------------------------
void holes::cell_size(double sz)
{
int x,y;
if (sz<1e-6) sz=1e-6;
x=ceil((x1-x0)/sz);
y=ceil((y1-y0)/sz);
_alloc(x,y);
ml2g=sz; mg2l=1.0/sz;
}
//---------------------------------------------------------------------------
void holes::holes_beg()
{
int i,j;
for (i=0;i<xs;i++)
for (j=0;j<ys;j++)
map[i][j]=0;
}
//---------------------------------------------------------------------------
void holes::holes_pnt(double x,double y)
{
int i,j;
g2l(i,j,x,y);
if ((i>=0)&&(i<xs))
if ((j>=0)&&(j<ys))
if (map[i][j]<0x7FFFFFFF) map[i][j]++; // avoid overflow
}
//---------------------------------------------------------------------------
void holes::holes_end()
{
int i,j,e,i0,i1;
List<int> ix; // hole lines start/stop indexes for speed up the polygonization
_line *a,*b,l;
_point *aa,*bb,p;
lin.num=0; lin_i0=0;// clear lines
ix.num=0; // clear indexes
// find holes (map[i][j].cnt==0) or (map[i][j].cnt<=treshold)
// and create lin[] list of H,V lines covering holes
for (j=0;j<ys;j++) // search lines
for (i=0;i<xs;)
{
int i0,i1;
for (;i<xs;i++) if (map[i][j]==0) break; i0=i-1; // find start of hole
for (;i<xs;i++) if (map[i][j]!=0) break; i1=i; // find end of hole
if (i0< 0) continue; // skip bad circumstances (edges or no hole found)
if (i1>=xs) continue;
if (map[i0][j]==0) continue;
if (map[i1][j]==0) continue;
l.i0=i0;
l.i1=i1;
l.j0=j ;
l.j1=j ;
l.id=-1;
lin.add(l);
}
for (i=0;i<xs;i++) // search columns
for (j=0;j<ys;)
{
int j0,j1;
for (;j<ys;j++) if (map[i][j]==0) break; j0=j-1; // find start of hole
for (;j<ys;j++) if (map[i][j]!=0) break; j1=j ; // find end of hole
if (j0< 0) continue; // skip bad circumstances (edges or no hole found)
if (j1>=ys) continue;
if (map[i][j0]==0) continue;
if (map[i][j1]==0) continue;
l.i0=i ;
l.i1=i ;
l.j0=j0;
l.j1=j1;
l.id=-1;
lin.add(l);
}
// segmentate lin[] ... group lines of the same hole together by lin[].id
// segmentation based on vector lines data
// you can also segmentate the map[][] directly as bitmap during hole detection
for (i=0;i<lin.num;i++) lin[i].id=i; // all lines are separate
for (;;) // join what you can
{
for (e=0,a=lin.dat,i=0;i<lin.num;i++,a++)
{
for (b=a,j=i;j<lin.num;j++,b++)
if (a->id!=b->id)
{
// if a,b not intersecting or neighbouring
if (a->i0>b->i1) continue;
if (b->i0>a->i1) continue;
if (a->j0>b->j1) continue;
if (b->j0>a->j1) continue;
// if they do mark e for join groups
e=1; break;
}
if (e) break; // join found ... stop searching
}
if (!e) break; // no join found ... stop segmentation
i0=a->id; // joid ids ... rename i1 to i0
i1=b->id;
for (a=lin.dat,i=0;i<lin.num;i++,a++)
if (a->id==i1)
a->id=i0;
}
// sort lin[] by id
for (e=1;e;) for (e=0,a=&lin[0],b=&lin[1],i=1;i<lin.num;i++,a++,b++)
if (a->id>b->id) { l=*a; *a=*b; *b=l; e=1; }
// re id lin[] and prepare start/stop indexes
for (i0=-1,i1=-1,a=&lin[0],i=0;i<lin.num;i++,a++)
if (a->id==i1) a->id=i0;
else { i0++; i1=a->id; a->id=i0; ix.add(i); }
ix.add(lin.num);
// polygonize
lin_i0=lin.num;
for (j=1;j<ix.num;j++) // process hole
{
i0=ix[j-1]; i1=ix[j];
// create border pnt[] list (unique points only)
pnt.num=0; p.used=0; p.p0=-1; p.p1=-1;
for (a=&lin[i0],i=i0;i<i1;i++,a++)
{
p.i=a->i0;
p.j=a->j0;
map[p.i][p.j]=0;
for (aa=&pnt[0],e=0;e<pnt.num;e++,aa++)
if ((aa->i==p.i)&&(aa->j==p.j)) { e=-1; break; }
if (e>=0) pnt.add(p);
p.i=a->i1;
p.j=a->j1;
map[p.i][p.j]=0;
for (aa=&pnt[0],e=0;e<pnt.num;e++,aa++)
if ((aa->i==p.i)&&(aa->j==p.j)) { e=-1; break; }
if (e>=0) pnt.add(p);
}
// mark not border points
for (aa=&pnt[0],i=0;i<pnt.num;i++,aa++)
if (!aa->used) // ignore marked points
if ((aa->i>0)&&(aa->i<xs-1)) // ignore map[][] border points
if ((aa->j>0)&&(aa->j<ys-1))
{ // ignore if any non hole cell around
if (map[aa->i-1][aa->j-1]>0) continue;
if (map[aa->i-1][aa->j ]>0) continue;
if (map[aa->i-1][aa->j+1]>0) continue;
if (map[aa->i ][aa->j-1]>0) continue;
if (map[aa->i ][aa->j+1]>0) continue;
if (map[aa->i+1][aa->j-1]>0) continue;
if (map[aa->i+1][aa->j ]>0) continue;
if (map[aa->i+1][aa->j+1]>0) continue;
aa->used=1;
}
// delete marked points
for (aa=&pnt[0],e=0,i=0;i<pnt.num;i++,aa++)
if (!aa->used) { pnt[e]=*aa; e++; } pnt.num=e;
// connect neighbouring points distance=1
for (i0= 0,aa=&pnt[i0];i0<pnt.num;i0++,aa++)
if (aa->used<2)
for (i1=i0+1,bb=&pnt[i1];i1<pnt.num;i1++,bb++)
if (bb->used<2)
{
i=aa->i-bb->i; if (i<0) i=-i; e =i;
i=aa->j-bb->j; if (i<0) i=-i; e+=i;
if (e!=1) continue;
aa->used++; if (aa->p0<0) aa->p0=i1; else aa->p1=i1;
bb->used++; if (bb->p0<0) bb->p0=i0; else bb->p1=i0;
}
// try to connect neighbouring points distance=sqrt(2)
for (i0= 0,aa=&pnt[i0];i0<pnt.num;i0++,aa++)
if (aa->used<2)
for (i1=i0+1,bb=&pnt[i1];i1<pnt.num;i1++,bb++)
if (bb->used<2)
if ((aa->p0!=i1)&&(aa->p1!=i1))
if ((bb->p0!=i0)&&(bb->p1!=i0))
{
if ((aa->used)&&(aa->p0==bb->p0)) continue; // avoid small closed loops
i=aa->i-bb->i; if (i<0) i=-i; e =i*i;
i=aa->j-bb->j; if (i<0) i=-i; e+=i*i;
if (e!=2) continue;
aa->used++; if (aa->p0<0) aa->p0=i1; else aa->p1=i1;
bb->used++; if (bb->p0<0) bb->p0=i0; else bb->p1=i0;
}
// try to connect to closest point
int ii,dd;
for (i0= 0,aa=&pnt[i0];i0<pnt.num;i0++,aa++)
if (aa->used<2)
{
for (ii=-1,i1=i0+1,bb=&pnt[i1];i1<pnt.num;i1++,bb++)
if (bb->used<2)
if ((aa->p0!=i1)&&(aa->p1!=i1))
if ((bb->p0!=i0)&&(bb->p1!=i0))
{
i=aa->i-bb->i; if (i<0) i=-i; e =i*i;
i=aa->j-bb->j; if (i<0) i=-i; e+=i*i;
if ((ii<0)||(e<dd)) { ii=i1; dd=e; }
}
if (ii<0) continue;
i1=ii; bb=&pnt[i1];
aa->used++; if (aa->p0<0) aa->p0=i1; else aa->p1=i1;
bb->used++; if (bb->p0<0) bb->p0=i0; else bb->p1=i0;
}
// add connected points to lin[] ... this is hole perimeter !!!
// lines are 2 x duplicated so some additional code for sort the order of line swill be good idea
l.id=lin[ix[j-1]].id;
for (i0=0,aa=&pnt[i0];i0<pnt.num;i0++,aa++)
{
l.i0=aa->i;
l.j0=aa->j;
// [edit3] this avoid duplicating lines
if (aa->p0>i0) { bb=&pnt[aa->p0]; l.i1=bb->i; l.j1=bb->j; lin.add(l); }
if (aa->p1>i0) { bb=&pnt[aa->p1]; l.i1=bb->i; l.j1=bb->j; lin.add(l); }
//if (aa->p0>=0) { bb=&pnt[aa->p0]; l.i1=bb->i; l.j1=bb->j; lin.add(l); }
//if (aa->p1>=0) { bb=&pnt[aa->p1]; l.i1=bb->i; l.j1=bb->j; lin.add(l); }
}
}
}
//---------------------------------------------------------------------------
List<T>模板与 std::list或其他任何(我无法分享的模板)。它是 T 的动态一维数组...List<int> x;与 int x[]; 相同x.add();将空项目添加到 x x.add(a);将项目添加到 x x.reset()清除数组 x.allocate(size)预分配空间以避免在运行缓慢时重新分配 x.num是 x[] 中的项目数 ... 项目中使用的大小 h.scann_beg(); for (i=0;i<view.pnt.num;i++) { p=view.pnt[i].p0.p; h.scann_pnt(p[0],p[1]); } h.scann_end();
h.cell_size(2.5);
h.holes_beg(); for (i=0;i<view.pnt.num;i++) { p=view.pnt[i].p0.p; h.holes_pnt(p[0],p[1]); } h.holes_end();
view.pnt[]是输入点列表及其内部:view.pnt[i].p0.p[ 2 ]= { x,y }h.lin[]和 lin_i0在哪里:h.lin[i] i= < 0,lin_i0 )是内部 H、V 线 h.lin[i] i= < lin_i0,h.lin.num )是周长 lin[]是 id .. id孔0,1,2,3,...该线路所属的和 i,j map 内的坐标。所以为了正确输出到您的世界坐标中,请执行以下操作:int i,j;
holes h; // holes class
double *p; // input point list ptr
h.scann_beg(); for (i=0;i<view.pnt.num;i++) { p=view.pnt[i].p0.p; h.scann_pnt(p[0],p[1]); } h.scann_end();
h.cell_size(2.5);
h.holes_beg(); for (i=0;i<view.pnt.num;i++) { p=view.pnt[i].p0.p; h.holes_pnt(p[0],p[1]); } h.holes_end();
DWORD coltab[]=
{
0x000000FF,
0x0000FF00,
0x00FF0000,
0x0000FFFF,
0x00FFFF00,
0x00FF00FF,
0x00FFFFFF,
0x00000088,
0x00008800,
0x00880000,
0x00008888,
0x00888800,
0x00880088,
0x00888888,
};
for (i=0;i<h.lin.num;i++) // draw lin[]
{
glview2D::_lin a;
holes::_line *b=&h.lin[i];
h.l2g(a.p0.p[0],a.p0.p[1],b->i0,b->j0);
h.l2g(a.p1.p[0],a.p1.p[1],b->i1,b->j1);
if (i<h.lin_i0) // H,V lines inside hole(b->id) .. gray [edit3] was <= which is wrong and miss-color first perimeter line
{
a.col=0x00808080;
}
else{ // hole(b->id) perimeter lines ... each hole different collor
if ((b->id>=0)&&(b->id<14)) a.col=coltab[b->id];
if (b->id==-1) a.col=0x00FFFFFF; // special debug lines
if (b->id==-2) a.col=0x00AA8040; // special debug lines
}
view.lin.add(a); // here draw your line or add it to your polygon instead
}
view.lin[]有成员(member):p0,p1,这些点为 view.pnt[]和 col这是颜色 (diameter < 3 cells)否则没问题 /* add connected points to lin[] ... this is hole perimeter !!!
// lines are 2 x duplicated so some additional code for sort the order of line swill be good idea
l.id=lin[ix[j-1]].id;
for (i0=0,aa=&pnt[i0];i0<pnt.num;i0++,aa++)
{
l.i0=aa->i;
l.j0=aa->j;
// [edit3] this avoid duplicating lines
if (aa->p0>i0) { bb=&pnt[aa->p0]; l.i1=bb->i; l.j1=bb->j; lin.add(l); }
if (aa->p1>i0) { bb=&pnt[aa->p1]; l.i1=bb->i; l.j1=bb->j; lin.add(l); }
//if (aa->p0>=0) { bb=&pnt[aa->p0]; l.i1=bb->i; l.j1=bb->j; lin.add(l); }
//if (aa->p1>=0) { bb=&pnt[aa->p1]; l.i1=bb->i; l.j1=bb->j; lin.add(l); }
} */
// add connected points to lin[] ... this is hole perimeter !!!
l.id=lin[ix[j-1]].id;
// add index of points instead points
int lin_i1=lin.num;
for (i0=0,aa=&pnt[i0];i0<pnt.num;i0++,aa++)
{
l.i0=i0;
if (aa->p0>i0) { l.i1=aa->p0; lin.add(l); }
if (aa->p1>i0) { l.i1=aa->p1; lin.add(l); }
}
// reorder perimeter lines
for (i0=lin_i1,a=&lin[i0];i0<lin.num-1;i0++,a++)
for (i1=i0+1 ,b=&lin[i1];i1<lin.num ;i1++,b++)
{
if (a->i1==b->i0) { a++; l=*a; *a=*b; *b=l; a--; break; }
if (a->i1==b->i1) { a++; l=*a; *a=*b; *b=l; i=a->i0; a->i0=a->i1; a->i1=i; a--; break; }
}
// convert point indexes to points
for (i0=lin_i1,a=&lin[i0];i0<lin.num;i0++,a++)
{
bb=&pnt[a->i0]; a->i0=bb->i; a->j0=bb->j;
bb=&pnt[a->i1]; a->i1=bb->i; a->j1=bb->j;
}
holes::holes_end作品 lin[]按孔和密度图分割/分组/排序 map[][] .pnt[] (没有重复)。因此,为每条线取 2 个端点,并查看每个点是否已在列表中。如果不添加它,否则忽略它。 map[][] 中的 4 个邻居来移除所有与非孔区域没有接触的点。 used=0; p0=-1; p1=-1;对于 pnt[] 中的所有点列表 distance=1 pnt[]与 used<2这意味着它们尚未完全使用,并且对于每个这样的点搜索 pnt[]再次为另一个这样的点,也有distance = 1到它。这意味着它是它的 4 个邻居,因此应该连接 添加 他们的展位的连接信息(使用 p0 或 p1 未使用的索引 (-1) )并增加两个点的使用量。 distance=sqrt(2) 连接点pnt[] 形成多边形p0 或 p1 )。然后添加它的连接点(不同于之前添加到多边形的点以避免前后循环)。添加尽可能多的点数 pnt[] . 关于c# - 在二维点集中寻找洞?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21816562/
几个月前,我读了一篇关于rubygem的博客文章,它可以通过阅读代码本身来确定编程语言。对于我的生活,我不记得博客或gem的名称。谷歌搜索“ruby编程语言猜测”及其变体也无济于事。有人碰巧知道相关gem的名称吗? 最佳答案 是这个吗:http://github.com/chrislo/sourceclassifier/tree/master 关于ruby-寻找通过阅读代码确定编程语言的rubygem?,我们在StackOverflow上找到一个类似的问题:
如何在ruby中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL
我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha
C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.
我正在处理http://prepwork.appacademy.io/mini-curriculum/array/中概述的数组问题我正在尝试创建函数my_transpose,它接受一个矩阵并返回其转置。我对写入二维数组感到很困惑!这是一个代码片段,突出了我的困惑。rows=[[0,1,2],[3,4,5],[6,7,8]]columns=Array.new(3,Array.new(3))putscolumns.to_s#Outputisa3x3arrayfilledwithnilcolumns[0][0]=0putscolumns.to_s#Outputis[[0,nil,nil],[
我如何做Ruby方法"Flatten"RubyMethod在C#中。此方法将锯齿状数组展平为一维数组。例如:s=[1,2,3]#=>[1,2,3]t=[4,5,6,[7,8]]#=>[4,5,6,[7,8]]a=[s,t,9,10]#=>[[1,2,3],[4,5,6,[7,8]],9,10]a.flatten#=>[1,2,3,4,5,6,7,8,9,10 最佳答案 递归解决方案:IEnumerableFlatten(IEnumerablearray){foreach(variteminarray){if(itemisIEnume
我最近从C#转向了Ruby,我发现自己无法制作可折叠的标记代码区域。我只是想到做这种事情应该没问题:classExamplebegin#agroupofmethodsdefmethod1..enddefmethod2..endenddefmethod3..endend...但是这样做真的可以吗?method1和method2最终与method3是同一种东西吗?还是有一些我还没有见过的用于执行此操作的Ruby惯用语? 最佳答案 正如其他人所说,这不会改变方法定义。但是,如果要标记方法组,为什么不使用Ruby语义来标记它们呢?您可以使用
什么是Linq聚合方法的ruby等价物。它的工作原理是这样的varfactorial=new[]{1,2,3,4,5}.Aggregate((acc,i)=>acc*i);每次将数组序列中的值传递给lambda时,变量acc都会累积。 最佳答案 这在数学以及几乎所有编程语言中通常称为折叠。它是更普遍的变形概念的一个实例。Ruby从Smalltalk中继承了这个特性的名称,它被称为inject:into:(像aCollectioninject:aStartValueinto:aBlock一样使用。)所以,在Ruby中,它称为inj
技术选型1,前端小程序原生MINA框架cssJavaScriptWxml2,管理后台云开发Cms内容管理系统web网页3,数据后台小程序云开发云函数云开发数据库(基于MongoDB)云存储4,人脸识别算法基于百度智能云实现人脸识别一,用户端效果图预览老规矩我们先来看效果图,如果效果图符合你的需求,就继续往下看,如果不符合你的需求,可以跳过。1-1,登录注册页可以看到登录页有注册入口,注册页如下我们的注册,需要管理员审核,审核通过后才可以正常登录使用小程序1-2,个人中心页登录成功以后,我们会进入个人中心页我们在个人中心页可以注册人脸,因为我们做人脸识别签到,需要先注册人脸才可以进行人脸比对,进
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭8年前。Improvethisquestion几年前我去学校学习编程,毕业后我找到了一份系统管理方面的工作,这就是我职业生涯的方向。我想重新开始某种开发,并且一直在“玩”C#和ASP.NET,但我已经听到很多关于其他"new"语言的讨论(新的意思是它们是新的)我)喜欢Ruby和F#。我想我想知道我是否在浪费时间学习主要的MS语言,而不是成为一名通才。很长一段时间没有离开开发社区(如果我曾经离开过的话)让我在潮流中挣扎,我不想落在时代的