zoukankan      html  css  js  c++  java
  • 交点计数 -- 软工个人项目作业

    项目 内容
    这个作业属于哪个课程 2020春北航计算机学院软件工程(罗杰 任健)
    这个作业的要求在哪里 个人项目作业

    项目地址

    PSP 2.1

    PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
    Planning 计划
    · Estimate · 估计这个任务需要多少时间 10 10
    Development 开发
    · Analysis · 需求分析 (包括学习新技术) 30 60
    · Design Spec · 生成设计文档 30 30
    · Design Review · 设计复审 (和同事审核设计文档) 0 0
    · Coding Standard · 代码规范 (为目前的开发制定合适的规范) 10 10
    · Design · 具体设计 30 50
    · Coding · 具体编码 60 90
    · Code Review · 代码复审 60 60
    · Test · 测试(自我测试,修改代码,提交修改) 120 120
    Reporting 报告
    · Test Report · 测试报告 20 20
    · Size Measurement · 计算工作量 10 10
    · Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划 30 40
    合计 400 500

    解题思路

    基本问题

    直线公式

    对于复杂问题而言,我们首先寻求将问题简化。我们将问题简化到求两条直线的交点。

    由解析几何的知识我们知道,通过两条直线的公式可以求出他们的交点。为了简化问题,我使用直线的一般式来表示直线: Ax+By+C = 0.

    A,B,C 可以由题目中给定的两点坐标计算得出(设两点为 (x_1,y_1),(x_2,y_2) ):

    • A=y_2−y_1
    • B=x_1−x_2
    • C=x_2y_1−x_1 y_2
    交点的计算方法

    通过联立上述直线公式,我们可以得到两条直线的交点。

    交点x = {B_1C_2-B_2C_1} / {A_1 * B_2-B_1 * A_2}

    交点y = {A_2 * C_1-C_2 * A_1} / {A_1 * B_2-B_1 * A_2}

    存储方法

    我们选用Vector存储过程中产生的交点。在所有交点计算完毕后,我们对数组内元素排序,并去重。

    复杂度

    由于在获得直线交点时,需要枚举两条直线的所以可能。所以时间复杂度为O(n^2)

    设计和实现过程

    本设计中包含两个类(直线、圆)和一个结构体(坐标)。结构体作为坐标的数据结构,具有比较等功能。而两个类中都有和其他对象判断交点的方法。主函数通过对每个直线、每个圆建立相应对象,再枚举调用交点计算方法即可找出所有的交点。

    交点

    stuct Position {
    	double x;
    	double y;
    };
    

    由于我们在后续需要对交点进行排序去重处理,所以我构造和posCompare,posEqual两个函数来比较两个交点的大小和是否相等。

    直线:

    在直线类中我们存储直线一般式的三个参数(A,B,C)

    直线可以相交,我们为直线构造相交方法,返回交点结构体。

    Class Line {
    	long long a, b, c;
    	Line(long long x1, long long y1, long long x2, long long y2);
    	struct Position intersect(Line&);
    }
    

    的类中,我们存储能够定位一个圆的三个参数:(x,y,r),即圆心和半径。

    同时圆的类中,包含圆与直线相交、圆与圆相交的方法。

    class Circle 
    {
    public:
    	Circle(long long x, long long y, long long r);
    	long long x, y, r;
    	void lineIntersect(const Line&, vector<struct Position>&);
    	void circleIntersect(const Circle&, vector<struct Position>&);
    };
    
    

    在计算直线和圆的交点时,我们采用了点到直线的距离公式。distance = |Ax0+By0+C| / sqrt(A^2+B^2),如果点到直线的距离大于半径,则不会有交点,如果小于或等于半径,则会有0或1个交点。而圆和圆之间的交点,我们采用了向量公式法来进行计算。

    性能分析

    在本节中我们对代码进行了性能分析。通过随机生成的2000条直线进行测试。从图中可以看出,我们代码的主要耗时部分在于去重时对代码进行的排序操作,占到了所有消耗的80%左右。对于重复结点的删除,我们有两种可以选择的方法,一种是进入时检查,即使用set等维护一个互不重复的结点结合,另一种是输出时检查,此时我们需要额外进行去重处理。二者都需要消耗额外的时间,目前还没有一个很好地降低时间复杂度的方法。


    测试

    单元测试设计

    单元测试主要针对结点的比较函数和交点的计算方法进行。主要的要求是要考虑所有的情况,例如,要考虑结点比较时可能出现的大于、小于、等于等情况,直线交点计算时的相交、平行、垂直等情况,圆和圆之间的相切、相交、相离等其情况。

    消除 Code Quality Analysis 中的所有警告

    关键代码说明

    交点计算方法

    这里直接调用公式即可。注意到笔者在这里整数类型都选取的是long long型,虽然我们的坐标值等变量都不会超过int的范围,但是在整数进行乘法运算时,可能有溢出的风险,所以使用long long能够更保证程序的正确性。

    结构体(位置)比较函数

    我们使用结构体struct Position来存储交点的坐标。由于在最后我们需要对这些坐标进行去重操作,所以我们需要设置坐标的比较函数,判断二者的大小和相等性。

  • 相关阅读:
    探偵ガリレオー転写る 完了
    探偵ガリレオー転写る3
    探偵ガリレオー転写る2
    探偵ガリレオー転写る1
    探偵ガリレオ 燃えるまで
    探偵ガリレオ2
    探偵ガリレオ1
    【转】2014找工作----扎实的基础和开阔的视野是企业最看重的因素
    三种交换两个整数的方法
    计算十进制整数的二进制中的1的数目
  • 原文地址:https://www.cnblogs.com/lebway/p/12457526.html
Copyright © 2011-2022 走看看