多线程 1
载入中...
搜索中...
未找到
FillPology.hpp
浏览该文件的文档.
1//
2// FillPology.hpp
3// 多线程
4//
5// Created by 赵明明 on 2023/6/15.
6//
7#pragma once
8#ifndef FillPology_hpp
9#define FillPology_hpp
10
11#include <stdio.h>
12#include <iostream>
13#include <algorithm>
14#include "矩阵.hpp"
15#include <vector>
16#include "线.hpp"
17#include <cmath>
18
19using namespace std;
20
25
27{
28public:
32 矩阵 * points=NULL;
34 矩阵 * vns=NULL;
36 矩阵 * 视线=NULL;
40 vector<矩阵*> select_pos;
42 矩阵 * pmin=NULL;
44 矩阵 * pmax=NULL;
47public:
50 坐标阵[0]=NULL;
51 坐标阵[1]=NULL;
52
53 };
54
60 FillPology(矩阵* 多边形顶点,矩阵* 法线=NULL,矩阵* view_vector=NULL,int plane_index=0){
61 points=多边形顶点;
62 vns=法线;
63 视线=view_vector;
64 //select_pos=NULL;
65 坐标阵[0]=NULL;
66 坐标阵[1]=NULL;
67 this->plane_index=plane_index;
68
69 }
70
73 矩阵* minmax=NULL;
74
75
76 minmax=points->minmax(0);
77 pmin=((*minmax)["0,:"]);
78 pmax=((*minmax)["1,:"]);
79 //cout<<*(pmax);
80 //cout<<*(pmin);
81
82 线 线1=线(0.2,0.5);
83 //矩阵* 左右扫描点=NULL;
84 int ymax=(int)((*pmax)[1]);//向下取整
85 int ymin=(int)((*pmin)[1]);//向上取整
86
87 int step=0;
88 if(ymax>ymin){
89 step =(ymax-ymin)/((int)ymax-(int)ymin);
90 }else if (ymax==ymin){
91 float data[4]={(*pmin)[0],(float)ymax,(*pmax)[0],(float)ymax};
92 矩阵* 左右点=new 矩阵(2,2,data,1);
93 if(!左右扫描点){
94 左右扫描点=左右点;
95 }else{
97 }
98 // 确保每条扫描线得到两个点。 扫面线的数据是左右扫描点的1/2
99 //cout<<"扫描线: "<<((int)ymax-(int)ymin)+1<<","<<左右扫描点->h<<endl;
100 assert( ((ymax-ymin)+1)*2 == 左右扫描点->h );
101
102 //cout<<*左右扫描点;
103 return 左右扫描点;
104
105 }
106
107
108 for(float y=ymin;y<ymax+1;y+=step){
109 float data[4]={(*pmin)[0],(float)y,(*pmax)[0],(float)y};
110 int imax=points->h;//被扫描边数
111 int imin=0;//被扫描边的开始序号
112 // 判断y在某个顶点上,且不在上下边界
113 bool y_in_edge_flag=((y-ymin<step) or (ymax-y<step)) or (y-ymin==0) or(ymax-y==0);
114 // 判断当前扫描线是否位于两条边的交点, -1 表示不在交点
115 int y_in_point_index=-1;
116 矩阵 差=(*(*points)[":,1"])-y;
117 float y_in_point_flag[4]={0,0,0,0};
118 for(int 差i=0;差i<差.h;差i++){
119 if(abs(差[差i])<step*0.5 or abs(差[差i])==0){
120 y_in_point_flag[差i]=1;
121
122 if((y_in_point_flag[0]+y_in_point_flag[1]==1) and 差i==2 and imax==4){imax=imax-1;}// 当序号为0,2的点在扫描线上时,不扫描最后一条边
123
124 y_in_point_index=差i;// 存储多边形上的、在扫描线上的最后一个点、的序号
125 }
126 }
127 矩阵 旗 = 矩阵(1,4,y_in_point_flag,1);
128
129 if((旗.())->data[0]==3){imax = points->h;}// 如果4边形有3个点都在扫描线上
130 if(旗[1]==1 and 旗[3]==1 and (旗.())->data[0]==2){imin=1;}
131 矩阵 扫描线=矩阵(2,2,(float *)data,1);
132
133 for(int i=imin;i<imax;i++){
134 矩阵* 边=NULL;
135 if(i<points->h-1){
136 stringstream ss;
137 ss<<i<<":"<<i+2<<",:";
138 边=(*points)[ss.str()];
139
140 }
141 else if(i==points->h-1){
142 stringstream ss;
143 ss<<i<<",:";
144 边=points->r_((*points)[ss.str()],(*points)["0,:"]);
145 }
146 /*
147 cout<<"扫描线:";
148 cout<<扫描线;
149 cout<<"边:";
150 cout<<*(边);
151 */
152
153 float 被替换的序号2=0;
154 边->取整();
155 扫描线.取整();
156 // 如果边与扫描线共线
157 if(边->data[1]==边->data[3] and 边->data[1]==扫描线[1]){
158 //什么也不做,因为左右两个端点在构成其他边的时候,可以被求取出来
159 }
160 else{// 如果边与扫描线不共线
161 矩阵* 交点2=线1.线段交点(*边,扫描线,&被替换的序号2);
162 /*cout<<"多边形,边,扫描线,交点"<<endl;
163 cout<<*points;
164 cout<<*边;
165 cout<<扫描线;
166 cout<<*交点2;
167 */
168 if( 被替换的序号2 != 线1.Inf){
169 if(!左右扫描点){
170 左右扫描点=new 矩阵(*交点2);
171 }else{
173 }
174 }
175 //扫描两条边的交点处时,如果交点不是上下限点,就跳过两条边中的一条,
176 //避免扫描到四边形的某个顶点时,计算得到2个左点或者2个右点
177 if(!y_in_edge_flag){
178
179 if(y_in_point_index==i+1){//如果线段的第2个点是交点,那就就不再扫描以第二个点为起点的线段
180 i=i+1;
181 }
182 if(y_in_point_index==i and i==0){//如果只有序号为0的点在扫描线上,那么不扫描最后一条边
183 imax=imax-1;
184 }
185 }
186
187 }
188 }
189 //cout<<"左右扫描点"<<endl;
190 //cout<<(*左右扫描点);
191 }
192 // 确保每条扫描线得到两个点。 扫面线的数据是左右扫描点的1/2
193 //cout<<"plane_index:"<<plane_index<<" 扫描线: "<<((int)ymax-(int)ymin)+1<<","<<左右扫描点->h<<endl;
194 assert( ((ymax-ymin)+1)*2 == 左右扫描点->h );
195
196 //cout<<*左右扫描点;
197 return 左右扫描点;
198 }
199
202 矩阵* select_pos_return=NULL;
203 矩阵* minmax=NULL;
204 minmax=points->minmax(0);
205 pmin=((*minmax)["0,:"]);
206 pmax=((*minmax)["1,:"]);
207 float minx=(*pmin)[0];
208 float miny=(*pmin)[1];
209 float maxx=(*pmax)[0];
210 float maxy=(*pmax)[1];
211
212 select_pos_return = new 矩阵(maxy-miny+1,maxx-minx+1,0);
213 for(int j=0;j<maxy-miny;j+=1){
214 float x1=(*左右扫描点)[0+j*4];
215 float x2=(*左右扫描点)[2+j*4];
216 float y=(*左右扫描点)[1+j*4];
217 //cout<<x1<<","<<x2<<","<<y<<endl;
218 // 交换x1和x2的值
219 if(x1>x2){
220 x1=x1+x2;
221 x2=x1-x2;
222 x1=x1-x2;
223 }
224 for(int x=x1;x<x2+1;x++){
225 select_pos_return->data[x-(int)minx+(int)(round(y)-miny)*select_pos_return->w]=1;
226 }
227 }
228 select_pos.insert(select_pos.end(),select_pos_return);
229 return select_pos_return;
230 }
231
233 矩阵* fill_color(矩阵 * img, float * color){
234 矩阵* select_pos_return=NULL;
235 *color=need_display();
236 //cout<<*color<<endl;
237 if(*color<0){ return select_pos_return;}
238 if(!左右扫描点){
239 get_scan();
240 }
241
242 矩阵* minmax=NULL;
243 minmax=points->minmax(0);
244 pmin=((*minmax)["0,:"]);
245 pmax=((*minmax)["1,:"]);
246 float minx=(*pmin)[0];
247 float miny=(*pmin)[1];
248 float maxx=(*pmax)[0];
249 float maxy=(*pmax)[1];
250
251 select_pos_return = new 矩阵(maxy-miny+1,maxx-minx+1,0);
252 //assert(img->h==select_pos_return->h);
253 //assert(img->w==select_pos_return->w);
254
255 for(int j=0;j<maxy-miny;j+=1){
256 float x1=(*左右扫描点)[0+j*4];
257 float x2=(*左右扫描点)[2+j*4];
258 float y=(*左右扫描点)[1+j*4];
259 //cout<<x1<<","<<x2<<","<<y<<endl;
260 // 交换x1和x2的值
261 if(x1>x2){
262 x1=x1+x2;
263 x2=x1-x2;
264 x1=x1-x2;
265 }
266 // x=x+1开始填色,尝试避免抖动,经实验发现,虽然不抖动了,但是会出现一些黑点。这是由于从x+1开始,带来的副作用.
267
268 if(( (int)(x1*1000)-((int)x1)*1000)>0){ //为避免上述副作用,只在当x为小数时,向上取整。实验发现,两个平面的边缘部分不再抖动了。只剩下物体边缘的平面在抖动。这个不是这里能够解决的了。因为是平面法线不准确,造成本不应该被完全显示的平面,进行了完全显示,遮挡了前方的平面。
269 x1=int(x1+1);
270 }
271
272 for(float x=x1;x<x2;x++){
273 select_pos_return->data[(int)x-(int)minx+(int)(round(y)-(int)miny)*select_pos_return->w]=1;
274 /*
275 if(vns->h==4){
276 矩阵 点=矩阵(1,2,(float)0);
277 点[0]=x;
278 点[1]=y;
279 *color = cacu_color(&点);
280
281 }*/
282
283 if(*color>0){
284 img->data[(int)x+(int)round(y)*img->w]=*color;
285 }
286
287 }
288 }
289 return select_pos_return;
290 }
291
293 float need_display(void){
294 if(!视线){
295 float view[]={0,0,1};
296 视线=new 矩阵(1,3,view,1);
297 }
298 // 差值法计算的发现是错误的,直接用第一个点的发线来计算亮度
299 //矩阵* 亮度=法线.点积(视线);
300 矩阵 *暂时法线=(*((*vns).和(0))).单位化();
301 /*cout<<*vns;
302 cout<<*((*vns).和(0));
303 cout<<*暂时法线;
304 cout<<视线;
305 */矩阵* 亮度=暂时法线->点积(*视线);
306 //cout<<*暂时法线;
307 //cout<<"亮度:"<<亮度->data[0]<<endl;
308 亮度->data[0]=-亮度->data[0];
309 if(亮度->data[0]<0){亮度->data[0]=0;}
310 return 亮度->data[0];
311 }
312
315 float cacu_color(矩阵 * 点){
316 //float color=0.5;
317 //cout<<*点;
318 //cout<<vns->w<<","<<vns->h<<endl;
319 //cout<<*vns;
320
321 // 计算a,b,c,d: a = norm(view) 点积 norm(vns)
322 // 计算ar,br,cr,dr
323 //计算pu,pb
324 //计算pur pdr
325 //计算p
326 矩阵 横差=*points - 点->data[0];
327 // 计算
328 float pax=横差[0];
329 float pbx=-横差[1];
330 // ar,br
331 float puw[]={pbx/(pax+pbx),pax/(pax+pbx)};
332 矩阵 PUW=矩阵(1,2,puw,1);
333 矩阵* aby_=(*(*points)["0:2,:"])[":,1"];
334 aby_->转置();
335 // 计算y ,即pu,
336 矩阵* puy=PUW.点积(*aby_);
337 // 计算法线
338 矩阵 上法线=*((*vns)["0,:"])*PUW[0]+*((*vns)["1,:"])*PUW[1];
339
340
341 float pcx=横差[2];
342 float pdx=-横差[3];
343 // cr ,dr
344 float pdw[]={pdx/(pcx+pdx),pcx/(pcx+pdx)};
345 矩阵 PDW=矩阵(1,2,pdw,1);
346 矩阵* cdy_=(*(*points)["2:4,:"])[":,1"];
347 cdy_->转置();
348 // 计算y, 即pd
349 矩阵* pdy=PDW.点积(*cdy_);
350 // 计算法线
351 矩阵 下法线=*((*vns)["2,:"])*PUW[0]+*((*vns)["3,:"])*PUW[1];
352
353
354 矩阵* PUD = pdy->c_(puy,pdy);
355
356 矩阵 纵差=*PUD - 点->data[1];
357
358 float puyd=纵差[0];
359 float pdyd=-纵差[1];
360 // pur pdr
361 float pudw[]={pdyd/(puyd+pdyd),puyd/(puyd+pdyd)};
362 矩阵 PUDW=矩阵(1,2,pudw,1);
363 // 计算p
364 矩阵* py=PUDW.点积(*PUD);
365 // 计算法线,即,计算p
366 矩阵 法线=(上法线)*PUDW[0]+(下法线)*PUDW[1];
367
368 float view[]={0,0,1};
369 矩阵 视线=矩阵(1,3,view,1);
370 // 差值法计算的发现是错误的,直接用第一个点的发线来计算亮度
371 //矩阵* 亮度=法线.点积(视线);
372 矩阵* 暂时法线=((*vns)["0,:"]);
373 矩阵* 亮度=暂时法线->点积(视线);
374 //cout<<*暂时法线;
375 //cout<<"亮度:"<<亮度->data[0]<<endl;
376 亮度->data[0]=-亮度->data[0];
377 if(亮度->data[0]<0){亮度->data[0]=0;}
378
379 return 亮度->data[0];
380 }
381
384 矩阵* minmax=NULL;
385 矩阵* select_pos_return=NULL;
386
387 minmax=points->minmax(0);
388 pmin=((*minmax)["0,:"]);
389 pmax=((*minmax)["1,:"]);
390 //cout<<*(pmax);
391 //cout<<*(pmin);
392 矩阵* 行x=minmax->arange((*pmin)[0],(*pmax)[0]+1);
393 //cout<<*行x;
394
395 矩阵* 行y=minmax->arange((*pmin)[1],(*pmax)[1]+1);
396 //cout<<*行y;
397
398
399 //矩阵* 坐标阵[]={NULL,NULL};
400 minmax->meshgrid( 行x, 行y,坐标阵);
401 //cout<<"矩阵* 坐标阵=minmax->meshgrid( 行x, 行y);"<<endl;
402 //cout<<*(坐标阵[0]);
403 //cout<<*(坐标阵[1]);
404 矩阵* last_compare=NULL;
405 //vector<矩阵*> select_pos;
406 for(int i=-1;i<points->h-1;i++){
407 stringstream ss1,ss2;
408 ss1<<i+1<<",:";
409
410 if(i==-1){ss2<<points->h-1<<",:";}
411 else{ss2<<i<<",:";}
412 矩阵 p01=*((*points)[ss1.str()])-*((*points)[ss2.str()]);
413
414 矩阵 xd=(*坐标阵[0])-(*points)[i*points->w];
415
416 矩阵 yd=(*坐标阵[1])-(*points)[i*points->w+1];
417
418 矩阵 p01xy=yd*p01[0];
419 矩阵 p01xx=xd*p01[1];
420 矩阵 p01x = p01xy-p01xx;
421
422 矩阵 p01xz=(p01x>=0);
423 //cout<<p01xz;
424
425 if(i>=0){
426 vector<矩阵*>::iterator it;
427 it=select_pos.end();
428 //cout<<(*last_compare);
429 //cout<<p01xz;
430 矩阵 等阵= (*last_compare)==p01xz;
431 //cout<<等阵;
432 select_pos.insert(it,new 矩阵(等阵));
433 //cout<<等阵;
434 }
435
436 if(i>=1){
437 矩阵 乘阵=(*(select_pos[i]))*(*(select_pos[i-1]));
438 //cout<<乘阵;
439 select_pos[i]=new 矩阵(乘阵);
440 }
441
442 last_compare=new 矩阵(p01xz);
443 //cout<<*last_compare;
444
445 }
446
447 //cout<<*(select_pos[select_pos.size()-1]);
448 矩阵* last_sp=select_pos[select_pos.size()-1];
449 select_pos_return = new 矩阵(last_sp->h,last_sp->w,last_sp->data,1);
450
451 return select_pos_return;
452 };
454 int * fill_color(int * img, float * color){
455
456 return img;
457 };
458
460 int * fill_img(int* img,float * img_color,int *select_pos_z,int plane_index){return img;};
461
463 void fill_test(){std::cout<<"fill_test"<<std::endl;};
464};
465#endif /* FillPology_hpp */
int * fill_color(int *img, float *color)
给图像里填充颜色,输入参数是图像指针
矩阵 * 左右扫描点
光删扫描后,得到的左点和右点
vector< 矩阵 * > select_pos
存储在多边形内部的点坐标
矩阵 * vns
多边形每个点的法线
void fill_test()
测试FillPology是否建立成功,并可调用
矩阵 * 视线
看向多边形的视线
矩阵 * get_select_pos_from_scan(矩阵 *左右扫描点)
使用光栅扫描法得到的左右点,计算多边形内点的坐标
矩阵 * fill_color(矩阵 *img, float *color)
利用光删扫描法得到的左右点,对多边形内部填充颜色
FillPology(矩阵 *多边形顶点, 矩阵 *法线=NULL, 矩阵 *view_vector=NULL, int plane_index=0)
float need_display(void)
使用
矩阵 * get_select_pos(int plane_index)
使用矩阵法计算得到多边形内部的点的坐标
float cacu_color(矩阵 *点)
int * fill_img(int *img, float *img_color, int *select_pos_z, int plane_index)
给图像里填充图像,适用于将图像插入当前图像的多边形内
int plane_index
一个三维物体有很多多边形构成,此参数为平面的序号
矩阵 * pmax
多边形点的x,y坐标的最大值
矩阵 * get_scan(void)
尝试光删扫描法,看会不会比矩阵求取法更快一些
矩阵 * pmin
多边形点的x,y坐标的最小值
矩阵 * 坐标阵[]
//! 对应python版本的Fillpology.py的 self.X,self.Y
矩阵 * points
多边形的点
FillPology()
建立各成员指针都为NULL的FillPology 对象
基本的矩阵计算类,用于完成各种矩阵初始化、最大最小、取值、加减乘除、精度设置等矩阵计算
Definition 矩阵.hpp:25
矩阵 * c_(矩阵 *矩阵1, 矩阵 *矩阵2)
Definition 矩阵.hpp:296
float * data
储存矩阵元素的数组
Definition 矩阵.hpp:40
矩阵 * arange(int start, int end)
模仿numpy 的arange
Definition 矩阵.hpp:236
void 取整(void)
对矩阵内的数据取整
Definition 矩阵.hpp:117
int w
矩阵的宽度,即列数
Definition 矩阵.hpp:32
矩阵 * 转置(void)
Definition 矩阵.hpp:458
矩阵 * r_(矩阵 *矩阵1, 矩阵 *矩阵2)
按行合并
Definition 矩阵.hpp:314
int h
矩阵的高度,即行数
Definition 矩阵.hpp:34
矩阵 * minmax(void)
求矩阵中所有元素的最大值,最小值
Definition 矩阵.hpp:196
矩阵 ** meshgrid(矩阵 *行x, 矩阵 *行y, 矩阵 **坐标阵)
模仿numpy 的meshgrid
Definition 矩阵.hpp:247
矩阵 * 和(void)
求矩阵内个元素的和
Definition 矩阵.hpp:162
矩阵 * 点积(矩阵 &矩阵1)
矩阵点积运算,对应位置相乘再相加
Definition 矩阵.hpp:135
矩阵 * 单位化(void)
对矩阵的每一行,进行单位化
Definition 矩阵.hpp:141
Definition 线.hpp:15
矩阵 * 线段交点(矩阵 &线1的两个点, 矩阵 &线2的两个点, float *被替换的序号)
Definition 线.hpp:88
float Inf
Definition 线.hpp:19
矩阵 * img
Definition main.cpp:22