【算法记录/计算几何】计算三角形覆盖的格子集合

问题描述

  • 如下图,需要计算三角形ABC所覆盖的格子集合。
    在这里插入图片描述

方法一

  • 计算出囊括三角形ABC的最小矩形,判断矩形中每一个格子是否在三角形内。
    在这里插入图片描述

方法二

  • 先计算出线段AB、BC、CA覆盖的格子
    AB:(1,4)(2,5)(3,5)(4,6)
    BC:(4,6)(5,5)(5,4)(6,3)
    CA:(6,3)(5,3)(4,3)(3,4)(4,4)(5,4)
  • 然后将这些坐标按x轴进行归纳,即x坐标相同的两点,对于这两点之间的点,视为三角形内。
    例如(4,4)(4,6),那么(4,5)必然在三角形内。
  • code
    #include <iostream>
    #include <vector>
    #include <map>
    #include <algorithm>
    
    struct Point
    {
    	int x;
    	int y;
    
    	Point() {};
    	Point(int x_, int y_) : x(x_), y(y_) {};
    };
    
    struct VerticalLine
    {
    	int x;
    	int minY;
    	int maxY;
    
    	VerticalLine() {};
    	VerticalLine(int x_, int min_, int max_) :x(x_), minY(min_), maxY(max_) {};
    };
    
    // 计算线段上的格子
    void PointLine(std::vector<Point*>& result, Point p0, Point p1)
    {
    	int dx = p1.x - p0.x;
    	int dy = p1.y - p0.y;
    
    	int N = std::max<int>(abs(dx), abs(dy));
    
    	float divN = (N == 0) ? 0.0 : 1.0 / N;
    	float xStep = dx * divN;
    	float yStep = dy * divN;
    
    	float x = p0.x;
    	float y = p0.y;
    
    	for (int step = 0;step <= N; step++) {
    		result.push_back(new Point(round(x), round(y)));
    
    		x += xStep;
    		y += yStep;
    	}
    }
    
    // 计算三角形覆盖的格子
    void TrianglePoint(std::vector<Point*>& result, Point p0, Point p1, Point p2)
    {
    	std::map<int, VerticalLine*> data;
    
    	std::vector<Point*> list;
    	PointLine(list, p0, p1);
    	PointLine(list, p1, p2);
    	PointLine(list, p2, p0);
    
    	Point* tmpPoint;
    	VerticalLine* tmpVerLine;
    
    	std::map<int, VerticalLine*>::iterator mIter;
    	for (auto p : list) 
    	{
    		mIter = data.find(p->x);
    		if (mIter == data.end())
    		{
    			data.insert(std::pair<int, VerticalLine*>(p->x, new VerticalLine(p->x, p->y, 0)));
    			continue;
    		}
    
    		tmpVerLine = (*mIter).second;
    		if (p->y >= tmpVerLine->minY) {
    			tmpVerLine->maxY = p->y;
    			continue;
    		}
    
    		tmpVerLine->maxY = tmpVerLine->minY;
    		tmpVerLine->minY = p->y;
    	}
    
    	for (auto item : data) {
    		tmpVerLine = item.second;
    
    		for (int y = tmpVerLine->minY;y <= tmpVerLine->maxY;y++)
    		{
    			result.push_back(new Point(tmpVerLine->x, y));
    		}
    	}
    }
    
    int main()
    {
    	std::vector<Point*> res;
    	Point p0(1, 4);
    	Point p1(4, 6);
    	Point p2(6, 3);
    
    	TrianglePoint(res, p0, p1, p2);
    
    	return 0;
    }
    
  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值