Point4f planeParameter(int i) throws ScriptException {
		Vector3f vAB = new Vector3f();
		Vector3f vAC = new Vector3f();
		while (true) {
			if (i >= statementLength)
				break;
			switch (statement[i].tok) {
			case Token.leftbrace:
				if (!isCoordinate3(i))
					return getPoint4f(i);
			case Token.expressionBegin:
				Point3f pt1 = atomCenterOrCoordinateParameter(i);
				i = pcLastExpressionInstruction;
				Point3f pt2 = atomCenterOrCoordinateParameter(++i);
				i = pcLastExpressionInstruction;
				Point3f pt3 = atomCenterOrCoordinateParameter(++i);
				i = pcLastExpressionInstruction;
				Vector3f plane = new Vector3f();
				float w = Graphics3D.getPlaneThroughPoints(pt1, pt2, pt3, plane, vAB, vAC);
				Point4f p = new Point4f(plane.x, plane.y, plane.z, w);
				Logger.info("defined plane: " + p);
				return p;
			case Token.identifier:
			case Token.string:
				String str = (String) statement[i].value;
				pcLastExpressionInstruction = i;
				if (str.equalsIgnoreCase("xy"))
					return new Point4f(0, 0, 1, 0);
				if (str.equalsIgnoreCase("xz"))
					return new Point4f(0, 1, 0, 0);
				if (str.equalsIgnoreCase("yz"))
					return new Point4f(1, 0, 0, 0);
				pcLastExpressionInstruction += 2;
				if (str.equalsIgnoreCase("x")) {
					if (++i == statementLength || statement[i++].tok != Token.opEQ)
						evalError("x=?");
					return new Point4f(1, 0, 0, -floatParameter(i));
				}
				if (str.equalsIgnoreCase("y")) {
					if (++i == statementLength || statement[i++].tok != Token.opEQ)
						evalError("y=?");
					return new Point4f(0, 1, 0, -floatParameter(i));
				}
				if (str.equalsIgnoreCase("z")) {
					if (++i == statementLength || statement[i++].tok != Token.opEQ)
						evalError("z=?");
					return new Point4f(0, 0, 1, -floatParameter(i));
				}
			default:
				break;
			}
		}
		evalError(GT._("plane expected -- either three points or atom expressions or {0} or {1}", new Object[] {
				"{a b c d}", "\"xy\" \"xz\" \"yz\"" }));
		// impossible return
		return null;
	}