Inheritance - SGU 129(线段与多边形相交的长度)

题目大意:给一个凸多边形(点不是按顺序给的),然后计算给出的线段在这个凸多边形里面的长度,如果在边界不计算。

分析:WA2..WA3...WA4..WA11...WA的无话可说,总之细节一定考虑清楚,重合的时候一定是0

代码如下:

=========================================================================================================

#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<iostream>
using namespace std;

const int MAXN = 1007;
const double EPS = 1e-14;
const double FarX = 4e4+7;

int Sign(double x)
{
    if(x > EPS)return 1;
    if(fabs(x) < EPS)return 0;
    return -1;
}
struct point
{
    double x, y;
    point(double x=0, double y=0):x(x),y(y){}
    point operator - (const point &t)const{
        return point(x-t.x, y-t.y);
    }
    bool operator == (const point &t)const{
        return Sign(x-t.x) ==0 && Sign(y-t.y) == 0;
    }
    double operator ^(const point &t)const{
        return x*t.y - y*t.x;
    }
    double operator *(const point &t)const{
        return x*t.x + y*t.y;
    }
};
double Dist(point t1, point t2)
{
    return sqrt((t1-t2)*(t1-t2));
}
struct segment
{
    point S, E;
    double a, b, c;///ax + by = c;

    segment(point S=0, point E=0):S(S), E(E){
        a = S.y - E.y;
        b = E.x - S.x;
        c = E.x*S.y - S.x*E.y;
    }
    int  Inter(const segment &tmp)const{
        int t1 = Sign((S-E)^(tmp.S-E));
        int t2 = Sign((S-E)^(tmp.E-E));

        if(t1 == 0 && t2 == 0)
            return -1;

        if(t1*t2 == -1)
            return 1;
        if(abs(t1+t2) == 1)///如果完全相交或者有一点相交,不考虑重合
            return 2;
        return false;
    }
    point crossNode(const segment &tmp)const
    {///两条线段的交点
        point result;
        result.x = (c*tmp.b-tmp.c*b) / (a*tmp.b-tmp.a*b);
        result.y = (c*tmp.a-tmp.c*a) / (b*tmp.a-tmp.b*a);

        return result;
    }
    bool OnSeg(const point &p)
    {///判断点是否在线段上
        if(Sign((S-E)^(p-E)) == 0)
        if(Sign((p.x-S.x)*(p.x-E.x)) <= 0)
        if(Sign((p.y-S.y)*(p.y-E.y)) <= 0)
            return true;
        return false;
    }
};
struct Polygon
{
    int N;///有N个点
    point vertex[MAXN];

    int Point_In_Poly(const point &p)
    {///点在多边形里面1,还是外面-1,还是边上 0
        segment ray(p, point(FarX, p.y));
        int cnt = 0;

        for(int i=0; i<N; i++)
        {
            segment L(vertex[i], vertex[i+1]);

            if(L.OnSeg(p))
                return 0;

            if(ray.OnSeg(L.S))
            {
                if(L.E.y-L.S.y > EPS)
                    cnt ++;
            }
            else if(ray.OnSeg(L.E))
            {
                if(L.S.y-L.E.y > EPS)
                    cnt ++;
            }
            else if(L.Inter(ray)==1 && ray.Inter(L)==1)
                cnt++;
        }

        if(cnt % 2)
            return 1;
        return -1;
    }
    double Seg_In_Poly(const segment &L1)
    {///线段与多边形相交的长度,先求出线段与多边形有几个交点
        point p[10];
        int k=0;

        for(int i=0; i<N; i++)
        {
            segment L2(vertex[i], vertex[i+1]);

            if(L1.Inter(L2) == -1 && L2.Inter(L1) == -1)
                return 0;

            if(k<2 && L1.Inter(L2) && L2.Inter(L1))
            {
                point t = L1.crossNode(L2);
                if(!k || !(p[0] == t) )
                    p[k++] = t;
            }
        }

        double len=0;

        if(k == 2)
        {///有两个不同的交点
            len = Dist(p[0], p[1]);
        }
        else if(k == 1)
        {///有一个交点,判断哪个端点在多边形内
            if(Point_In_Poly(L1.S) == 1)
                len = Dist(p[0], L1.S);
            else if(Point_In_Poly(L1.E) == 1)
                len = Dist(p[0], L1.E);
        }
        else if(Point_In_Poly(L1.S) == 1)
        {///没有交点的时候,判断线段是否在多边形内
            len = Dist(L1.S, L1.E);
        }

        return len;
    }
};
Polygon poly;

bool cmp(point t1, point t2)
{
    return Sign((t2-poly.vertex[0])^(t1-poly.vertex[0])) < 0;
}

int main()
{
    int i, M, ki=0;

    scanf("%d", &poly.N);

    for(i=0; i<poly.N; i++)
    {
        scanf("%lf%lf", &poly.vertex[i].x, &poly.vertex[i].y);
        if(poly.vertex[ki].y > poly.vertex[i].y ||
           (poly.vertex[ki].y == poly.vertex[i].y && poly.vertex[ki].x > poly.vertex[i].x) )
           ki = i;
    }

    swap(poly.vertex[0], poly.vertex[ki]);
    sort(poly.vertex+1, poly.vertex+poly.N, cmp);
    poly.vertex[poly.N] = poly.vertex[0];

    scanf("%d", &M);

    while(M--)
    {
        point A, B;

        scanf("%lf%lf%lf%lf", &A.x, &A.y, &B.x, &B.y);
        segment L(A, B);
        printf("%.6f\n",poly.Seg_In_Poly(L));
    }

    return 0;
}
/**
6
1 2
2 1
2 3
3 1
3 3
4 2
200
1 1 4 10
**/
时间: 2024-11-10 04:46:02

Inheritance - SGU 129(线段与多边形相交的长度)的相关文章

dtIntersectSegmentPoly2D 2D上的线段与多边形相交计算 产生结果:是否相交,线段跨越的开始和结束百分比,相交的边

dtIntersectSegmentPoly2D(startPos, endPos, verts, nv, tmin, tmax, segMin, segMax): http://geomalgorithms.com/vector_products.html perp product也就是 2D外积 inline float dtVperp2D(const float* u, const float* v) { return u[2]*v[0] - u[0]*v[2]; } 所有的都是映射到xz

线段与多边形关系的算法

目录 介绍 解决思路 问题一:点与线段的关系 问题二:线段与线段的关系 问题三:点与多边形的关系 问题四:线段与多边形的关系 总结 源码 介绍 最近项目中要用到有关几何(Geometry)方面的知识,程序需要判断给定的一条线段(Segment)与指定多边形(Polygon)的位置关系.这种关系分为三种:多边形包含线段.多边形与线段相交以及多边形与线段无关联. 起初我以为.NET类库中已经包含此种判定功能的API,比如类似System.Drawing.Region这些类型,后来等到实际要用的时候才

并行计算大作业之多边形相交(OpenMP、MPI、Java、Windows)

***************************************转载请注明出处:http://blog.csdn.net/lttree******************************************** 吐槽: 话说,相当郁闷,2015年,第一次打开博客,准备总结一下这一年.. 结果博客被封了= =! 今天,终于解封了,换了密码,换了密保.... 但是,写回顾的激情有点退散了.. 明后两天要上课,明天还要验收一个综合设计大作业,再后两天要考试,再后两天继续上课,

hdu3060Area2(任意多边形相交面积)

链接 多边形的面积求解是通过选取一个点(通常为原点或者多边形的第一个点)和其它边组成的三角形的有向面积. 对于两个多边形的相交面积就可以通过把多边形分解为三角形,求出三角形的有向面积递加.三角形为凸多边形,因此可以直接用凸多边形相交求面积的模板. 凸多边形相交后的部分肯定还是凸多边形,所以只需要判断哪些点是相交部分上的点,最后求下面积. 1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #inc

判断线段和直线相交 POJ 3304

1 // 判断线段和直线相交 POJ 3304 2 // 思路: 3 // 如果存在一条直线和所有线段相交,那么平移该直线一定可以经过线段上任意两个点,并且和所有线段相交. 4 5 #include <cstdio> 6 #include <cstring> 7 #include <iostream> 8 #include <algorithm> 9 #include <map> 10 #include <set> 11 #inclu

poj 1410 Intersection (判断线段与矩形相交 判线段相交)

题目链接 Intersection Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 12040   Accepted: 3125 Description You are to write a program that has to decide whether a given line segment intersects a given rectangle. An example: line: start point:

poj 3082多边形相交 &#39;Roid Rage

题意是判断多边形是否相交 主要的思路就是判断每一个点是否在另外的多变形内 判断一个点是否在另一个多边形内主要思路是: 判断的那个点向左边做射线,如果射线与多边形的交点为奇数个则在多边形内,偶数个则不在,其中有特殊情况: 1.如果判断的点与所要判断的边在平行且在所要判断的边上,则在多边形上 2.如果向左做射线恰好在某一点上,不特殊处理会计算两次,因为在两条边上,判断射线与多变形的交点数目,所以要在一个情况下忽略 3.就是判断点是否在多边形的左边了 but:WA了好久因为一个多边形可能包涵另一个多边

HDU 4063 线段与圆相交+最短路

Aircraft Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 980    Accepted Submission(s): 228 Problem Description You are playing a flying game. In the game, player controls an aircraft in a 2D-

平面上两多边形相交

public static void Run_PolygonsIntersection() { int count = 0; Ps1[0] = new Point(0, 0); Ps1[1] = new Point(3, 0); Ps1[2] = new Point(0, 3); Ps1[3] = new Point(0, 0); Ps2[0] = new Point(1, 1);; Ps2[1] = new Point(4, 1); Ps2[2] = new Point(4, 4); Ps2[