/****************************************************************************
Copyright (c) 2004, Colorado School of Mines and others. All rights reserved.
This program and accompanying materials are made available under the terms of
the Common Public License - v1.0, which accompanies this distribution, and is
available at http://www.eclipse.org/legal/cpl-v10.html
****************************************************************************/
package edu.mines.jtk.mosaic;

import static java.lang.Math.*;
import edu.mines.jtk.util.Check;

/**
 * Converts (projects) world coordinates v to/from normalized coordinates u.
 * @author Dave Hale, Colorado School of Mines
 * @version 2004.12.14
 */
public class Projector {

  /**
   * Constructs a projector with specified u and v values. The
   * parameters u0 and u1 determine the margins of the projector.
   * The world coordinate v0 corresponds to normalized coordinate u0.
   * @param u0 the u coordinate closest to normalized coordinate 0;
   *  0.0 &lt;= u0 &lt; u1 is required.
   * @param u1 the u coordinate closest to normalized coordinate 1;
   *  u0 &lt; u1 &lt;= 1.0 is required.
   * @param v0 the v coordinate that corresponds to u coordinate u0;
   *  v0 != v1 is required.
   * @param v1 the v coordinate that corresponds to u coordinate u1;
   *  v0 != v1 is required.
   */
  public Projector(double u0, double u1, double v0, double v1) {
    Check.argument(0.0<=u0,"0.0 <= u0");
    Check.argument(u0<u1,"u0 < u1");
    Check.argument(u1<=1.0,"u1 <= 1.0");
    Check.argument(v0!=v1,"v0 != v1");
    _u0 = u0;
    _u1 = u1;
    _v0 = v0;
    _v1 = v1;
  }

  /**
   * Converts world coordinate v to normalized coordinate u.
   * @param v world coordinate v.
   * @return normalized coordinate u.
   */
  public double u(double v) {
    return _vshift+_vscale*v;
  }

  /**
   * Converts normalized coordinate u to world coordinate v.
   * @param u normalized coordinate u.
   * @return world coordinate v.
   */
  public double v(double u) {
    return _ushift+_uscale*u;
  }

  ///////////////////////////////////////////////////////////////////////////
  // private

  private double _u0,_u1;
  private double _v0,_v1;
  private double _ushift,_uscale;
  private double _vshift,_vscale;

  private void computeShiftAndScale() {
    _uscale = (_v1-_v0)/(_u1-_u0);
    _ushift = _v0-_uscale*_u0;
    _vscale = (_u1-_u0)/(_v1-_v0);
    _vshift = _u0-_vscale*_v0;
  }
}

@@ -487,22 +487,28 @@
 tic 
-java.lang.Math
+edu.mines.jtk.util.M
 .*;%0A
@@ -533,21 +533,17 @@
 tk.util.
-Check
+*
 ;%0A%0A/**%0A 
@@ -1618,16 +1618,46 @@
 1 = v1;%0A
+    computeShiftsAndScales();%0A
   %7D%0A%0A  /
@@ -2073,16 +2073,971 @@
 u;%0A  %7D%0A%0A
+  /**%0A   * Merges the specified projector into this projector.%0A   * @param p the projector.%0A   */%0A  public void merge(Projector p) %7B%0A%0A    // Parameters for this projector A.%0A    double u0a = _u0;%0A    double u1a = _u1;%0A    double v0a = _v0;%0A    double v1a = _v1;%0A%0A    // Parameters for that projector B.%0A    double u0b = p._u0;%0A    double u1b = p._u1;%0A    double v0b = p._v0;%0A    double v1b = p._v1;%0A%0A    // Merge normalized coordinate bounds. Ensure u0 %3C u1.%0A    _u0 = max(u0a,u0b);%0A    _u1 = min(u1a,u1b);%0A    if (_u0%3E=_u1) %7B%0A      double um = 0.5*(_u0+_u1);%0A      _u0 = um-10.0*DBL_EPSILON;%0A      _u1 = um+10.0*DBL_EPSILON;%0A    %7D%0A%0A    // Merge world coordinate bounds. (Condition v0 %3C v1 is invariant.)%0A    if (v0a%3Cv1a) %7B%0A      _v0 = min(v0a,min(v0b,v1b));%0A      _v1 = max(v1a,max(v0b,v1b));%0A    %7D else %7B%0A      _v0 = max(v0a,max(v0b,v1b));%0A      _v1 = min(v1a,min(v0b,v1b));%0A    %7D%0A%0A    // Recompute shifts and scales.%0A    computeShiftsAndScales();%0A  %7D%0A%0A
   //////
@@ -3268,24 +3268,25 @@
 uteShift
+s
 AndScale
 () %7B%0A   
@@ -3277,16 +3277,17 @@
 AndScale
+s
 () %7B%0A   

add method merge(Projector)