新增头文件:
新增源文件:hit_test_tool.cpp
//hit_test_tool.cpp
#include "hit_test_tool.hpp"
#include <cmath>
#include <algorithm>
//求两点间的直线距离(已知直角三角形两直角边长度,求斜边长度)
double get_line_length(int startX, int startY
, int endX, int endY)
{
double dx = endX - startX;
double dy = endY - startY;
return std::sqrt(dx * dx + dy * dy);
}
//点testX, testY是否在给定的线段上
bool OnLineSegment(int startX, int startY
, int endX, int endY
, int testX, int testY)
{
//允许的误差值,否则我们点半天也点不到线上
const double MARGIN_FOR_LINE_HITTEST_ERROR = 0.01;
double l1 = get_line_length(startX, startY, testX, testY);
double l2 = get_line_length(testX, testY, endX, endY);
double l = get_line_length(startX, startY, endX, endY);
return std::abs(l - (l1 + l2)) <= MARGIN_FOR_LINE_HITTEST_ERROR;
}
//点testX, testY是否在给定的方框内
bool InRect(int startX, int startY
, int endX, int endY
, int testX, int testY
, bool hollow) //hollow:是否“中空”
{
int minorX = std::min(startX, endX);//startX,endX中的较小值
int minorY = std::min(startY, endY);
int biggishX = std::max(startX, endX);
int biggishY = std::max(startY, endY);
if(hollow)
{
//如果“中空”,就简单粗暴地判断是不是在框的四条边线上
return OnLineSegment(minorX, minorY, minorX, biggishY, testX, testY)
|| OnLineSegment(minorX, minorY, biggishX, minorY, testX, testY)
|| OnLineSegment(biggishX, biggishY, biggishX, minorY, testX, testY)
|| OnLineSegment(biggishX, biggishY, minorX, biggishY, testX, testY);
}
else
{
return (testX >= minorX && testX <= biggishX)
&& (testY >= minorY && testY <= biggishY);
}
}
//点testX, testY是否在给定的圆内
bool InCircle(int centerX, int centerY, int radius
, int testX, int testY
, bool hollow) //hollow:是否“中空”
{
double distance = get_line_length(centerX, centerY, testX, testY);
const double MARGIN_FOR_CIRCLE_HITTEST_ERROR = 2.5;
if(hollow)
{
return std::abs(distance - radius) <= MARGIN_FOR_CIRCLE_HITTEST_ERROR;
}
else
{
return distance <= radius;
}
}
为抽象类添加新接口:
小提示:在已经有不少派生类的情况下调试基类的新接口
一旦为IItem添加一个纯虚的接口,比如前述的 IsHitOn(), 就意味着我们不得不为所有当前已经存在的派生类都实现该接口之后,程序才能够编译通过,运行起来接受测试。小窍门是暂时将IItem::IsHitOn 改成一个空的实现,默认返回false。等后续完成各派生类实现了,才将它恢复成纯虚接口, 不推荐这样做,推荐的做法是为每个派生类写一个空的实现,先简单返回false
实现接口:
直线:
item_line.hpp
item_line.cpp
其他图形,接口IsHitOn(int x, int y)暂时实现为一个空实现: