CSUOJ 1812 三角形和矩形

本篇介绍了一个计算直角三角形与矩形重叠部分面积的问题,通过使用半平面交算法来解决该几何问题。算法首先将输入转换为一系列线段,然后找出这些线段构成的多边形,最后计算该多边形的面积。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接:http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1812

1812: 三角形和矩形

Time Limit: 5 Sec   Memory Limit: 128 MB   Special Judge

Description

Bobo 有一个三角形和一个矩形,他想求他们交的面积。
具体地,三角形和矩形由 8 个整数 x 1,y 1,x 2,y 2,x 3,y 3,x 4,y 4 描述。 表示三角形的顶点坐标是 (x 1,y 1),(x 1,y 2),(x 2,y 1), 矩形的顶点坐标是 (x 3,y 3),(x 3,y 4),(x 4,y 4),(x 4,y 3).

Input

输入包含不超过 30000 组数据。
每组数据的第一行包含 4 个整数 x 1,y 1,x 2,y 2 (x 1≠x 2,y 1≠y 2).
第二行包含 4 个整数 x 3,y 3,x 4,y 4 (x 3<x 4,y 3<y 4).
(0≤x i,y i≤10 4)

Output

对于每组数据,输出一个实数表示交的面积。绝对误差或相对误差小于 10 -6 即认为正确。

Sample Input

1 1 3 3
0 0 2 2
0 3 3 1
0 0 2 2
4462 1420 2060 2969
4159 257 8787 2970

Sample Output

1.00000000
0.75000000
439744.13967527

HINT

Source

题目大意:

求一个直角三角形和一个矩形重合的面积。

解题思路:

半平面交问题,交板子,找到了Non_Cease神犇的板子。

一条直线把一个平面分为两个半平面,注意要取那个半平面,用

addLine(Line& l, double x1, double y1, double x2, double y2)

添加线段,板子是取的向量(x1, y1)-> (x2,  y2)左边的半平面。


#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>

using namespace std;

const double eps = 1e-8;
int n, pn, dq[20005], top, bot;

struct Point{
    double x, y;

    Point(double x, double y) : x(x), y(y) {}
    Point(){}
};

struct Line{
    Point a, b;
    double angle;

    Line& operator = (const Line& l){
        a.x   = l.a.x;
        a.y   = l.a.y;
        b.x   = l.b.x;
        b.y   = l.b.y;
        angle = l.angle;
        return *this;
    }
};

Point p[20005];
Line  l[20005];

int dblcmp(double k){
    if(fabs(k) < eps) return 0;
    return k > 0 ? 1 : -1;
}

double multi(Point p0, Point p1, Point p2){
    return (p1.x - p0.x) * (p2.y - p0.y) - (p1.y - p0.y) * (p2.x - p0.x);
}

bool cmp(const Line& l1, const Line& l2){
    int d = dblcmp(l1.angle - l2.angle);
    if(!d) return dblcmp(multi(l1.a, l2.a, l2.b)) > 0;
    return d < 0;
}

void addLine(Line& l, double x1, double y1, double x2, double y2){
    l.a.x = x1;
    l.a.y = y1;
    l.b.x = x2;
    l.b.y = y2;
    l.angle = atan2(y2 - y1, x2 - x1);
}

Point getIntersect(Line l1, Line l2){
    double A1 = l1.b.y - l1.a.y;
    double B1 = l1.a.x - l1.b.x;
    double C1 = (l1.b.x - l1.a.x) * l1.a.y - (l1.b.y - l1.a.y) * l1.a.x;
    double A2 = l2.b.y - l2.a.y;
    double B2 = l2.a.x - l2.b.x;
    double C2 = (l2.b.x - l2.a.x) * l2.a.y - (l2.b.y - l2.a.y) * l2.a.x;
    Point p((C2 * B1 - C1 * B2) / (A1 * B2 - A2 * B1), (C1 * A2 - C2 * A1) / (A1 * B2 - A2 * B1));
    return p;
}

bool judge(Line l0, Line l1, Line l2){
     Point p;
     p = getIntersect(l1, l2);
     return dblcmp(multi(p, l0.a, l0.b)) < 0;
}

void HalfPlaneIntersect(){
    int i, j;

    sort(l, l + n, cmp);
    for(i = 0, j = 0; i < n; i++)
        if(dblcmp(l[i].angle - l[j].angle) > 0)
            l[++j] = l[i];
    n     = j + 1;
    dq[0] = 0;
    dq[1] = 1;
    top   = 1;
    bot   = 0;
    for(i = 2; i < n; i++){
        while(top > bot && judge(l[i], l[dq[top]], l[dq[top - 1]])){
            top--;
        }
        while(top > bot && judge(l[i], l[dq[bot]], l[dq[bot + 1]])){
            bot++;
        }
        dq[++top] = i;
    }
    while(top > bot && judge(l[dq[bot]], l[dq[top]], l[dq[top - 1]])){
        top--;
    }
    while(top > bot && judge(l[dq[top]], l[dq[bot]], l[dq[bot + 1]])){
        bot++;
    }
    dq[++top] = dq[bot];
    for(pn = 0, i = bot; i < top; i++, pn++){
        p[pn] = getIntersect(l[dq[i + 1]], l[dq[i]]);
    }
}

double getArea(){
    if(pn < 3) return 0;
    double area = 0;
    for(int i = 1; i < pn - 1; i++)
        area += multi(p[0], p[i], p[i + 1]);
    if(area < 0) area = -area;
    return area / 2;
}

int main()
{
    double x1, y1, x2, y2, x3, y3, x4, y4;

    while (scanf ("%lf%lf%lf%lf", &x1, &y1, &x2, &y2) != EOF){
        n = 0;
        if(x2 < x1){
            if(y2 < y1){
                addLine(l[n++], x1, y1, x2, y1);
                addLine(l[n++], x2, y1, x1, y2);
                addLine(l[n++], x1, y2, x1, y1);
            }else{
                addLine(l[n++], x1, y1, x1, y2);
                addLine(l[n++], x1, y2, x2, y1);
                addLine(l[n++], x2, y1, x1, y1);
            }
        }else{
            if(y2 < y1){
                addLine(l[n++], x1, y1, x1, y2);
                addLine(l[n++], x1, y2, x2, y1);
                addLine(l[n++], x2, y1, x1, y1);
            }else{
                addLine(l[n++], x1, y1, x2, y1);
                addLine(l[n++], x2, y1, x1, y2);
                addLine(l[n++], x1, y2, x1, y1);
            }
        }
        scanf("%lf%lf%lf%lf", &x3, &y3, &x4, &y4);
        if(x3 < x4 && y3 < y4){
            if(y3 < y4){
                addLine(l[n++], x3, y3, x4, y3);
                addLine(l[n++], x4, y3, x4, y4);
                addLine(l[n++], x4, y4, x3, y4);
                addLine(l[n++], x3, y4, x3, y3);
            }else{
                addLine(l[n++], x3, y3, x3, y4);
                addLine(l[n++], x3, y4, x4, y4);
                addLine(l[n++], x4, y4, x4, y3);
                addLine(l[n++], x4, y3, x3, y3);
            }
        }else{
            if(y3 < y4){
                addLine(l[n++], x3, y3, x3, y4);
                addLine(l[n++], x3, y4, x4, y4);
                addLine(l[n++], x4, y4, x4, y3);
                addLine(l[n++], x4, y3, x3, y3);
            }else{
                addLine(l[n++], x3, y3, x4, y3);
                addLine(l[n++], x4, y3, x4, y4);
                addLine(l[n++], x4, y4, x3, y4);
                addLine(l[n++], x3, y4, x3, y3);
            }
        }
        HalfPlaneIntersect();
        printf ("%f\n", getArea());
    }
    return 0;
}


<think>我们参考了用户提供的引用内容,特别是引用[1]引用[3]中提到的创建区域的方法,以及引用[5]中关于绘制多边形的信息。在Halcon中,绘制三角形矩形通常通过创建对应的区域(region)来实现,然后可以将这些区域显示在图像上。 绘制矩形: Halcon提供了`gen_rectangle2`算子来创建任意方向的矩形(通过中心、角度半边长定义),以及`gen_rectangle1`来创建轴对齐的矩形(通过左上角右下角定义)。 绘制三角形三角形可以通过指定三个顶点来创建。Halcon没有直接生成三角形的算子,但我们可以通过以下步骤实现: 1. 使用`gen_contour_polygon_xld`创建一个XLD(扩展线描述)轮廓,该轮廓由三个点构成一个闭合三角形。 2. 将XLD轮廓转换为区域(region),使用`gen_region_contour_xld`或`gen_region_polygon`。 另外,根据引用[3],Halcon也提供了交互式绘制形状的算子(以`draw_`开头),但这里我们关注的是非交互式编程绘制。 下面分别给出绘制矩形三角形的代码示例(使用HDevelop语法,但也可在C#、C++等中使用相应的Halcon函数):</think>在Halcon中绘制三角形矩形主要通过创建**区域(Region)** 或 **XLD轮廓(轮廓多边形)** 实现。以下是具体方法: --- ### 一、绘制矩形 #### 方法1:轴对齐矩形(水平/垂直) 使用 `gen_rectangle1` 算子,通过左上角坐标 $(Row1, Column1)$ 右下角坐标 $(Row2, Column2)$ 生成矩形区域: ```cpp gen_rectangle1(Rectangle, Row1, Column1, Row2, Column2) ``` #### 方法2:旋转矩形 使用 `gen_rectangle2` 算子,通过中心坐标 $(Row, Column)$、旋转角度 $\phi$(弧度制)半边长 $(Length1, Length2)$ 生成: ```cpp gen_rectangle2(RotatedRect, Row, Column, Phi, Length1, Length2) ``` --- ### 二、绘制三角形 Halcon没有直接生成三角形的算子,需通过以下两种方式实现: #### 方法1:多边形轮廓(XLD) 用 `gen_contour_polygon_xld` 指定三个顶点坐标生成闭合三角形轮廓: ```cpp // 定义三个顶点坐标 (行,列) Rows := [100, 150, 200] // 三角形顶点的行坐标 Cols := [200, 300, 250] // 三角形顶点的列坐标 gen_contour_polygon_xld(TriangleContour, Rows, Cols) ``` #### 方法2:区域填充法 将三角形轮廓转换为填充区域: ```cpp gen_region_polygon_filled(TriangleRegion, Rows, Cols) ``` --- ### 三、在图像上显示图形 生成区域或轮廓后,使用以下算子叠加到图像: ```cpp // 显示原始图像 read_image(Image, 'your_image.png') // 显示矩形区域(红色) dev_display(Rectangle) // 显示三角形轮廓(蓝色,线宽2) dev_set_color('blue') dev_set_line_width(2) dev_display(TriangleContour) ``` --- ### 四、交互式绘制(进阶) 通过 `draw_polygon` 或 `draw_rectangle2` 实现鼠标交互绘制: ```cpp // 交互绘制三角形 draw_polygon(WindowHandle, Rows, Cols) // 交互绘制旋转矩形 draw_rectangle2(WindowHandle, Row, Column, Phi, Length1, Length2) ``` > **注意**: > - 旋转角度 $\phi$ 以弧度为单位,水平方向为0,逆时针为正方向[^4]。 > - 若需仿射变换(旋转/平移),使用 `hom_mat2d_rotate` 等算子处理区域[^4]。 > - 图像质量直接影响绘制精度,建议预处理增强对比度[^2]。 --- ### 示例代码 ```cpp read_image(Image, 'part.png') gen_rectangle2(Rect, 300, 400, 0.5, 100, 50) // 旋转矩形 Rows := [100, 200, 150] Cols := [300, 320, 400] gen_region_polygon_filled(Triangle, Rows, Cols) // 填充三角形 dev_display(Image) dev_set_color('red') dev_display(Rect) dev_set_color('green') dev_display(Triangle) ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值