package org.opensha2.eq.fault.surface;
import org.opensha2.eq.model.Distance;
import org.opensha2.geo.Location;
import org.opensha2.geo.LocationList;
import org.opensha2.geo.Locations;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import java.util.List;
/**
* <b>Title:</b> GriddedSubsetSurface<p>
*
* <b>Description:</b> This represents a subset of an GriddedSurface (as a
* pointer, not duplicated in memory)
*
* <b>Note:</b> This class is purely a convinience class that translates indexes
* so the user can deal with a smaller window than the full GriddedSurface.
* Think of this as a "ZOOM" function into a GriddedSurface.<p>
*
* @author Steven W. Rock & revised by Ned Field
*/
class GriddedSubsetSurface extends ContainerSubset2D<Location> implements GriddedSurface {
// for distance measures
// Location siteLocForDistCalcs= null; //new
// Location(Double.NaN,Double.NaN);
// Location siteLocForDistXCalc= null; //new
// Location(Double.NaN,Double.NaN);
// double distanceJB, distanceSeis, distanceRup, distanceX;
GriddedSurface parentSurface;
/**
* Constructor for the GriddedSubsetSurface object
*
* @param numRows Specifies the length of the window.
* @param numCols Specifies the height of the window
* @param startRow Start row into the main GriddedSurface.
* @param startCol Start column into the main GriddedSurface.
* @param data The main GriddedSurface this is a window into
* @exception ArrayIndexOutOfBoundsException Thrown if window indexes exceed
* the main GriddedSurface indexes.
*/
public GriddedSubsetSurface(int numRows, int numCols, int startRow, int startCol,
GriddedSurface data)
throws ArrayIndexOutOfBoundsException {
super(numRows, numCols, startRow, startCol, data);
parentSurface = data;
}
/**
* Add a Location to the grid. This method throws
* UnsupportedOperationException as it is disabled.
*/
public void setLocation(int row, int col, Location location) {
throw new java.lang.UnsupportedOperationException(
"This function is not implemented in this subclass");
}
/**
* Proxy method that returns the number of rows in the main GriddedSurface.
*/
public int getMainNumRows() {
return data.getNumRows();
}
/**
* Proxy method that returns the number of colums in the main GriddedSurface.
*/
public int getMainNumCols() {
return data.getNumCols();
}
@Override
public double strike() {
LocationList locs = getEvenlyDiscritizedUpperEdge();
return Locations.azimuth(locs.first(), locs.last());
}
@Override
public LocationList getEvenlyDiscritizedListOfLocsOnSurface() {
return LocationList.create(this);
// List<Location> locs = Lists.newArrayList();
// Iterator<Location> it = listIterator();
// while(it.hasNext()) locs.add(it.next());
// return LocationList.create(locs);
}
/**
* Proxy method that returns the rupDip of the main GriddedSurface. <P>
*
* This should actually be recomputed if the main surface is a
* SimpleListricGriddedSurface.
*/
@Override
public double dip() {
return ((AbstractGriddedSurface) data).dip();
}
@Override
public double dipRad() {
return ((AbstractGriddedSurface) data).dipRad();
}
/** Debug string to represent a tab. Used by toString(). */
final static char TAB = '\t';
@Override
public double length() {
return getGridSpacingAlongStrike() * (getNumCols() - 1);
}
@Override
public double width() {
return getGridSpacingDownDip() * (getNumRows() - 1);
}
@Override
public LocationList getEvenlyDiscritizedPerimeter() {
throw new UnsupportedOperationException("do be deleted");
// return GriddedSurfaceUtils.getEvenlyDiscritizedPerimeter(this);
}
/**
* returns the grid spacing along strike
*/
@Override
public double getGridSpacingAlongStrike() {
return ((AbstractGriddedSurface) data).getGridSpacingAlongStrike();
}
/**
* returns the grid spacing down dip
*/
@Override
public double getGridSpacingDownDip() {
return ((AbstractGriddedSurface) data).getGridSpacingDownDip();
}
// /**
// * this tells whether along-strike and down-dip grid spacings are the same
// * @return
// */
// public Boolean isGridSpacingSame() {
// return ((AbstractGriddedSurface)data).isGridSpacingSame();
// }
@Override
public double area() {
return width() * length();
}
@Override
public Location getLocation(int row, int column) {
return get(row, column);
}
public LocationList getRow(int row) {
List<Location> locs = Lists.newArrayList();
for (int col = 0; col < getNumCols(); col++) {
locs.add(get(row, col));
}
return LocationList.create(locs);
}
@Override
public double dipDirection() {
return ((AbstractGriddedSurface) data).dipDirection();
}
@Override
public double getAveGridSpacing() {
return parentSurface.getAveGridSpacing();
}
@Override
public LocationList getEvenlyDiscritizedUpperEdge() {
return getRow(0);
}
@Override
public LocationList getEvenlyDiscritizedLowerEdge() {
return getRow(getNumRows() - 1);
}
@Override
public Location getFirstLocOnUpperEdge() {
return get(0, 0);
}
@Override
public Location getLastLocOnUpperEdge() {
// TODO Auto-generated method stub
return get(0, getNumCols() - 1);
}
@Override /**
* This assumes the lateral edges are straight lines
*/
public LocationList getPerimeter() {
LocationList topTr = getRow(0);
LocationList botTr = LocationList.create(getRow(getNumRows() - 1)).reverse();
Iterable<Location> locs = Iterables.concat(topTr, botTr,
Lists.newArrayList(topTr.get(0)));
return LocationList.create(locs);
}
/**
* Returns same as getEvenlyDiscritizedUpperEdge()
*/
@Override
public LocationList getUpperEdge() {
return getEvenlyDiscritizedUpperEdge();
}
@Override
public Distance distanceTo(Location loc) {
return Distance.compute(this, loc);
}
// @Deprecated
// private void setPropagationDistances() {
// throw new UnsupportedOperationException("to be deleted");
// // double[] dists = GriddedSurfaceUtils.getPropagationDistances(this,
// siteLocForDistCalcs);
// // distanceRup = dists[0];
// // distanceJB = dists[1];
// // distanceSeis = dists[2];
// }
//
// /**
// * This returns rupture distance (kms to closest point on the
// * rupture surface), assuming the location has zero depth (for numerical
// * expediency).
// * @return
// */
// public synchronized double getDistanceRup(Location siteLoc){
// if(!siteLocForDistCalcs.equals(siteLoc)) {
// siteLocForDistCalcs = siteLoc;
// setPropagationDistances();
// }
// return distanceRup;
// }
//
// /**
// * This returns distance JB (shortest horz distance in km to surface
// projection
// * of rupture), assuming the location has zero depth (for numerical
// * expediency).
// * @return
// */
// public synchronized double getDistanceJB(Location siteLoc){
// if(!siteLocForDistCalcs.equals(siteLoc)) {
// siteLocForDistCalcs = siteLoc;
// setPropagationDistances();
// }
// return distanceJB;
// }
//
// /**
// * This returns "distance seis" (shortest distance in km to point on
// rupture
// * deeper than 3 km), assuming the location has zero depth (for numerical
// * expediency).
// * @return
// */
// public synchronized double getDistanceSeis(Location siteLoc){
// if(!siteLocForDistCalcs.equals(siteLoc)) {
// siteLocForDistCalcs = siteLoc;
// setPropagationDistances();
// }
// return distanceSeis;
// }
//
// /**
// * This returns distance X (the shortest distance in km to the rupture
// * trace extended to infinity), where values >= 0 are on the hanging wall
// * and values < 0 are on the foot wall. The location is assumed to be at
// zero
// * depth (for numerical expediency).
// * @return
// */
// @Deprecated
// public synchronized double getDistanceX(Location siteLoc){
// throw new UnsupportedOperationException("to be removed");
// // if(!siteLocForDistXCalc.equals(siteLoc)) {
// // siteLocForDistXCalc = siteLoc;
// // distanceX =
// GriddedSurfaceUtils.getDistanceX(getEvenlyDiscritizedUpperEdge(),
// siteLocForDistXCalc);
// // }
// // return distanceX;
// }
//
@Override
public double depth() {
// TODO depth could be computed more efficiently
// for traces with uniform dpeths, will we ever know
// this to be absolutely true?
// if (this.data instanceof GriddedSurfFromSimpleFaultData) {// all
// depths
// // are the
// // same on
// // the top
// // row
// return getLocation(0, 0).depth();
// }
double depth = 0;
LocationList topTrace = getRow(0);
for (Location loc : topTrace) {
depth += loc.depth();
}
return depth / topTrace.size();
}
@Override
public String toString() {
return Surfaces.getSurfaceInfo(this) + super.toString();
}
/**
* This returns the parent surface
*/
public GriddedSurface getParentSurface() {
return parentSurface;
}
@Override
public Location centroid() {
/*
* This would have to be a slow lazy implementation and perhaps the racy
* single-check idiom.
*/
throw new UnsupportedOperationException("SubsetSurface does not support centroid()");
}
}