gt: 		ArrayList< byte [] > linesOfBytes = new ArrayList< byte [] >();
context: /* -*- mode: java; c-basic-offset: 8; indent-tabs-mode: t; tab-width: 8 -*- */
  
  /*
   * NamedPointSet.java
   *
   * Created on 28-Sep-2007, 11:49:37
   */
  
  package neblandmarks;
  
  import ij.IJ;
  import ij.ImagePlus;
  import ij.gui.ImageCanvas;
  import ij.gui.PointRoi;
  import ij.gui.Roi;
  import ij.io.FileInfo;
  import ij.measure.Calibration;
  import java.io.BufferedReader;
  import java.io.File;
  import java.io.FileOutputStream;
  import java.io.FileReader;
  import java.io.StringReader;
  import java.io.IOException;
  import java.io.FileNotFoundException;
  import java.io.UnsupportedEncodingException;
  import java.util.ArrayList;
  import java.util.List;
  import java.util.Iterator;
  import java.util.ListIterator;
  import java.util.StringTokenizer;
  import java.util.regex.Matcher;
  import java.util.regex.Pattern;
  import java.util.HashSet;
  import java.util.Set;
  import math3d.Point3d;
  import vib.transforms.FastMatrixTransform;
  import vib.transforms.OrderedTransformations;
  import javax.xml.parsers.SAXParserFactory;
  import javax.xml.parsers.SAXParser;
  import org.xml.sax.Attributes;
  import org.xml.sax.InputSource;
  import org.xml.sax.helpers.DefaultHandler;
  import org.xml.sax.SAXException;
  import util.BatchOpener;
  import util.opencsv.CSVReader;
  
  public class NamedPointSet {
  
  	private static class Handler extends DefaultHandler {
  		protected NamedPointSet nps;
  		public Handler( NamedPointSet nps ) {
  			super();
  			this.nps = nps;
  		}
  		String version = "";
  		@Override
  		public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
  			if( qName.equals("namedpointset") ) {
  				version = attributes.getValue( "version" );
  				if( version == null ) {
  					throw new SAXException( "No 'version' attribute in <namedpointset>" );
  				}
  			}
  			if( qName.equals("pointworld") ) {
  				String setString = attributes.getValue("set");
  				String nameString = attributes.getValue("name");
  				String xString = attributes.getValue("x");
  				String yString = attributes.getValue("y");
  				String zString = attributes.getValue("z");
  				if( setString == null )
  					throw new SAXException( "No 'set' attribute in <pointworld>" );
  				boolean set;
  				if( setString.equals("true") )
  					set = true;
  				else if( setString.equals("false") )
  					set = false;
  				else
  					throw new SAXException( "The 'set' attribute must be 'true' or 'false'" );
  				if( nameString == null )
  					throw new SAXException( "No 'name' attribute in <pointworld" );
  				String name = nameString;
  				if( set && (xString == null || yString == null || zString == null) )
  					throw new SAXException( "If 'set' is true then all of 'x', 'y' and 'z' must be specified." );
  				if( ! set && (xString != null || yString != null || zString != null ) )
  					throw new SAXException( "If 'set' is false then none of 'x', 'y' or 'z' may be specified." );
  				double x = -1;
  				double y = -1;
  				double z = -1;
  				if( set ) {
  					try {
  						x = Double.parseDouble( xString );
  						y = Double.parseDouble( yString );
  						z = Double.parseDouble( zString );
  						nps.add( new NamedPointWorld( name, x, y, z ) );
  					} catch( NumberFormatException e ) {
  						throw new SAXException( "One of 'x', 'y' and 'z' couldn't be parsed as a number" );
  					}
  				} else {
  					nps.add( new NamedPointWorld( name ) );
  				}
  			}
  		}
  		@Override
  		public void endElement(String uri, String localName, String qName) throws SAXException {
  		}
  	}
  
  	public static class PointsFileException extends Exception {
  		PointsFileException( String message ) {
  			super( message );
  		}
  	}
  
  	ArrayList<NamedPointWorld> pointsWorld;
  
  	public int size() {
  		return pointsWorld.size();
  	}
  
  	public NamedPointSet() {
  		pointsWorld = new ArrayList<NamedPointWorld>();
  	}
  
  	public ListIterator listIterator() {
  		return pointsWorld.listIterator();
  	}
  
  	public NamedPointSet transformPointsWith( OrderedTransformations o ) {
  		NamedPointSet result = new NamedPointSet();
  		Iterator i0;
  		for( i0 = pointsWorld.listIterator(); i0.hasNext(); ) {
  			NamedPointWorld p = (NamedPointWorld)i0.next();
  			NamedPointWorld transformed = p.transformWith(o);
  			result.add( transformed );
  		}
  		return result;
  	}
  
  	public NamedPointWorld getPoint( String name ) {
  		Iterator<NamedPointWorld> i;
  		for (i = listIterator(); i.hasNext();) {
  			NamedPointWorld p = i.next();
  			if( p.name.equals(name) ) {
  				return p;
  			}
  		}
  		return null;
  	}
  
  	synchronized public NamedPointWorld delete(int i) {
  		return (NamedPointWorld)pointsWorld.remove(i);
  	}
  
  	public NamedPointWorld get(int i) {
  		return pointsWorld.get(i);
  	}
  
  	public NamedPointWorld get(String name) {
  		Iterator<NamedPointWorld> i0;
  		for(i0=pointsWorld.listIterator();i0.hasNext();) {
  			NamedPointWorld p=i0.next();
  			if( p.getName().equals(name) )
  				return p;
  		}
  		return null;
  	}
  
  	public String[] getPointNames(){
  		String[] sa= new String[pointsWorld.size()];
  		int i=0;
  		for (Iterator it = listIterator(); it.hasNext();) {
  			NamedPointWorld p = (NamedPointWorld)it.next();
  			sa[i++]=p.name;
  		}
  		return sa;
  	}
  
  	public int getIndexOfPoint( String name ) {
  		int i = 0;
  		for( NamedPointWorld p : pointsWorld ) {
  			if( p.getName().equals( name ) )
  				return i;
  			++i;
  		}
  		return -1;
  	}
  
  	void showAsROI(int i, ImagePlus imp) {
  		NamedPointWorld p = pointsWorld.get(i);
  		assert p.set;
  		double x = p.x;
  		double y = p.y;
  		double z = p.z;
  		Calibration c = imp.getCalibration();
  		if( c != null ) {
  			x /= c.pixelWidth;
  			y /= c.pixelHeight;
  			z /= c.pixelDepth;
  		}
  		int sliceAllChannels = (int)z;
  		System.out.println("sliceAllChannels: "+sliceAllChannels);
  		int channels = imp.getNChannels();
  		int currentChannel = imp.getChannel();
  		int slice = sliceAllChannels * channels + currentChannel;
  		System.out.println("slice: "+slice);
  		imp.setSlice(slice);
  		Roi roi = new PointRoi( (int)x, (int)y );
  		imp.setRoi(roi);
  	}
  
  	public boolean savePointsFile( String savePath ) {
  
  		try {
  			FileOutputStream fos = new FileOutputStream(savePath);
  			byte [] asBytes = xmlDataAsBytes( );
  			fos.write(asBytes);
  			fos.close();
  			return true;
  		} catch( IOException e ) {
  			return false;
  		}
  	}
  
  	public String xmlDataAsString( ) {
  		StringBuffer result = new StringBuffer();
  		result.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
  		result.append("<!DOCTYPE namedpointset [\n");
  		result.append("  <!ELEMENT namedpointset (pointworld*)>\n");
  		result.append("  <!ELEMENT pointworld EMPTY>\n");
  		result.append("  <!ATTLIST namedpointset version CDATA #REQUIRED>\n");
  		result.append("  <!ATTLIST pointworld set (true|false) #REQUIRED>\n");
  		result.append("  <!ATTLIST pointworld name CDATA #REQUIRED>\n");
  		result.append("  <!ATTLIST pointworld x CDATA #IMPLIED>\n");
  		result.append("  <!ATTLIST pointworld y CDATA #IMPLIED>\n");
  		result.append("  <!ATTLIST pointworld z CDATA #IMPLIED>\n");
  		result.append("]>\n\n");
  		result.append("<namedpointset version=\"1.0\">\n");
  		Iterator<NamedPointWorld> i = pointsWorld.iterator();
  		while( i.hasNext() ) {
  			NamedPointWorld p = i.next();
  			result.append("  ");
  			result.append(p.toXMLElement());
  			result.append("\n");
  		}
  		result.append("</namedpointset>\n");
  		return result.toString();
  	}
  
  	public byte [] xmlDataAsBytes( ) {
  		try {
  			return xmlDataAsString().getBytes("UTF-8");
  		} catch( java.io.UnsupportedEncodingException e ) {
  			IJ.error("UTF-8 isn't available (!)");
  			return null;
  		}
  	}
  
  	public boolean saveIGSPointsFile( String savePath ) {
  
  		try {
  			FileOutputStream fos = new FileOutputStream(savePath);
  			StringBuffer sb=new StringBuffer("! TYPEDSTREAM 1.1\n");
  			Iterator<NamedPointWorld> i;
  			for(i=listIterator();i.hasNext();) {
  				NamedPointWorld p = i.next();
  				if(p.set) sb.append(p.toIGS()+"\n");
  			}
  			fos.write(sb.toString().getBytes("UTF-8"));
  			fos.close();
  			return true;
  		} catch( IOException e ) {
  			return false;
  		}
  	}
  
  /*
  	public byte [] dataAsBytes( ) {
  
  		int total_bytes = 0;
  
  