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

org.jaitools.jiffle.runtime.CoordinateTransforms Maven / Gradle / Ivy

/* 
 *  Copyright (c) 2011, Michael Bedward. 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 and the following disclaimer. 
 *   
 *  - Redistributions in binary form must reproduce the above copyright notice, this 
 *    list of conditions and the following disclaimer in the documentation and/or 
 *    other materials provided with the distribution.   
 *   
 *  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 HOLDER 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. 
 */   

package org.jaitools.jiffle.runtime;

import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;

/**
 * Utility class to create {@link CoordinateTransform} objects for simple cases.
 *
 * @author Michael Bedward
 * @since 0.1
 * @version $Id$
 */
public class CoordinateTransforms {
    
    /**
     * Creates an identity transform.
     * 
     * @return a new transform instance
     */
    public static CoordinateTransform identity() {
        return new IdentityCoordinateTransform();
    }
    
    /**
     * Creates a scaling transform.
     * 
     * @param xscale scale on the X axis
     * @param yscale scale on the Y axis
     * 
     * @return a new transform instance
     */
    public static CoordinateTransform scale(double xscale, double yscale) {
        return new AffineCoordinateTransform(AffineTransform.getScaleInstance(xscale, yscale));
    }
    
    /**
     * Creates a translation transform.
     * 
     * @param dx translation in the X direction
     * @param dy translation in the Y direction
     * 
     * @return a new transform instance
     */
    public static CoordinateTransform translation(double dx, double dy) {
        return new AffineCoordinateTransform(AffineTransform.getTranslateInstance(dx, dy));
    }

    /**
     * Creates a transform for working in the unit rectangle, ie. proportional
     * image coordinates where both X and Y ordinates vary from 0 to 1.
     * 
     * @param imageBounds the image bounds
     * 
     * @return a new transform instance
     * 
     * @throws IllegalArgumentException if {@code imageBounds} is {@code null} or empty
     */
    public static CoordinateTransform unitBounds(Rectangle imageBounds) {
        if (imageBounds == null || imageBounds.isEmpty()) {
            throw new IllegalArgumentException("imageBounds must not be null or empty");
        }

        return getTransform(new Rectangle(0, 0, 1, 1), imageBounds);
    }

    /**
     * Gets the transform which converts from {@code worldBounds} to {@code imageBounds}.
     * This method is a shortcut for {@code getTransform(worldBounds, imageBounds, false, false)}.
     * 
     * @param worldBounds the coordinate bounds in world (user-defined) units
     * @param imageBounds the image bounds
     * 
     * @return a new transform instance
     * 
     * @throws IllegalArgumentException if either argument is {@code null} or empty
     */
    public static CoordinateTransform getTransform(Rectangle2D worldBounds, Rectangle imageBounds) {
        return getTransform(worldBounds, imageBounds, false, false);
    }
    
    /**
     * Gets the transform which converts from {@code worldBounds} to {@code imageBounds}.
     * The two {@code boolean} arguments provide the option of treating the world X and/or Y
     * axis direction as reversed in relation to the corresponding image axis direction.
     * 

* Example: for an image representing a geographic area, aligned such that the image * Y-axis was parallel with the world north-south axis, then setting {@code reverseY} * to {@code true} will result in correct transformation of world to image coordinates. * * @param worldBounds the coordinate bounds in world (user-defined) units * @param imageBounds the image bounds * @param reverseX whether to treat the direction of the world X axis as reversed * in relation to the image X axis * @param reverseY whether to treat the direction of the world Y axis as reversed * in relation to the image Y axis * * @return a new transform instance * * @throws IllegalArgumentException if either argument is {@code null} or empty */ public static CoordinateTransform getTransform(Rectangle2D worldBounds, Rectangle imageBounds, boolean reverseX, boolean reverseY) { if (worldBounds == null || worldBounds.isEmpty()) { throw new IllegalArgumentException("worldBounds must not be null or empty"); } if (imageBounds == null || imageBounds.isEmpty()) { throw new IllegalArgumentException("imageBounds must not be null or empty"); } double xscale = (imageBounds.getMaxX() - imageBounds.getMinX()) / (worldBounds.getMaxX() - worldBounds.getMinX()); double xoff; if (reverseX) { xscale = -xscale; xoff = imageBounds.getMinX() - xscale * worldBounds.getMaxX(); } else { xoff = imageBounds.getMinX() - xscale * worldBounds.getMinX(); } double yscale = (imageBounds.getMaxY() - imageBounds.getMinY()) / (worldBounds.getMaxY() - worldBounds.getMinY()); double yoff; if (reverseY) { yscale = -yscale; yoff = imageBounds.getMinY() - yscale * worldBounds.getMaxY(); } else { yoff = imageBounds.getMinY() - yscale * worldBounds.getMinY(); } return new AffineCoordinateTransform(new AffineTransform(xscale, 0, 0, yscale, xoff, yoff)); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy