/*
* Copyright (c) 2004-2005, The Hong Kong University of Science and Technology (HKUST)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
*   * Redistributions of source code must retain the above copyright notice,
*     this list of conditions,the authors and the following disclaimer.
*   * Redistributions in binary form must reproduce the above copyright notice,
*     this list of conditions,the authors and the following disclaimer in
*     the documentation and/or other materials provided with the distribution.
*   * Neither the name of the university nor the names of its
*     contributors may be used to endorse or promote products derived from
*     this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
/*
 * SDGEN: a data generator for Bisque
 * @Author: Bingsheng He (saven@cs.ust.hk)
 * @Date:28/3/3005
 * @Version: 1.0
 * @Function: the class representing the topology which contains a number of sensor node.
 * The sensor node contains: id, x, y;
 */
 import java.io.*;
 import java.util.*;
 class Node{
 	public int id;
 	public double x;
 	public double y;


 	Node(int v_id, double v_x, double v_y){
 		id=v_id;x=v_x; y=v_y;
 		}
 	public void print()
 	{
 		System.out.println("Node id="+id+", x="+x+", y="+y);
 	}
 	public boolean isEqual(Node n)
 	{
 		return (this.x==n.x)&&(this.y==n.y);
 	}
 }

 public class Topology{
 	public Vector nodes; //type is Node
 //	public Vector dataSets; //type is a list, contains the tuples:)
 	public Vector tables; //one node for one table, we check their id. nodes[i]<-->tables[i];
 	//for the cover
 	public double lowX;
 	public double lowY;
 	public double highX;
 	public double highY;
 	Topology()
 	{
 		nodes=new Vector();
 		tables=new Vector();
 	}
 	public void AddNode(int v_id, double v_x, double v_y)
 	{
 		//we note that the index in the <nodes> vector may not equal to <v_id>
 		Node n=new Node(v_id,v_x,v_y);
 		nodes.add(n);
 		//update the cover
 		if(v_x<lowX) lowX=v_x;
 		if(v_x>highX) highX=v_x;
 		if(v_y<lowY) lowY=v_y;
 		if(v_y>highY) highY=v_y;
 	}
 	//check whether tt can cover this topology.
 	public boolean isCoverBy(Topology tt)
 	{
 		if(((tt.highX*1.05)>=highX) && ((tt.highY*1.05)>=highY))
 		if(((tt.lowX*0.95)<=lowX) && ((tt.lowY*0.95)<=lowY))
 		return true;

 		return false;
 	}
 	public void print()
 	{
 		for(int i=0;i<nodes.size();i++)
 		{
 			((Node)(nodes.elementAt(i))).print();
 		}
 	}

 	public void AddTable(int index, DTable o)
 	{
 		tables.add(index,o);
 	}
 	public void printTable(int index)
 	{
 		((DTable)(tables.elementAt(index))).print();
 	}
 	public DTable tableAt(int index)
 	{
 		return (DTable) (tables.elementAt(index));
 	}
 	//we use the location to detect it!!!
 	public boolean isIn(Node n)
 	{
 		boolean result=false;
 		for(int i=0;i<nodes.size();i++)
 		{
 			Node nn=(Node)(nodes.elementAt(i));
 			if(n.x==nn.x && n.y==nn.y)
 			{
 				result=true;
 				return result;
 			}
 		}
 		return result;
 	}
 	public int getIndexFromID(int id)
 	{
 		int result=-1;
 		for(int i=0;i<nodes.size();i++)
 		{
 			Node n=(Node)(nodes.elementAt(i));
 			if(n.id==id)
 			{
 				result=i;
 				return result;
 			}
 		}
 		return result;
 	}

 	public int getIndexFromNode(Node n)
 	{
 		int result=-1;
 		for(int i=0;i<nodes.size();i++)
 		{
 			Node nn=(Node)(nodes.elementAt(i));
 			if(Math.abs(nn.x-n.x)<=0.05*n.x && Math.abs(nn.y-n.y)<=0.05*n.x)
 			{
 				result=i;
 				return result;
 			}
 		}
 		return result;
 	}

 	/*
 	 * return the Vector containing the index of nodes with minimum distance.
 	 */
 	public Vector minimumFour(Node n)
 	{
 		if(isIn(n))
 		{
 			System.exit(0);
 		}
 		Vector dist=new Vector();
 		double tmpD=0;
 		//ASC order
 		double []D=new double[4];
 		int []DID=new int[4];
 		for(int i=0;i<4;i++)
 			D[i]=Double.MAX_VALUE;
 		for(int i=0;i<nodes.size();i++)
 		{
 			Node nn=(Node)(nodes.elementAt(i));
 			if(! nn.isEqual(n))
 			{
 				tmpD=(n.x-nn.x)*(n.x-nn.x)+(n.y-nn.y)*(n.y-nn.y);
 				for(int j=0;j<4;j++)
 				{
 					if(D[j]>=tmpD)
 					{
 						for(int m=3;m>j;m--)
 						{
 							D[m]=D[m-1];
 							DID[m]=DID[m-1];
 						}

 						D[j]=tmpD;
 						DID[j]=i;
 						break;

 					}

 				}
 			}
 		}

 		for(int i=0;i<4;i++)
 			dist.add(new Integer(DID[i]));

 		return dist;
 	}

 	/*
 	 *
 	 * mapping one topology to another topology using MBR.
 	 * Note that we may update the all coordinate (x,y) in all target nodes.
 	 * First, compute the scale_x=(Olength/Ilength), scale_y=(Oheight/Iheight).
 	 * Second, the new_x=Ox*scale_x+ILow_x-OLow_x*scale_x; new_y=Oy*scale_y+ILow_y-OLow_y*scale_y;
 	 */

 	 void mapTo(Topology inputTopo)
 	 {
 	 	double scale_x=(inputTopo.highX-inputTopo.lowX)/(highX-lowX);
 	 	double scale_y=(inputTopo.highY-inputTopo.lowY)/(highY-lowY);

 	 	double ILow_x=inputTopo.lowX;
 	 	double ILow_y=inputTopo.lowY;

 	 	double base_x=ILow_x-scale_x*lowX;
 	 	double base_y=ILow_y-scale_y*lowY;

 	 	//update the x and y in the current topology
 	 	lowX=scale_x*lowX+base_x;
 	 	lowY=scale_y*lowY+base_y;
 	 	highX=scale_x*highX+base_x;
 	 	highY=scale_y*highY+base_y;

 	 	//update the coordinate in the nodes.
 	 	for(int i=0;i<nodes.size();i++)
 	 	{
 	 		Node n=(Node)(nodes.elementAt(i));
 	 		n.x=n.x*scale_x+base_x;
 	 		n.y=n.y*scale_y+base_y;
 	 	}

 	 }

 }