1227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks/* 2227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Copyright (C) 2011 The Android Open Source Project 3227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 4227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Licensed under the Apache License, Version 2.0 (the "License"); 5227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * you may not use this file except in compliance with the License. 6227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * You may obtain a copy of the License at 7227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 8227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * http://www.apache.org/licenses/LICENSE-2.0 9227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 10227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Unless required by applicable law or agreed to in writing, software 11227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * distributed under the License is distributed on an "AS IS" BASIS, 12227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * See the License for the specific language governing permissions and 14227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * limitations under the License. 15227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 16227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 17227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendrickspackage androidx.media.filterfw.geometry; 18227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 19227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.annotation.SuppressLint; 20227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.graphics.Matrix; 21227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.graphics.PointF; 22227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricksimport android.graphics.RectF; 23227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 24227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks/** 25227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * The Quad class specifies a (possibly affine transformed) rectangle. 26227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 27227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * A Quad instance holds 4 points that define its shape. The points may represent any rectangle that 28227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * has been transformed by an affine transformation. This means that Quads can represent translated, 29227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * scaled, rotated and sheared/skewed rectangles. As such, Quads are restricted to the set of 30227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * parallelograms. 31227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 32227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Each point in the Quad represents a specific corner of the Quad. These are top-left, top-right, 33227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * bottom-left, and bottom-right. These labels allow mapping a transformed Quad back to an up-right 34227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Quad, with the point-to-point mapping well-defined. They do not necessarily indicate that e.g. 35227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * the top-left corner is actually at the top-left of coordinate space. 36227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 37227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks@SuppressLint("FloatMath") 38227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendrickspublic class Quad { 39227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 40227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private final PointF mTopLeft; 41227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private final PointF mTopRight; 42227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private final PointF mBottomLeft; 43227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private final PointF mBottomRight; 44227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 45227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 46227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Returns the unit Quad. 47227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * The unit Quad has its top-left point at (0, 0) and bottom-right point at (1, 1). 48227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return the unit Quad. 49227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 50227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static Quad unitQuad() { 51227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return new Quad(0f, 0f, 1f, 0f, 0f, 1f, 1f, 1f); 52227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 53227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 54227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 55227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Return a Quad from the specified rectangle. 56227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 57227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param rect a RectF instance. 58227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return Quad that represents the passed rectangle. 59227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 60227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static Quad fromRect(RectF rect) { 61227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return new Quad(new PointF(rect.left, rect.top), 62227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks new PointF(rect.right, rect.top), 63227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks new PointF(rect.left, rect.bottom), 64227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks new PointF(rect.right, rect.bottom)); 65227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 66227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 67227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 68227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Return a Quad from the specified rectangle coordinates. 69227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 70227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param x the top left x coordinate 71227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param y the top left y coordinate 72227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param width the width of the rectangle 73227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param height the height of the rectangle 74227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return Quad that represents the passed rectangle. 75227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 76227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static Quad fromRect(float x, float y, float width, float height) { 77227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return new Quad(new PointF(x, y), 78227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks new PointF(x + width, y), 79227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks new PointF(x, y + height), 80227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks new PointF(x + width, y + height)); 81227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 82227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 83227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 84227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Return a Quad that spans the specified points and height. 85227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 86227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * The returned Quad has the specified top-left and top-right points, and the specified height 87227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * while maintaining 90 degree angles on all 4 corners. 88227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 89227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param topLeft the top-left of the quad 90227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param topRight the top-right of the quad 91227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param height the height of the quad 92227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return Quad that spans the specified points and height. 93227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 94227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static Quad fromLineAndHeight(PointF topLeft, PointF topRight, float height) { 95227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks PointF dp = new PointF(topRight.x - topLeft.x, topRight.y - topLeft.y); 96227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks float len = dp.length(); 97227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks PointF np = new PointF(height * (dp.y / len), height * (dp.x / len)); 98227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks PointF p2 = new PointF(topLeft.x - np.x, topLeft.y + np.y); 99227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks PointF p3 = new PointF(topRight.x - np.x, topRight.y + np.y); 100227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return new Quad(topLeft, topRight, p2, p3); 101227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 102227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 103227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 104227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Return a Quad that represents the specified rotated rectangle. 105227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 106227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * The Quad is rotated counter-clockwise around its centroid. 107227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 108227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param rect the source rectangle 109227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param angle the angle to rotate the source rectangle in radians 110227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return the Quad representing the source rectangle rotated by the given angle. 111227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 112227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static Quad fromRotatedRect(RectF rect, float angle) { 113227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return Quad.fromRect(rect).rotated(angle); 114227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 115227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 116227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 117227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Return a Quad that represents the specified transformed rectangle. 118227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 119227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * The transform is applied by multiplying each point (x, y, 1) by the matrix. 120227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 121227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param rect the source rectangle 122227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param matrix the transformation matrix 123227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return the Quad representing the source rectangle transformed by the matrix 124227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 125227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static Quad fromTransformedRect(RectF rect, Matrix matrix) { 126227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return Quad.fromRect(rect).transformed(matrix); 127227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 128227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 129227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 130227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Returns the transformation matrix to transform the source Quad to the target Quad. 131227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 132227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param source the source quad 133227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param target the target quad 134227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return the transformation matrix to map source to target. 135227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 136227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public static Matrix getTransform(Quad source, Quad target) { 137227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // We only use the first 3 points as they sufficiently specify the transform 138227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks Matrix transform = new Matrix(); 139227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks transform.setPolyToPoly(source.asCoords(), 0, target.asCoords(), 0, 3); 140227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return transform; 141227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 142227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 143227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 144227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * The top-left point of the Quad. 145227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return top-left point of the Quad. 146227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 147227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public PointF topLeft() { 148227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mTopLeft; 149227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 150227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 151227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 152227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * The top-right point of the Quad. 153227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return top-right point of the Quad. 154227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 155227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public PointF topRight() { 156227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mTopRight; 157227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 158227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 159227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 160227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * The bottom-left point of the Quad. 161227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return bottom-left point of the Quad. 162227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 163227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public PointF bottomLeft() { 164227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mBottomLeft; 165227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 166227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 167227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 168227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * The bottom-right point of the Quad. 169227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return bottom-right point of the Quad. 170227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 171227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public PointF bottomRight() { 172227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return mBottomRight; 173227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 174227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 175227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 176227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Rotate the quad by the given angle. 177227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 178227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * The Quad is rotated counter-clockwise around its centroid. 179227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 180227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param angle the angle to rotate in radians 181227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return the rotated Quad 182227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 183227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public Quad rotated(float angle) { 184227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks PointF center = center(); 185227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks float cosa = (float) Math.cos(angle); 186227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks float sina = (float) Math.sin(angle); 187227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 188227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks PointF topLeft = rotatePoint(topLeft(), center, cosa, sina); 189227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks PointF topRight = rotatePoint(topRight(), center, cosa, sina); 190227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks PointF bottomLeft = rotatePoint(bottomLeft(), center, cosa, sina); 191227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks PointF bottomRight = rotatePoint(bottomRight(), center, cosa, sina); 192227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 193227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return new Quad(topLeft, topRight, bottomLeft, bottomRight); 194227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 195227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 196227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 197227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Transform the quad with the given transformation matrix. 198227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 199227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * The transform is applied by multiplying each point (x, y, 1) by the matrix. 200227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 201227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param matrix the transformation matrix 202227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return the transformed Quad 203227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 204227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public Quad transformed(Matrix matrix) { 205227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks float[] points = asCoords(); 206227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks matrix.mapPoints(points); 207227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return new Quad(points); 208227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 209227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 210227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 211227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Returns the centroid of the Quad. 212227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 213227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * The centroid of the Quad is where the two inner diagonals connecting the opposite corners 214227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * meet. 215227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 216227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return the centroid of the Quad. 217227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 218227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public PointF center() { 219227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // As the diagonals bisect each other, we can simply return the center of one of the 220227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks // diagonals. 221227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return new PointF((mTopLeft.x + mBottomRight.x) / 2f, 222227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks (mTopLeft.y + mBottomRight.y) / 2f); 223227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 224227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 225227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 226227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Returns the quad as a float-array of coordinates. 227227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * The order of coordinates is top-left, top-right, bottom-left, bottom-right. This is the 228227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * default order of coordinates used in ImageShaders, so this method can be used to bind 229227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * an attribute to the Quad. 230227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 231227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public float[] asCoords() { 232227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return new float[] { mTopLeft.x, mTopLeft.y, 233227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mTopRight.x, mTopRight.y, 234227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mBottomLeft.x, mBottomLeft.y, 235227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mBottomRight.x, mBottomRight.y }; 236227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 237227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 238227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 239227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Grow the Quad outwards by the specified factor. 240227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 241227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * This method moves the corner points of the Quad outward along the diagonals that connect 242227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * them to the centroid. A factor of 1.0 moves the quad outwards by the distance of the corners 243227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * to the centroid. 244227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 245227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param factor the growth factor 246227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return the Quad grown by the specified amount 247227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 248227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public Quad grow(float factor) { 249227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks PointF pc = center(); 250227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return new Quad(factor * (mTopLeft.x - pc.x) + pc.x, 251227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks factor * (mTopLeft.y - pc.y) + pc.y, 252227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks factor * (mTopRight.x - pc.x) + pc.x, 253227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks factor * (mTopRight.y - pc.y) + pc.y, 254227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks factor * (mBottomLeft.x - pc.x) + pc.x, 255227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks factor * (mBottomLeft.y - pc.y) + pc.y, 256227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks factor * (mBottomRight.x - pc.x) + pc.x, 257227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks factor * (mBottomRight.y - pc.y) + pc.y); 258227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 259227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 260227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 261227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Scale the Quad by the specified factor. 262227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 263227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param factor the scaling factor 264227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return the Quad instance scaled by the specified factor. 265227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 266227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public Quad scale(float factor) { 267227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return new Quad(mTopLeft.x * factor, mTopLeft.y * factor, 268227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mTopRight.x * factor, mTopRight.y * factor, 269227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mBottomLeft.x * factor, mBottomLeft.y * factor, 270227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mBottomRight.x * factor, mBottomRight.y * factor); 271227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 272227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 273227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 274227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Scale the Quad by the specified factors in the x and y factors. 275227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 276227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param sx the x scaling factor 277227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @param sy the y scaling factor 278227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return the Quad instance scaled by the specified factors. 279227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 280227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public Quad scale2(float sx, float sy) { 281227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return new Quad(mTopLeft.x * sx, mTopLeft.y * sy, 282227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mTopRight.x * sx, mTopRight.y * sy, 283227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mBottomLeft.x * sx, mBottomLeft.y * sy, 284227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mBottomRight.x * sx, mBottomRight.y * sy); 285227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 286227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 287227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 288227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Returns the Quad's left-to-right edge. 289227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 290227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Returns a vector that goes from the Quad's top-left to top-right (or bottom-left to 291227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * bottom-right). 292227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 293227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return the edge vector as a PointF. 294227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 295227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public PointF xEdge() { 296227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return new PointF(mTopRight.x - mTopLeft.x, mTopRight.y - mTopLeft.y); 297227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 298227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 299227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks /** 300227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Returns the Quad's top-to-bottom edge. 301227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 302227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * Returns a vector that goes from the Quad's top-left to bottom-left (or top-right to 303227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * bottom-right). 304227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * 305227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks * @return the edge vector as a PointF. 306227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks */ 307227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public PointF yEdge() { 308227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return new PointF(mBottomLeft.x - mTopLeft.x, mBottomLeft.y - mTopLeft.y); 309227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 310227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 311227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks @Override 312227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks public String toString() { 313227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return "Quad(" + mTopLeft.x + ", " + mTopLeft.y + ", " 314227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks + mTopRight.x + ", " + mTopRight.y + ", " 315227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks + mBottomLeft.x + ", " + mBottomLeft.y + ", " 316227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks + mBottomRight.x + ", " + mBottomRight.y + ")"; 317227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 318227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 319227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private Quad(PointF topLeft, PointF topRight, PointF bottomLeft, PointF bottomRight) { 320227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mTopLeft = topLeft; 321227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mTopRight = topRight; 322227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mBottomLeft = bottomLeft; 323227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mBottomRight = bottomRight; 324227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 325227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 326227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private Quad(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3) { 327227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mTopLeft = new PointF(x0, y0); 328227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mTopRight = new PointF(x1, y1); 329227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mBottomLeft = new PointF(x2, y2); 330227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mBottomRight = new PointF(x3, y3); 331227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 332227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 333227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private Quad(float[] points) { 334227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mTopLeft = new PointF(points[0], points[1]); 335227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mTopRight = new PointF(points[2], points[3]); 336227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mBottomLeft = new PointF(points[4], points[5]); 337227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks mBottomRight = new PointF(points[6], points[7]); 338227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 339227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 340227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks private static PointF rotatePoint(PointF p, PointF c, float cosa, float sina) { 341227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks float x = (p.x - c.x) * cosa - (p.y - c.y) * sina + c.x; 342227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks float y = (p.x - c.x) * sina + (p.y - c.y) * cosa + c.y; 343227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks return new PointF(x,y); 344227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks } 345227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks} 346227b47625d7482b5b47ad0e4c70ce0a246236adeBenjamin Hendricks 347