三维凸包模版 求三维凸包的表面积和体积

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <iostream>
#include <queue>
#include <algorithm>
using namespace std;
#define PR 1e-8
#define N 510
struct TPoint{
    double x, y, z;
    TPoint(){}
    TPoint(double _x, double _y, double _z):x(_x), y(_y), z(_z){}
    TPoint operator-(const TPoint p){return TPoint(x-p.x, y-p.y, z-p.z);}
    TPoint operator*(const TPoint p){return TPoint(y*p.z-z*p.y, z*p.x-x*p.z, x*p.y-y*p.x);}
    double operator^(const TPoint p){return x*p.x+y*p.y+z*p.z;}
};
struct fac{
    int a, b, c;
    bool ok;
};
struct T3dhull{
    int n;
    TPoint ply[N];
    int trianglecnt;
    fac tri[N];
    int vis[N][N];
    double dist(TPoint a){return sqrt(a.x*a.x+a.y*a.y+a.z*a.z);}
    double area(TPoint a, TPoint b, TPoint c)
    { return dist((b-a)*(c-a));}
    double volume(TPoint a, TPoint b, TPoint c, TPoint d)
    { return (b-a)*(c-a)^(d-a);}
    double ptoplane(TPoint &p, fac &f)
    {
        TPoint m = ply[f.b] - ply[f.a], n = ply[f.c]-ply[f.a], t = p-ply[f.a];
        return (m*n)^t;
    }
    void deal(int p, int a, int b){
        int f = vis[a][b];
        fac add;
        if(tri[f].ok)
        {
            if((ptoplane(ply[p], tri[f])) > PR)
                dfs(p, f);
            else
            {
                add.a = b, add.b = a, add.c = p, add.ok = 1;
                vis[p][b] = vis[a][p] = vis[b][a] = trianglecnt;
                tri[trianglecnt++] = add;
            }
        }
    }
    void dfs(int p, int cnt) {
        tri[cnt].ok = 0;
        deal(p, tri[cnt].b, tri[cnt].a);
        deal(p, tri[cnt].c, tri[cnt].b);
        deal(p, tri[cnt].a, tri[cnt].c);
    }
    bool same(int s, int e) {
        TPoint a = ply[tri[s].a], b = ply[tri[s].b], c = ply[tri[s].c];
        return fabs(volume(a,b,c,ply[tri[e].a])) < PR
            && fabs(volume(a,b,c,ply[tri[e].b])) < PR
            && fabs(volume(a,b,c,ply[tri[e].c])) < PR;
    }
    void construct()
    {
        int i, j;
        trianglecnt = 0;
        if(n<4) return ;
        bool tmp = true;
        for(i = 1; i < n; i++)
        {
            if((dist(ply[0]-ply[i])) > PR)
            {
                swap(ply[1], ply[i]);
                tmp = false;
                break;
            }
        }
        if(tmp)return ;
        tmp = true;
        for(i = 2; i < n; i++)
        {
            if((dist((ply[0]-ply[1])*(ply[1]-ply[i]))) > PR)
            {
                swap(ply[2], ply[i]);
                tmp = false;
                break;
            }
        }
        if(tmp) return ;
        tmp = true;
        for(i = 3; i < n; i++)
        {
            if(fabs((ply[0]-ply[1])*(ply[1]-ply[2])^(ply[0]-ply[i]))>PR)
            {
                swap(ply[3], ply[i]);
                tmp =false;
                break;
            }
        }
        if(tmp)return ;
        fac add;
        for(i = 0; i < 4; i++)
        {
            add.a = (i+1)%4, add.b = (i+2)%4, add.c = (i+3)%4, add.ok = 1;
            if((ptoplane(ply[i], add))>0)
                swap(add.b, add.c);
            vis[add.a][add.b] = vis[add.b][add.c] = vis[add.c][add.a] = trianglecnt;
            tri[trianglecnt++] = add;
        }
        for(i = 4; i < n; i++)
        {
            for(j = 0; j < trianglecnt; j++)
            {
                if(tri[j].ok && (ptoplane(ply[i], tri[j])) > PR)
                {
                    dfs(i, j); break;
                }
            }
        }
        int cnt = trianglecnt;
        trianglecnt = 0;
        for(i = 0; i < cnt; i++)
        {
            if(tri[i].ok)
                tri[trianglecnt++] = tri[i];
        }
    }
    double area()
    {
        double ret = 0;
        for(int i = 0; i < trianglecnt; i++)
            ret += area(ply[tri[i].a], ply[tri[i].b], ply[tri[i].c]);
        return ret/2.0;
    }
    double volume()
    {
        TPoint p(0,0,0);
        double ret = 0;
        for(int i = 0; i < trianglecnt; i++)
            ret += volume(p, ply[tri[i].a], ply[tri[i].b], ply[tri[i].c]);
        return fabs(ret/6);
    }
}hull;  

int main(){
    int Cas = 1;
    while(scanf("%d",&hull.n), hull.n){
        int i ;
        for(i = 0; i < hull.n; i++)
            scanf("%lf %lf %lf",&hull.ply[i].x, &hull.ply[i].y, &hull.ply[i].z);
        hull.construct();
        printf("Case %d: %.2lf\n", Cas++, hull.area());
    }
    return 0;
}  
时间: 2024-10-21 16:08:40

三维凸包模版 求三维凸包的表面积和体积的相关文章

第四周(基于对象求长方体表面积和体积)

/* *copyright(c) 2015,烟台大学计算机学院 *All rights reserved. *文件名称:第四周(基于对象求长方体表面积和体积) *作者:王忠 *完成日期:2015.4.2 *版本号:v1.0 * *问题描述: 需要你定义长方柱类,代码中已经给出由5个长方柱对象构成的对象数组b: B数组中的前3个对象b[0].b[1].b[2]直接参数初始了,需要定义构造函数,而初始化中,各对象提供的参数数目不同,需要有默认参数的构造函数(未给出的参数默认为1.0) 第4个对象b[

圆柱体的表面积和体积

// // Copyright (c) 2014级软件1班 // All rithts reseved. // 作者:A36 黄阿德 // 完成日期:2014年12月9日 // // 问题描述:创建一个程序来求圆柱体的表面积和体积 // 输出:表面积和体积 // using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; na

0018---求球的表面积和体积

求球的表面积和体积 难度级别:A: 运行时间限制:1000ms: 运行空间限制:51200KB: 代码长度限制:2000000B 试题描述 输入一个不超过300的正数表示球的半径,计算该球的表面积和体积. 输入 只有一个不超过300的正数.  输出 由空格隔开的两个正数分别表示球的表面积和体积.  输入示例 4 输出示例 200.96 267.947  其他说明 圆周率使用3.14,球的表面积和体积计算公式百度一下顺便记住了,今后一定能派上用场,你懂的! 这道题的公式有点刁钻,得自己去查. 球体

0017---正方体的表面积和体积

正方体的表面积和体积 难度级别:A: 运行时间限制:1000ms: 运行空间限制:51200KB: 代码长度限制:2000000B 试题描述 从键盘上输入一个正整数 n 表示正方体的棱长,计算并输出该正方体的表面积和体积 输入 一个正整数n 输出 由一个空格隔开的两个整数,分别表示正方体的表面积和体积  输入示例 2 输出示例 24 8 其他说明 数据范围:0<n<1000 还是套公式--- 把正方体的表面积公式和体积公式带进去就ok了. 代码如下: #include<iostream&

三维计算几何模版

网上找了一个三维计算几何模版,完善了一下,使它能使用了... #include <cstdio> #include <cstring> #include <algorithm> using namespace std; /***********基础*************/ const double EPS=0.000001; typedef struct Point_3D { double x, y, z; Point_3D(double xx = 0, doubl

求凸包(两遍扫描,求上下凸包的方法)

求凸包模版 struct point { double x,y; double val,len; }points[20]; point points1[20]; point points2[20]; const int INF=1e8; bool cmp(point a,point b) { if(a.x==b.x) return a.y<b.y; return a.x<b.x; } double chaji(point a,point b,point c,point d) { return

凸包模版 HDU1392 Surround the Trees

题目链接 题目大意 给出n颗树的坐标,要用一根绳子将所有的树围起来,求绳子的最短长度. 解题思路 求这n个坐标能形成的最大凸包.需要特判n为1时绳子长度为0以及n为2时绳子长度为2树距离.剩下的套凸包模版即可. AC代码 #include <iostream> #include <cmath> #include <cstdio> #include <cstring> #define eps 0.00000001 using namespace std; /*

【POJ 1584】 A Round Peg in a Ground Hole (判凸包+判圆在凸包内)

[POJ 1584] A Round Peg in a Ground Hole (判凸包+判圆在凸包内) 这题题面是一大坑..长长的 明显是给我这种英语渣准备的... 大体意思是给出一个多边形的点 按顺时针或逆时针给出 判断是否为凸包 同时给出一个圆(圆心坐标+半径) 问这个圆在不在多边形内 首先顺逆时针不确定 我的做法是输入时先判断顺时针还是逆时针输入 然后统统变成逆时针来走 就是根据两种情况传入不同的枚举起点 终点 和加减(具体见代码 判凸包用建凸包的叉成法即可 既然逆时针走 那么如果是凸包

POJ 1584 A Round Peg in a Ground Hole(凸包判定&amp;&amp;圆在凸包内判定)

博客原文地址:http://blog.csdn.net/xuechelingxiao/article/details/39178777 A Round Peg in a Ground Hole 题目大意:按顺时针或逆时针给出多边形的顶点坐标.圆的半径及圆心坐标. 1.求多边形是否是个凸包,若不是输出"HOLE IS ILL-FORMED". 2.如果多边形为凸包,判定圆是否在凸包内,若凸包在园内,输出"PEG WILL FIT",若不在,输出"PEG WI