All Downloads are FREE. Search and download functionalities are using the official Maven repository.

mds.wave.ContourSignal Maven / Gradle / Ivy

There is a newer version: 7.139.60
Show newest version
package mds.wave;

import java.awt.geom.Point2D;
import java.io.IOException;
import java.util.Vector;

public class ContourSignal
{
	static final int CASE_A = 0;
	static final int CASE_B = 1;
	static final int CASE_C = 2;
	static final int CASE_D = 3;
	private static int xNear_A[] =
	{ 0, 1, 1, 0 };
	private static int yNear_A[] =
	{ 0, 0, 1, 1 };
	private static int rPoint_A[] =
	{ 0, 1, 3 };
	private static int succCase_A[] =
	{ CASE_C, CASE_A, CASE_B };
	private static int xNear_B[] =
	{ 1, 1, 0, 0 };
	private static int yNear_B[] =
	{ 0, 1, 1, 0 };
	private static int rPoint_B[] =
	{ 0, 2, 2 };
	private static int succCase_B[] =
	{ CASE_A, CASE_B, CASE_D };
	private static int xNear_C[] =
	{ 0, 0, 1, 1 };
	private static int yNear_C[] =
	{ 0, -1, -1, 0 };
	private static int rPoint_C[] =
	{ 0, 1, 2 };
	private static int succCase_C[] =
	{ CASE_D, CASE_C, CASE_A };
	private static int xNear_D[] =
	{ 0, -1, -1, 0 };
	private static int yNear_D[] =
	{ 0, 0, -1, -1 };
	private static int rPoint_D[] =
	{ 1, 1, 2 };
	private static int succCase_D[] =
	{ CASE_B, CASE_D, CASE_C };
	double x[];
	float y[];
	float z[][];
	double xmin = -1, xmax = 1;
	double ymin = -1, ymax = 1;
	double zmin = -1, zmax = 1;
	boolean automaticLimits = true;
	private boolean xflag[][];
	private boolean equalZ2;

	ContourSignal(double x[], float y[], float z[][])
	{
		if (x.length != z.length || y.length != z[0].length)
		{
			throw (new IllegalArgumentException("Z colum must be equals to x element end Z row to y elements"));
		}
		this.x = x;
		this.y = y;
		this.z = z;
		computeMinMax();
	}

	ContourSignal(Signal s)
	{
		if (s.getType() == Signal.TYPE_2D)
		{
			this.setMinMaxX(s.getX2Dmin(), s.getX2Dmax());
			this.setMinMaxY(s.getY2Dmin(), s.getY2Dmax());
			this.setMinMaxZ(s.getZ2Dmin(), s.getZ2Dmax());
			this.x = s.getX2D();
			this.y = s.getY2D();
			this.z = s.getZ2D();
		}
	}

	private final boolean checkIntersection(double level, double z1, double z2)
	{
		boolean out;
		out = (z1 < level && level < z2) || (z2 < level && level < z1) || (equalZ2 = (level == z2));
		return out;
	}

	private void computeMinMax()
	{
		xmin = xmax = x[0];
		ymin = ymax = y[0];
		zmin = zmax = z[0][0];
		for (int i = 0; i < x.length; i++)
		{
			if (x[i] < xmin)
			{
				xmin = x[i];
			}
			if (x[i] > xmax)
			{
				xmax = x[i];
			}
			for (int j = 0; j < z[0].length; j++)
			{
				if (z[i][j] < zmin)
				{
					zmin = z[i][j];
				}
				if (z[i][j] > zmax)
				{
					zmax = z[i][j];
				}
			}
		}
		for (final float element : y)
		{
			if (element < ymin)
			{
				ymin = element;
			}
			if (element > ymax)
			{
				ymax = element;
			}
		}
		equalCases();
	}

	public Vector> contour(double level)
	{
		final Vector> contours = new Vector<>();
		Vector contour = new Vector<>();
		double x1, y1, z1;
		double x2, y2, z2;
		double xc, yc, c1;
//System.out.println("Livello " + level);
		int xNear[] = null;
		int yNear[] = null;
		int rPoint[] = null;
		int succCase[] = null;
		Point2D.Double firstCPoint = new Point2D.Double();
		Point2D.Double currCPoint = new Point2D.Double();
		xflag = new boolean[x.length][y.length];
		int edgeCase = CASE_A;
		int ri = 0;
		int rj = 0;
		final int maxIteractions = x.length * y.length;
		for (int i = 0; i < x.length; i++)
		{
			for (int j = 0; j < y.length - 1; j++)
			{
				if (xflag[i][j])
				{
					continue;
				}
				x1 = x[i];
				y1 = y[j];
				z1 = z[i][j];
				x2 = x[i];
				y2 = y[j + 1];
				z2 = z[i][j + 1];
				// xflag[i][j] = true;
				// System.out.println("Manin Case A set "+i+" "+j);
				if (checkIntersection(level, z1, z2))
				{
					c1 = (level - z1) / (z2 - z1);
					xc = x1 + (x2 - x1) * c1;
					yc = y1 + (y2 - y1) * c1;
					contour.addElement((firstCPoint = new Point2D.Double(xc, yc)));
					edgeCase = CASE_A;
					ri = i;
					rj = j;
					if (equalZ2)
					{
						try
						{
							xflag[i][j - 1] = true;
							xflag[i][j] = true;
						}
						catch (final Exception exc)
						{}
					}
				}
				else
				{
					continue;
				}
				boolean contourCompleted = false;
				int l;
				int numIteractions = 0;
				while (!contourCompleted)
				{
					do
					{
						try
						{
							// System.out.println("Riferimento ["+(ri)+","+(rj)+"]");
							switch (edgeCase)
							{
							case CASE_A:
								// System.out.println("CASE_A");
								xNear = xNear_A;
								yNear = yNear_A;
								rPoint = rPoint_A;
								succCase = succCase_A;
								xflag[ri][rj] = true;
								break;
							case CASE_B:
								// System.out.println("CASE_B");
								xNear = xNear_B;
								yNear = yNear_B;
								rPoint = rPoint_B;
								succCase = succCase_B;
								break;
							case CASE_C:
								// System.out.println("CASE_C");
								xNear = xNear_C;
								yNear = yNear_C;
								rPoint = rPoint_C;
								succCase = succCase_C;
								break;
							case CASE_D:
								// System.out.println("CASE_D");
								xNear = xNear_D;
								yNear = yNear_D;
								rPoint = rPoint_D;
								succCase = succCase_D;
								xflag[ri][rj - 1] = true;
								break;
							}
							int rri = 0;
							int rrj = 0;
							for (l = 0; l < 3; l++)
							{
								rri = ri + xNear[l];
								rrj = rj + yNear[l];
								x1 = x[rri];
								y1 = y[rrj];
								z1 = z[rri][rrj];
								final int rrii = ri + xNear[l + 1];
								final int rrjj = rj + yNear[l + 1];
								x2 = x[rrii];
								y2 = y[rrjj];
								z2 = z[rrii][rrjj];
//System.out.print("["+(ri + xNear[l])+","+(rj + yNear[l])+"] "+" ["+(ri + xNear[l+1])+","+(rj + yNear[l+1])+"] " + l);
								if (checkIntersection(level, z1, z2))
								{
									if (equalZ2)
									{
										try
										{
											xflag[rrii][rrjj - 1] = true;
											xflag[rrii][rrjj] = true;
										}
										catch (final Exception exc)
										{}
									}
									c1 = (level - z1) / (z2 - z1);
									xc = x1 + (x2 - x1) * c1;
									yc = y1 + (y2 - y1) * c1;
									contour.addElement((currCPoint = new Point2D.Double(xc, yc)));
									ri += xNear[rPoint[l]];
									rj += yNear[rPoint[l]];
									edgeCase = succCase[l];
									break;
								}
							}
							if (l == 3)
							{
								System.out.println("Errore creazione curva di livello");
								currCPoint = firstCPoint;
							}
						}
						catch (final Exception exc)
						{
							if (!(exc instanceof IOException))
							{
								// System.out.println("Eccezzione");
								// Quando una curva di livello esce dalla griglia
								// si verifica una eccezione che gestisco andando
								// alla ricerca sul bordo dove rientra la curva
								// e riprendendo quindi la ricerca dei punti
								// di contour
								boolean found = false;
								int xi, yj;
								int border;
								for (border = 0; border < 4 && !found; border++)
								{
									switch (edgeCase)
									{
									case CASE_B:
										yj = y.length - 1;
										for (xi = ri; xi > 0; xi--)
										{
											x2 = x[xi];
											y2 = y[yj];
											z2 = z[xi][yj];
											x1 = x[xi - 1];
											y1 = y[yj];
											z1 = z[xi - 1][yj];
											if (checkIntersection(level, z1, z2))
											{
												found = true;
												ri = xi - 1;
												rj = yj;
												edgeCase = CASE_C;
												// System.out.println("CASE B Trovata int succ CASE C");
												break;
											}
										}
										// Non ho trovato nessun punto sul lato
										// superiore devo cercare un punto sul
										// bordo laterale CASE_A devo partire dal primo
										// punto a differenza del caso generico in cui
										// devo partire dal punto successivo al segmento in cui e'
										// stato individuato il punto di uscita della curva di livello
										// in esame, valgono considerazioni analoghe per gli altri casi.
										if (!found)
										{
											// System.out.println("CASE B NON Trovata int succ CASE A");
											edgeCase = CASE_D;
											rj = y.length - 1;
										}
										break;
									case CASE_A:
										xi = x.length - 1;
										for (yj = rj + 1; yj < y.length - 1; yj++)
										{
											x1 = x[xi];
											y1 = y[yj];
											z1 = z[xi][yj];
											x2 = x[xi];
											y2 = y[yj + 1];
											z2 = z[xi][yj + 1];
											xflag[xi][yj] = true;
											if (checkIntersection(level, z1, z2))
											{
												found = true;
												ri = xi;
												rj = yj + 1;
												edgeCase = CASE_D;
												// System.out.println("CASE A Trovata int succ CASE D");
												break;
											}
										}
										if (!found)
										{
											// System.out.println("CASE A NON Trovata int succ CASE C");
											edgeCase = CASE_B;
											ri = x.length - 1;
										}
										break;
									case CASE_C:
										yj = 0;
//                      for (xi = ri - 1; xi >= 0; xi--)
										for (xi = ri + 1; xi < x.length - 1; xi++)
										{
											x1 = x[xi];
											y1 = y[yj];
											z1 = z[xi][yj];
											x2 = x[xi + 1];
											y2 = y[yj];
											z2 = z[xi + 1][yj];
											if (checkIntersection(level, z1, z2))
											{
												found = true;
												ri = xi;
												rj = yj;
												edgeCase = CASE_B;
												// System.out.println("CASE C Trovata int succ CASE B");
												break;
											}
										}
										if (!found)
										{
											// System.out.println("CASE C NON Trovata int succ CASE D");
											edgeCase = CASE_A;
											rj = -1;
										}
										break;
									case CASE_D:
										xi = 0;
										for (yj = rj - 1; yj > 0; yj--)
										{
											x1 = x[xi];
											y1 = y[yj];
											z1 = z[xi][yj];
											x2 = x[xi];
											y2 = y[yj - 1];
											z2 = z[xi][yj - 1];
											xflag[xi][yj] = true;
											if (checkIntersection(level, z1, z2))
											{
												found = true;
												ri = xi;
												rj = yj - 1;
												edgeCase = CASE_A;
												// System.out.println("CASE D Trovata int succ CASE A");
												break;
											}
										}
										if (!found)
										{
											// System.out.println("CASE D NON Trovata int succ CASE B");
											edgeCase = CASE_C;
											ri = -1;
										}
										break;
									}
								}
								/*
								 * Per gestire correttamente le curve di livello che escono dalla griglia come
								 * curve spezzate devo memorizzare ogni singola spezzata separatamente per
								 * evitare che in fase di plot vengano congiunti con un segmento i punti di
								 * uscita dalla griglia della curva di livello in esame.
								 */
								if (contour.size() >= 2)
								{
									contours.addElement(contour);
									contour = new Vector<>();
								}
								else
								{
									contour.clear();
								}
								c1 = (level - z1) / (z2 - z1);
								xc = x1 + (x2 - x1) * c1;
								yc = y1 + (y2 - y1) * c1;
								contour.addElement((currCPoint = new Point2D.Double(xc, yc)));
								if (!found && border == 4)
								{
//                  System.out.println("Completato il bordo");
									numIteractions = maxIteractions;
								}
							}
						}
						// System.out.println("Edge case" + edgeCase );
						numIteractions++;
						if (numIteractions > maxIteractions)
							break;
					}
					/*
					 * La curva di livello si ritiene conclusa quando si ritorna al punto di
					 * partenza
					 */
					while (!(currCPoint.equals(firstCPoint)));
					/*
					 * if (numIteractions > maxIteractions)
					 * System.out.println("Raggiunto numero massimo di iterazioni");
					 */
					if (contour.size() >= 2)
					{
						contours.addElement(contour);
						contour = new Vector<>();
					}
					else
					{
						contour.clear();
					}
					// if(true) return contours;
					contourCompleted = true;
				}
			}
		}
		xflag = null;
		return contours;
	}

	private void equalCases()
	{
		if (xmax == xmin)
		{
			xmin -= xmax / 10.f;
			xmax += xmax / 10.f;
		}
		if (ymax == ymin)
		{
			ymin -= ymax / 10.f;
			ymax += ymax / 10.f;
		}
		if (zmax == zmin)
		{
			zmin -= zmax / 10.f;
			zmax += zmax / 10.f;
		}
	}

	public void setMinMax(float xmin, float xmax, float ymin, float ymax, float zmin, float zmax)
	{
		setMinMaxX(xmin, xmax);
		setMinMaxY(ymin, ymax);
		setMinMaxZ(zmin, zmax);
	}

	public void setMinMaxX(double xmin, double xmax)
	{
		this.xmin = xmin;
		this.xmax = xmax;
	}

	public void setMinMaxY(double ymin, double ymax)
	{
		this.ymin = ymin;
		this.ymax = ymax;
	}

	public void setMinMaxZ(double zmin, double zmax)
	{
		this.zmin = zmin;
		this.zmax = zmax;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy