4. Calculate the design and implementation of the interface module
My unique in that segment for the rays are basically a call to the original linear correlation function of the realization of new features , straight line segments when calculating the first ray intersection or into which they are located, and then determine the intersection of the straight line is calculated whether the point is on the line segment or radiation, greatly simplifies the code logic.
Considering that the geometric objects encapsulate only data is stored, the method does not involve therefore the package geometry with struct
struct Point {//点
double x;
double y;
double length;
bool operator ==(const Point& b) const noexcept
{
if (compareDouble(x - b.x) == 0 && compareDouble(y - b.y) == 0) return true;
return false;
}
bool operator <(const Point& b) const noexcept
{
if (compareDouble(x - b.x) == 0 && compareDouble(y - b.y) < 0) return true;
if (compareDouble(x - b.x) < 0) return true;
return false;
}
};
typedef Point Vector; //向量
struct Line { //直线
Point p1, p2;
};
struct Segment { //线段
Point p1, p2;
};
struct Ray { //射线
Point start, direction;
};
struct Circle { //圆
Point center;
double r;
};
Command line handler, get the name of the input and output file. Get all the geometric objects from the input file, the same kind of geometric objects into the same vector. The intersection of all Point
the set into a set
.
vector<Line> lineSet;
vector<Segment> segmentSet;
vector<Ray> raySet;
vector<Circle> circleSet;
set<Point> pointSet;
Intersection point calculation calPoint
function or between two different classes in the same vector at the internal vector. Intersection point calculation getPoint
function between two geometric objects, the number of intersections returned calculated: NOCROSS
, , ONECROSS
, TWOCROSS
(numerousMANYCROSS
intersections).
Intersection calculating function defined as follows
int getPoint(Line l1, Line l2, Point& crossPoint) noexcept;
int getPoint(Line l, Segment s, Point& crossPoint) noexcept;
int getPoint(Line l, Ray r, Point& crossPoint) noexcept;
int getPoint(Line l, Circle c, pair<Point, Point>& crossPair) noexcept;
int getPoint(Segment s1, Segment s2, Point& crossPoint) noexcept;
int getPoint(Segment s, Ray r, Point& crossPoint) noexcept;
int getPoint(Segment s, Circle c, pair<Point, Point>& crossPair) noexcept;
int getPoint(Ray r1, Ray r2, Point& crossPoint) noexcept;
int getPoint(Ray r, Circle c, pair<Point, Point>& crossPair) noexcept;
int getPoint(Circle c1, Circle c2, pair<Point, Point>& crossPair) noexcept;
int calPoint(vector<Line>& lineSet, set<Point>& pointSet);
int calPoint(vector<Line>& lineSet, vector<Segment>& segmentSet, set<Point>& pointSet);
int calPoint(vector<Line>& lineSet, vector<Ray>& raySet, set<Point>& pointSet);
int calPoint(vector<Line>& lineSet, vector<Circle>& circleSet, set<Point>& pointSet);
int calPoint(vector<Segment>& segmentSet, set<Point>& pointSet);
int calPoint(vector<Segment>& segmentSet, vector<Ray>& raySet, set<Point>& pointSet);
int calPoint(vector<Segment>& segmentSet, vector<Circle>& circleSet, set<Point>& pointSet);
int calPoint(vector<Ray>& raySet, set<Point>& pointSet);
int calPoint(vector<Ray>& raySet, vector<Circle>& circleSet, set<Point>& pointSet);
int calPoint(vector<Circle>& circleSet, set<Point>& pointSet);
int calPoint(vector<Line>& lineSet, vector<Segment>& segmentSet, vector<Ray>& raySet, vector<Circle>& circleSet, set<Point>& pointSet);
The rays into a linear segment or determines whether a key point in the function of a line segment or range of radiation:
//将线段转化成对应的直线
//将横坐标较小的点作为p1,若两点横坐标相同则将纵坐标较小的点作为p1
Line segmentToLine(Segment s) {
Line l;
if ((s.p1.x < s.p2.x) || ((s.p1.x == s.p2.x) && (s.p1.y < s.p2.y))) {
l.p1 = s.p1;
l.p2 = s.p2;
} else {
l.p1 = s.p2;
l.p2 = s.p1;
}
return l;
}
//将射线转化成对应的直线
Line rayToLine(Ray r) {
Line l{ r.start, r.direction };
return l;
}
//判断一个点是否在一线段的坐标范围内
int pointIfOnSeg(Point p, Line l)
{
if (l.p1.x == l.p2.x) {
if ((p.y >= l.p1.y) && (p.y <= l.p2.y)) {
return ON;
} else {
return NOTON;
}
} else {
if ((p.x >= l.p1.x) && (p.x <= l.p2.x)) {
return ON;
} else {
return NOTON;
}
}
}
//判断一个点是否在一射线的坐标范围内
int pointIfOnRay(Point p, Line l)
{
if (l.p2.x < l.p1.x) {
//若射线指向负方向
if (p.x <= l.p1.x) {
return ON;
} else {
return NOTON;
}
} else if (l.p2.x == l.p1.x && l.p2.y < l.p1.y) {
//若射线指向正下方
if (p.y <= l.p1.y) {
return ON;
} else {
return NOTON;
}
} else if (l.p2.x == l.p1.x && l.p2.y > l.p1.y) {
//若射线指向正上方
if (p.y >= l.p1.y) {
return ON;
} else {
return NOTON;
}
} else {
//若射线指向正方向
if (p.x >= l.p1.x) {
return ON;
} else {
return NOTON;
}
}
}
Calculation module interface section 6. Performance Improvement
Using a randomly generated test set contains more than a thousand pieces of data.
Obviously, the program will use most of the time in the set of elements inserted on.
In addition, based on the exact value determined rewriting equals significance also take up a lot of time
8. The display calculation module of the unit test
Defined above function module design part of the show, the calculation module is divided into LL, LR, LS, LC, SS, SR, SC, RR, RC, CC several functions, as long as these are covered calculate the intersection of these getPoint
functions, you to cover other computing functions that call. In order to cover all calPoint
functions, and then write a large test set contains a complete test of all types of calPoint
functions to achieve better coverage.
//测试圆与圆交点的多种情况,除保证计算交点个数正确外,还要保证计算的交点坐标正确
TEST_METHOD(Circle_Circle_TwoCross)
{
Circle c1;
Circle c2;
c1.center.x = 0; c1.center.y = 0; c1.r = 2;
c2.center.x = 2; c2.center.y = 0; c2.r = 2;
Point realPoint1, realPoint2;
pair<Point, Point> testPair;
realPoint1.x = 1; realPoint1.y = 1.73205081;
realPoint2.x = 1; realPoint2.y = -1.73205081;
Assert::IsTrue(getPoint(c1, c2, testPair) == 2);
Assert::IsTrue(((realPoint1 == testPair.first) && (realPoint2 == testPair.second)) || ((realPoint2 == testPair.first) && (realPoint1 == testPair.second)));
}
TEST_METHOD(Circle_Circle_OneCross)
{
Circle c1;
Circle c2;
c1.center.x = 0; c1.center.y = 0; c1.r = 2;
c2.center.x = 4; c2.center.y = 0; c2.r = 2;
Point realPoint1, realPoint2;
pair<Point, Point> testPair;
realPoint1.x = 2; realPoint1.y = 0;
Assert::IsTrue(getPoint(c1, c2, testPair) == 1);
Assert::IsTrue(realPoint1 == testPair.first);
}
TEST_METHOD(Circle_Circle_NoCross)
{
Circle c1;
Circle c2;
c1.center.x = 0; c1.center.y = 0; c1.r = 2;
c2.center.x = 5; c2.center.y = 0; c2.r = 2;
Point realPoint1, realPoint2;
pair<Point, Point> testPair;
Assert::IsTrue(getPoint(c1, c2, testPair) == 0);
}
TEST_METHOD(TestAll)
{
vector<Line> lineSet;
vector<Segment> segmentSet;
vector<Ray> raySet;
vector<Circle> circleSet;
set<Point> pointSet;
Line l1, l2; Segment s1, s2, s3; Ray r1, r2, r3; Circle c1, c2;
l1.p1.x = 1; l1.p1.y = 2; l1.p2.x = 3; l1.p2.y = 3;
l2.p1.x = 4; l2.p1.y = 2; l2.p2.x = 2; l2.p2.y = -4;
lineSet.push_back(l1); lineSet.push_back(l2);
s1.p1.x = -5; s1.p1.y = 1; s1.p2.x = 5; s1.p2.y = -3;
s2.p1.x = 5; s2.p1.y = 3; s2.p2.x = 2; s2.p2.y = 2;
s3.p1.x = 6; s3.p1.y = -5; s3.p2.x = 6; s3.p2.y = 6;
segmentSet.push_back(s1); segmentSet.push_back(s2);
segmentSet.push_back(s3);
r1.start.x = 5; r1.start.y = 2; r1.direction.x = 3; r1.direction.y = 4;
r2.start.x = 2; r2.start.y = -4; r2.direction.x = -1; r2.direction.y = -1;
r3.start.x = -10; r3.start.y = 1; r3.direction.x = 10; r3.direction.y = 1;
raySet.push_back(r1); raySet.push_back(r2); raySet.push_back(r3);
c1.center.x = 2; c1.center.y = 3; c1.r = 4;
c2.center.x = 5; c2.center.y = 2; c2.r = 2;
circleSet.push_back(c1); circleSet.push_back(c2);
Assert::AreEqual(calPoint(lineSet, segmentSet, raySet, circleSet, pointSet), 31);
}
Screenshot coverage calculation module GeoCalculate.pp
coverage reached 90%:
9. The computing module sections exception handling instructions. Each exception in a blog presentation design goals in detail. Each anomaly must choose a unit test sample posted in the blog, and indicate the error corresponding to the scene.
We designed the following categories exception:
- Illegal input format
- Enter the lack of geometric objects
- Enter the end of the file contents too
- Coordinate range exceeds the limit
- Command line parameters are other characters
- The number of intersection for the countless
Illegal input format
When confronted with the input data does not meet the requirements, such as the beginning of the file does not appear n, the illegal character, when the data is not correct geometric objects, throw exceptions illegalInputPattern
Unit Testing Sample:
Enter the lack of geometric objects
The first line of the file obtained from n, but when the input data is less than the n after the file, an exception is thrownnotEnoughInputElement
Unit Testing Sample:
Enter the end of the file contents too
After reading of the data of n and n geometric object file There undesirable content, an exception is thrownTooManyInputElements
Unit Testing Sample:
Coordinate range exceeds the limit
For each input data, it is determined in the range of (-100000,100000), if not, an exception is thrown outRangeException
. And when the small circle is equal to zero or an input radius, this will throw an exception.
Unit Testing Sample:
Command line parameters are other characters
If the command-line parameter is incorrect, an exception is thrown commandException
.
Unit testing sample :( command-line arguments for the "-d")
The number of intersection is an infinite number of
If the two figures there are numerous points of intersection, an exception is thrown infException
.
Unit test samples the two straight lines coinciding :()
Detailed design process 10. The interface module. In a blog details how to interface module is designed for, and write some necessary code description explains the implementation process.
Qt Creator interface module development, design of two windows, a main interface Dialog , the other is a drawing interface new_window .
The main interface as shown:
Then one by one to introduce four functions implemented:
-
open a file
void Dialog::readFile()
functionUsing the
getOpenFileName
method of acquiring the file path, the file open and, withreadLine
the method to read the file line by line content, and withsplit
the string dividing method according to the space, is stored in the corresponding structure. Finally, using theui->label->setText
contents of the read method displayed on the interface.Click "Open File" button and select the file results as shown:
-
Adding Graphics
void Dialog::addone()
functionUsing the
ui->text->toPlainText
method of acquiring the character string in the text box, withsplit
the method divided and stored into the respective structure. Finally, using theui->label_2->setText
method to add the data displayed on the screen.Click on the "Add" button shown in FIG effect:
-
Delete Graphics
void Dialog::deleteone()
functionUsing the
ui->text->toPlainText
method of acquiring the character string in the text box, asplit
method of segmenting, elements corresponding to the data is found and deleted. Finally, using theui->label_2->setText
method the deleted data is displayed on the screen.Click the "Delete" button effects as shown:
-
Graphing and intersection
void Dialog::open()
functionOpen a new window new_window , rewrite
paintEvent
method, image rendering.Drawing method:
- Line: drawLine
- Round: drawEllipse
- Point: drawPoint
Graphics rendering results as shown:
11. The docking module and the computing module interface. Description docking UI module design and two modules in detail, and the screenshot function implemented in the blog.
We need to use the intersection point calculation calPoint
method, which is a set of five interface structure, representing the straight line segment, radiation, and round point. My idea is to structure the interface module is also packaged in the same form, call the direct method can be calculated. Add the Release version of dynamic link libraries and header files related to your project, you can call this method directly.
Display functions to achieve
Add 3 from graphics file and add a pattern (rays) manually, as shown:
Click "draw graphics and intersection" button results as shown:
Add 4 from the graphic file, and manually remove a pattern (line), as shown:
Click "draw graphics and intersection" button results as shown: