Вроде как решение получено и все несколько раз перепроверил и на ручных тестах все работает, но полностью проверку не проходит. Что я упущено в решении?
Код:
#include <cstdio>
#include <cmath>
#include <vector>
using namespace std;
class Point
{
public:
Point(double x = 0, double y = 0, double z = 0): X(x), Y(y), Z(z) {};
Point(const Point& p): X(p.X), Y(p.Y), Z(p.Z) {};
Point operator-(const Point& b){ return Point(X-b.X, Y-b.Y, Z-b.Z);}
Point operator+(const Point& b){ return Point(X+b.X, Y+b.Y, Z+b.Z);}
Point& Normalize()
{
double length = GetLength();
X /= length;
Y /= length;
Z /= length;
return *this;
}
static double ScalarMultyVector(Point a, Point b)
{
return a.X*b.X + a.Y*b.Y + a.Z*b.Z;
};
static Point MultyVector(Point p1, Point p2)
{
return Point(
p1.Y*p2.Z - p1.Z*p2.Y,
-(p1.X*p2.Z - p1.Z*p2.X),
p1.X*p2.Y - p1.Y*p2.X
);
}
Point MultyScalar(double scalar){ return Point(X*scalar, Y*scalar, Z*scalar); }
double GetLength(){ return sqrt(X*X + Y*Y + Z*Z);}
double GetQrtLength(){ return X*X + Y*Y + Z*Z;}
double X;
double Y;
double Z;
};
class Plane
{
public:
Plane(Point p1, Point p2, Point p3)
{
Point v1(p2 - p1);
Point v2(p3 - p1);
Point n( Point::MultyVector(v1, v2) );
A = n.X;
B = n.Y;
C = n.Z;
D = -p1.X*n.X - p1.Y*n.Y - p1.Z*n.Z;
}
double GetDistance(Point a)
{
return abs(A*a.X + B*a.Y + C*a.Z + D)/GetNormal().GetLength();
}
Point GetNormal()
{
return Point(A, B, C);
}
double A;
double B;
double C;
double D;
};
bool IsPointInSphere(Point p)
{
return p.X*p.X + p.Y*p.Y + p.Z*p.Z <= 100*100;
}
void SortPoint(Point p, vector<Point>& in, vector<Point>& out)
{
if( IsPointInSphere(p) )
in.push_back(p);
else
out.push_back(p);
}
double GetTriangleSquare(Point p1, Point p2, Point p3)
{
Point v1(p2 - p1);
Point v2(p3 - p1);
return abs( Point::MultyVector(v1, v2).GetLength() / 2 );
}
Point GetPointOnSphere(Point in, Point out)
{
Point v(out - in);
double a = v.GetQrtLength();
double b = Point::ScalarMultyVector(in, v);
double c = in.GetQrtLength();
double t = (-b + sqrt(b*b - a*c) ) / a;
return in + v.MultyScalar(t);
}
double GetSectorSquare(Point center, Point p1, Point p2)
{
Point v1(p1 - center);
Point v2(p2 - center);
double angle = acos( Point::ScalarMultyVector(v1, v2) / (v1.GetLength() * v2.GetLength() ) );
return v1.GetLength() * angle;
}
double GetSquare(Point p1, Point p2, Point p3)
{
Plane plane(p1, p2, p3);
double distance = plane.GetDistance(Point(0, 0, 0));
if(distance >= 100)
return 0.0;
Point center( plane.GetNormal().Normalize().MultyScalar(distance) );
vector<Point> in, out;
SortPoint(p1, in, out);
SortPoint(p2, in, out);
SortPoint(p3, in, out);
switch(in.size())
{
case 3:
return GetTriangleSquare(p1, p2, p3);
case 2:
{
Point p4( GetPointOnSphere(in[0], out[0]) );
Point p5( GetPointOnSphere(in[1], out[0]) );
return GetTriangleSquare(in[0], in[1], p4) + GetTriangleSquare(p4, p5, in[1]) +
GetSectorSquare(center, p4, p5) - GetTriangleSquare(center, p4, p5);
}
case 1:
{
Point p4( GetPointOnSphere(in[0], out[0]) );
Point p5( GetPointOnSphere(in[0], out[1]) );
return GetTriangleSquare(in[0], p4, p5) +
GetSectorSquare(center, p4, p5) - GetTriangleSquare(center, p4, p5);
}
}
return 0.0;
}
int main(int argc, char *argv[])
{
Point p1, p2, p3;
scanf("%lf%lf%lf", &p1.X, &p1.Y, &p1.Z);
scanf("%lf%lf%lf", &p2.X, &p2.Y, &p2.Z);
scanf("%lf%lf%lf", &p3.X, &p3.Y, &p3.Z);
printf("%lf", GetSquare(p1, p2, p3));
return 0;
}