content: package edu.stanford.rsl.conrad.reconstruction.voi;
  
  import java.awt.Polygon;
  import java.io.BufferedReader;
  import java.io.FileReader;
  import java.io.IOException;
  import java.util.HashMap;
  
  import edu.stanford.rsl.conrad.io.ConfigFileParser;
  import edu.stanford.rsl.conrad.io.SafeSerializable;
  
  /**
   * VOI based on a polygon definition which is identical for each slice. The VOI is than formed as a stack of identical polygons. Note that this method is sub-optimal for clipping as either the VOI has to be pre-computed for the whole volume or clipped against a polygon in each call of contains(). 
   * @author akmaier
   *
   */
  public class PolygonBasedVolumeOfInterest extends VolumeOfInterest implements ConfigFileParser, SafeSerializable {
  
  	/**
  	 * 
  	 */
  	private static final long serialVersionUID = -8511498569857161802L;
  	Polygon sliceRegionOfInterest;
  	double maxZ, minZ;
  	int numberOfPointsInPolygon;
  	private boolean success = false;
  
  	private HashMap<Double, Boolean> sliceVoi = new HashMap<Double, Boolean>();
  
  	public PolygonBasedVolumeOfInterest(){
  	}
  
  	public PolygonBasedVolumeOfInterest(String maxVOIFileName) throws IOException{
  		readConfigFile(maxVOIFileName);
  	}
  
  	
  	
  	public boolean contains (double x, double y, double z){
  		if (debug) System.out.println("Voxel " + x + " " + y + " " + z);
  		boolean revan = true;
  		if ((z < minZ)||(z > maxZ)){
  			revan = false;
  			if (debug) System.out.println("z out of Range: " + z);
  			if (debug) System.out.println("Z-Range " + minZ + " " + maxZ);
  		} else {
  			Double location = new Double (x *1000 +y);
  			if (! sliceVoi.containsKey(location)) {
  				if (!(sliceRegionOfInterest.contains(x, y))){
  					revan = false;
  					if (debug) System.out.println("Not in polygon");
  				}
  				sliceVoi.put(location, new Boolean(revan));
  			} else {
  				revan = sliceVoi.get(location);
  			}
  		}
  		return revan;
  	}
  
  	public void readConfigFile(String filename) throws IOException {
  		FileReader read = new FileReader(filename);
  		BufferedReader bufferedReader = new BufferedReader(read);
  		String line = "";
  		//skip four lines
  		line = bufferedReader.readLine();
  		if (line.contains("version 2")){
  			line = bufferedReader.readLine();
  			line = bufferedReader.readLine();
  			line = bufferedReader.readLine();
  			if (debug) System.out.println(line);
  			String [] entries = line.split("\\s+");
  			minZ = Double.parseDouble(entries[1]);
  			maxZ = Double.parseDouble(entries[2]);
  			if (debug) System.out.println("Z-Range " + minZ + " " + maxZ);
  			line = bufferedReader.readLine();
  			if (debug) System.out.println(line);
  			entries = line.split("\\s+");
  			numberOfPointsInPolygon = Integer.parseInt(entries[1]);
  			int [] xvals = new int[numberOfPointsInPolygon];
  			int [] yvals = new int[numberOfPointsInPolygon];
  			for (int i=0; i < numberOfPointsInPolygon; i++){
  				line = bufferedReader.readLine();
  				entries = line.split("\\s+");
  				xvals[i] = (int) Math.round(Double.parseDouble(entries[1]));
  				yvals[i] = (int) Math.round(Double.parseDouble(entries[2]));
  				if (debug) System.out.println(line);
  			}
  			sliceRegionOfInterest = new Polygon(xvals, yvals, numberOfPointsInPolygon);
  			success = true;
  		} else {
  			throw new IOException("File is not in version 2 format.");
  		}
  		bufferedReader.close();
  	}
  
  	public boolean getSuccess() {
  		return success;
  	}
  
  	public void prepareForSerialization() {
  		sliceVoi = new HashMap<Double, Boolean>();
  	}
  }
  /*
   * Copyright (C) 2010-2014 Andreas Maier
   * CONRAD is developed as an Open Source project under the GNU General Public License (GPL).
  */