/*
 * This file is part of Mapyrus, software for plotting maps.
 * Copyright (C) 2003, 2004 Simon Chenery.
 *
 * Mapyrus is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * Mapyrus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Mapyrus; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

/*
 * @(#) $Id$
 */
package org.mapyrus.function;

import org.mapyrus.Argument;
import org.mapyrus.ContextStack;
import org.mapyrus.MapyrusException;

import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.io.ParseException;
import com.vividsolutions.jts.io.WKTReader;

/**
 * Function returning a zero or one value depending on whether
 * one geometry contains another. 
 */
public class Contains extends Function
{
	/**
	 * Calculates whether one geometry contains another.
	 * @param wkt1 OGC WKT string for first geometry.
	 * @param wkt2 OGC WKT string for second geometry.
	 * @return argument with non-zero value if wkt1 contains wkt2, zero value otherwise.
	 * @throws MapyrusException
	 */
	private Argument isContaining(String wkt1, String wkt2) throws MapyrusException
	{
		Argument retval;
		try
		{
			Geometry g1 = new WKTReader().read(wkt1);
			Geometry g2 = new WKTReader().read(wkt2);
			if (g1.contains(g2))
				retval = Argument.numericOne;
			else
				retval = Argument.numericZero;
		}
		catch (ParseException e)
		{
			throw new MapyrusException(e.getMessage());
		}
		catch (IllegalArgumentException e)
		{
			throw new MapyrusException(e.getMessage());
		}
		return(retval);
	}

	/**
	 * @see org.mapyrus.function.Function#evaluate(org.mapyrus.ContextStack,
	 * org.mapyrus.Argument, org.mapyrus.Argument)
	 */
	public Argument evaluate(ContextStack context, Argument arg1, Argument arg2)
		throws MapyrusException
	{
		String wkt1 = arg1.toString();
		String wkt2 = arg2.toString();
		return(isContaining(wkt1, wkt2));
	}

	/**
	 * @see org.mapyrus.function.Function#evaluate(org.mapyrus.ContextStack,
	 * org.mapyrus.Argument, org.mapyrus.Argument)
	 */
	public Argument evaluate(ContextStack context, Argument arg1, Argument arg2, Argument arg3)
		throws MapyrusException
	{
		String wkt1 = arg1.toString();
		String wkt2 = "POINT (" + arg2.getNumericValue() + " " + arg3.getNumericValue() + ")";
		return(isContaining(wkt1, wkt2));
	}

	/**
	 * @see org.mapyrus.function.Function#getMaxArgumentCount()
	 */
	public int getMaxArgumentCount()
	{
		return(3);
	}

	/**
	 * @see org.mapyrus.function.Function#getMinArgumentCount()
	 */
	public int getMinArgumentCount()
	{
		return(2);
	}

	/**
	 * @see org.mapyrus.function.Function#getName()
	 */
	public String getName()
	{
		return("contains");
	}
}

@@ -872,24 +872,59 @@
 .function;%0A%0A
+import java.awt.geom.Rectangle2D;%0A%0A
 import org.m
@@ -2314,32 +2314,553 @@
 rusException%0A%09%7B%0A
+%09%09/*%0A%09%09 * First geometry cannot contain second if it's bounding%0A%09%09 * box does not contain bounding box of second geometry.%0A%09%09 */%0A%09%09Rectangle2D.Double rect1 = arg1.getGeometryBoundingBox();%0A%09%09Rectangle2D.Double rect2 = arg2.getGeometryBoundingBox();%0A%09%09if (rect1 == null %7C%7C rect2 == null)%0A%09%09%09return(Argument.numericZero);%0A%09%09if (rect2.getMinX() %3C= rect1.getMinX() %7C%7C rect2.getMaxX() %3E= rect1.getMaxX() %7C%7C%0A%09%09%09rect2.getMinY() %3C= rect1.getMinY() %7C%7C rect2.getMaxY() %3E= rect1.getMaxY())%0A%09%09%7B%0A%09%09%09return(Argument.numericZero);%0A%09%09%7D%0A%0A
 %09%09String wkt1 = 
@@ -3203,16 +3203,339 @@
 tion%0A%09%7B%0A
+%09%09double x = arg2.getNumericValue();%0A%09%09double y = arg3.getNumericValue();%0A%0A%09%09/*%0A%09%09 * Geometry cannot possibly contain point if it's%0A%09%09 * bounding box does not contain the point.%0A%09%09 */%0A%09%09Rectangle2D.Double rect = arg1.getGeometryBoundingBox();%0A%09%09if (rect == null %7C%7C (!rect.contains(x, y)))%0A%09%09%09return(Argument.numericZero);%0A%0A
 %09%09String
@@ -3591,61 +3591,19 @@
 %22 + 
-arg2.getNumericValue() + %22 %22 + arg3.getNumericValue()
+x + %22 %22 + y
  + %22

Make more efficient by doing quick bounding box check before calling JTS function.