
public class Transform3DFactory {
    
    public static Transform3D shadow(final XPoint3D candle) {
        
        return new Transform3D() {
            
            XPoint3D c = (candle != null) ? candle : new XPoint3D();
            
            double x0 = c.x;
            double y0 = c.y;
            double z0 = c.z;
            
            public XPoint3D transform(XPoint3D p) {
                if (p != null) {
                    double x = p.x;
                    double y = p.y;
                    double z = p.z;
                    
                    double t = z0 / (z0 - z);
                    double u = 1 - t;
                    
                    double a = t * x + u * x0;
                    double b = t * y + u * y0;
                    
                    return new XPoint3D(a, b, 0);
                }
                
                return null;
            }
        };
    }
    
    
    public static Transform3D planeScale
        (final double scale, final double x0, final double y0)
    {
        return new Transform3D() {
            public XPoint3D transform(XPoint3D p) {
                if (p == null)
                    return null;
                
                double x = p.x;
                double y = p.y;
                
                double u =   scale * x + x0;
                double v = - scale * y + y0;
                
                return new XPoint3D(u, v, 0);
            }
        };
    }
}

