/** * Walks a point down the fault along a curve tangent to fault dip. * The input point is assumed to lie in the plane of this cell, * and the output point will lie in the plane of the returned cell. * That returned cell will be one immediately below this cell, if * sufficient cell nabors exist, or this cell, otherwise. * @param p input and output array {p1,p2,p3} of point coordinates. * @return the cell with a plane that contains the output point. */ FaultCell walkDownDipFrom(float[] p) { FaultCell cell = this; float p1 = p[0]; float p2 = p[1]; float p3 = p[2]; Debug.Assert(Math.Abs(cell.distanceFromPlaneTo(p1, p2, p3)) < 0.01f); // Use dip vector of specified cell to walk the point down its plane. p1 += 1.0f; p2 += cell.us * cell.u2; p3 += cell.us * cell.u3; // If a cell below is found, project point horizontally onto its plane. FaultCell cb = cell.getCellBelowNearestTo(p1, p2, p3); if (cb != null) { cell = cb; float us = cell.us; float ws = us * us * cell.distanceFromPlaneTo(p1, p2, p3); p2 -= ws * cell.w2; p3 -= ws * cell.w3; } // Return updated point and cell. Debug.Assert(Math.Abs(cell.distanceFromPlaneTo(p1, p2, p3)) < 0.01f); p[0] = p1; p[1] = p2; p[2] = p3; return(cell); }
/** * Gets the cell below this cell that is nearest to the specified point. * @param p1 1st coordinate of point. * @param p2 2nd coordinate of point. * @param p3 3rd coordinate of point. * @return the cell below; null, if none. */ FaultCell getCellBelowNearestTo(float p1, float p2, float p3) { FaultCell clb = (cl != null) ? cl.cb : null; FaultCell crb = (cr != null) ? cr.cb : null; return(nearestCell(cb, clb, crb, p1, p2, p3)); }
/** * Gets the cell above this cell that is nearest to the specified point. * @param p1 1st coordinate of point. * @param p2 2nd coordinate of point. * @param p3 3rd coordinate of point. * @return the cell above; null, if none. */ FaultCell getCellAboveNearestTo(float p1, float p2, float p3) { FaultCell cla = (cl != null) ? cl.ca : null; FaultCell cra = (cr != null) ? cr.ca : null; return(nearestCell(ca, cla, cra, p1, p2, p3)); }
/** * Sets the specified fault cell. Uses the cell's {x1,x2,x3} coordinates to * determine the indices of the cell in this grid. * @param cell the fault cell. */ public void set(FaultCell cell) { int i1 = cell.i1 - _j1; int i2 = cell.i2 - _j2; int i3 = cell.i3 - _j3; _cells[i3][i2][i1] = cell; }
/** * Constructs a fault grid for specified cells. Grid index bounds are * determined by the minimum and maximum indices of the specified cells. * @param cells array of cells to be included in the grid. */ public FaultCellGrid(FaultCell[] cells) { int i1min = int.MaxValue; int i2min = int.MaxValue; int i3min = int.MaxValue; int i1max = -i1min; int i2max = -i2min; int i3max = -i3min; foreach (FaultCell cell in cells) { if (cell.i1 < i1min) { i1min = cell.i1; } if (cell.i2 < i2min) { i2min = cell.i2; } if (cell.i3 < i3min) { i3min = cell.i3; } if (cell.i1 > i1max) { i1max = cell.i1; } if (cell.i2 > i2max) { i2max = cell.i2; } if (cell.i3 > i3max) { i3max = cell.i3; } } _j1 = i1min; _j2 = i2min; _j3 = i3min; _n1 = 1 + i1max - i1min; _n2 = 1 + i2max - i2min; _n3 = 1 + i3max - i3min; _cells = new FaultCell[_n3][][]; for (int xxx = 0; xxx < _n3; xxx++) { _cells[xxx] = new FaultCell[_n2][]; for (int yyy = 0; yyy < _n2; yyy++) { _cells[xxx][yyy] = new FaultCell[_n1]; } } foreach (FaultCell cell in cells) { set(cell); } }
/** * Finds a fault cell right of the specified cell. Searches for a cell right * that lies nearest to the line containing the specified cell and its * strike vector. If the specified cell is already linked to a nabor cell * right, this method skips the search and simply returns that nabor cell. * @param cell the cell for which to find a cell right. * @return the cell right; null, if none. */ public FaultCell findCellRight(FaultCell cell) { if (cell == null) { return(null); } if (cell.cr != null) { return(cell.cr); } return(findCellLeftRight(false, cell)); }
/** * Finds a fault cell left of the specified cell. Searches for a cell left * that lies nearest to the line containing the specified cell and its * strike vector. If the specified cell is already linked to a nabor cell * left, this method skips the search and simply returns that nabor cell. * @param cell the cell for which to find a cell left. * @return the cell left; null, if none. */ public FaultCell findCellLeft(FaultCell cell) { if (cell == null) { return(null); } if (cell.cl != null) { return(cell.cl); } return(findCellLeftRight(true, cell)); }
/** * Finds a fault cell below the specified cell. Searches for a cell below * that lies nearest to the line containing the specified cell and its dip * vector. If the specified cell is already linked to a nabor cell below, * this method skips the search and simply returns that nabor cell. * @param cell the cell for which to find a cell below. * @return the cell below; null, if none. */ public FaultCell findCellBelow(FaultCell cell) { if (cell == null) { return(null); } if (cell.cb != null) { return(cell.cb); } return(findCellAboveBelow(false, cell)); }
/** * Finds a fault cell above the specified cell. Searches for a cell above * that lies nearest to the line containing the specified cell and its dip * vector. If the specified cell is already linked to a nabor cell above, * this method skips the search and simply returns that nabor cell. * @param cell the cell for which to find a cell above. * @return the cell above; null, if none. */ public FaultCell findCellAbove(FaultCell cell) { if (cell == null) { return(null); } if (cell.ca != null) { return(cell.ca); } return(findCellAboveBelow(true, cell)); }
private FaultCell findCellLeftRight(bool left, FaultCell cell) { int i1 = cell.i1; int i2 = cell.i2; int i3 = cell.i3; float x1 = cell.x1; float x2 = cell.x2; float x3 = cell.x3; float v1 = cell.v1; float v2 = cell.v2; float v3 = cell.v3; if (left) { v1 = -v1; v2 = -v2; v3 = -v3; } FaultCell cmin = null; float dmin = float.MaxValue; for (int ik = 0; ik < 8; ++ik) { if (ik == 4 && cmin != null) { break; } int k2 = K2LR[ik]; int k3 = K3LR[ik]; FaultCell c = get(i1, i2 + k2, i3 + k3); if (c != null) { float d1 = c.x1 - x1; float d2 = c.x2 - x2; float d3 = c.x3 - x3; float dv = d1 * v1 + d2 * v2 + d3 * v3; if (dv > 0.0f) { d1 -= dv * v1; d2 -= dv * v2; d3 -= dv * v3; float d = d1 * d1 + d2 * d2 + d3 * d3; // squared distance to strike line if (d < dmin) { cmin = c; dmin = d; } } } } return(cmin); }
private FaultCell findCellAboveBelow(bool above, FaultCell cell) { int i1 = cell.i1; int i2 = cell.i2; int i3 = cell.i3; float x1 = cell.x1; float x2 = cell.x2; float x3 = cell.x3; float u1 = cell.u1; float u2 = cell.u2; float u3 = cell.u3; int k1 = 1; if (above) { k1 = -k1; u1 = -u1; u2 = -u2; u3 = -u3; } FaultCell cmin = null; float dmin = float.MaxValue; for (int k3 = -1; k3 <= 1; ++k3) { for (int k2 = -1; k2 <= 1; ++k2) { FaultCell c = get(i1 + k1, i2 + k2, i3 + k3); if (c != null) { float d1 = c.x1 - x1; float d2 = c.x2 - x2; float d3 = c.x3 - x3; float du = d1 * u1 + d2 * u2 + d3 * u3; if (du > 0.0f) { d1 -= du * u1; d2 -= du * u2; d3 -= du * u3; float d = d1 * d1 + d2 * d2 + d3 * d3; // squared distance to dip line if (d < dmin) { cmin = c; dmin = d; } } } } } return(cmin); }
/** * Returns an array of packed (x,y,z) coordinates for a fault curve. * The fault curve is everywhere tangent to fault dip, and contains the * point for this cell. Returned coordinates are in above-to-below order. * @return array of packed (x,y,z) coordinates. */ public float[] getFaultCurveXyz() { FloatList xyz = new FloatList(); float[] p = new float[3]; // Gather xyz for this cell and above this cell by walking up dip. FaultCell cell = this; p[0] = x1; p[1] = x2; p[2] = x3; for (int j1 = cell.i1; j1 == cell.i1; --j1) { xyz.add(p[2]); xyz.add(p[1]); xyz.add(p[0]); cell = cell.walkUpDipFrom(p); } // Remember the number of xyz gathered, including xyz for this cell. int na = xyz.n / 3; // Gather xyz for cells below this one by walking down dip. We have // already gathered the xyz for this cell, so now we skip to the one // below it. cell = this; p[0] = x1; p[1] = x2; p[2] = x3; cell = cell.walkDownDipFrom(p); // skip this cell for (int j1 = this.i1 + 1; j1 == cell.i1; ++j1) { xyz.add(p[2]); xyz.add(p[1]); xyz.add(p[0]); cell = cell.walkDownDipFrom(p); } // Flip the order of all xyz gathered above this cell while walking up. float[] xyzs = xyz.trim(); for (int ia = 1, i = ia * 3, ja = na - 1, j = ja * 3; ia < ja; ++ia, i += 3, --ja, j -= 3) { float xi = xyzs[i]; float yi = xyzs[i + 1]; float zi = xyzs[i + 2]; xyzs[i] = xyzs[j]; xyzs[i + 1] = xyzs[j + 1]; xyzs[i + 2] = xyzs[j + 2]; xyzs[j] = xi; xyzs[j + 1] = yi; xyzs[j + 2] = zi; } return(xyzs); }
private static FaultCell nearestCell( FaultCell c1, FaultCell c2, FaultCell c3, float p1, float p2, float p3) { float ds1 = distanceSquared(c1, p1, p2, p3); float ds2 = distanceSquared(c2, p1, p2, p3); float ds3 = distanceSquared(c3, p1, p2, p3); float dsm = Math.Min(Math.Min(ds1, ds2), ds3); if (dsm == ds1) { return(c1); } else if (dsm == ds2) { return(c2); } else { return(c3); } }
private static float distanceSquared( FaultCell c, float p1, float p2, float p3) { return(c != null?c.distanceSquaredTo(p1, p2, p3) : float.MaxValue); }