No.132 点と平面との距離

No.132 点と平面との距離 - yukicoder

  • 三次元平面との距離を求める問題。
  • 外積で法線を求めて、あとは公式を使う。
struct Pt3d {
    double x,y,z;
    Pt3d(double a, double b, double c) : x(a), y(b), z(c) {}
    Pt3d operator+(const Pt3d &other) const { return Pt3d(x+other.x, y+other.y, z+other.z); }
    Pt3d operator-(const Pt3d &other) const { return Pt3d(x-other.x, y-other.y, z-other.z); }
};
Pt3d cross(const Pt3d &a, const Pt3d &b) {
        return Pt3d(a.y*b.z-a.z*b.y, a.z*b.x-a.x*b.z, a.x*b.y-a.y*b.x);
}
double dot(const Pt3d &a, const Pt3d &b) {
        return a.x*b.x+a.y*b.y+a.z*b.z;
}
double norm(const Pt3d &a) { return sqrt(dot(a,a)); }

class DistanceOfPointAndPlane {
public:
    void solve(void) {
            int N;
            cin>>N;

            double x,y,z;
            double dist = 0;

            cin>>x>>y>>z;
            Pt3d p0(x,y,z);
            vector<Pt3d> qs;
            REP(i,N)
            {
                cin>>x>>y>>z;
                qs.emplace_back(x,y,z);
            }

            REP(i,N)
            FOR(j,i+1,N)
            FOR(k,j+1,N)
            {
                auto p = qs[i];
                // 法線をもとめる
                auto n = cross(qs[j]-qs[i], qs[k]-qs[i]);
                // 法線 n を持ち、 p を通る平面は以下のように表現できる
                // plane(x,y,z) = n.x*(x-p.x) + n.y*(y-p.y) + n.z*(z-p.z) = 0
                //
                // この平面と x0,y0,z0 の距離は
                //  |plane(x0,y0,z0)|/norm(n);
                // となる。
                //
                dist += abs(dot(n,p0-p))/norm(n);
            }
            cout<<setprecision(20)<<dist<<endl;
    }
};