/* JWildfire - an image and animation processor written in Java Copyright (C) 1995-2014 Andreas Maschke This is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this software; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jwildfire.create.tina.swing.flamepanel; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Graphics2D; import org.jwildfire.base.Prefs; import org.jwildfire.base.mathlib.MathLib; import org.jwildfire.create.tina.base.XForm; public abstract class AbstractControlHandler<T extends AbstractControlShape> { protected final Prefs prefs; protected final FlamePanelConfig config; public AbstractControlHandler(Prefs pPrefs, FlamePanelConfig pConfig) { prefs = pPrefs; config = pConfig; } protected static final Color XFORM_COLOR = new Color(217, 219, 223); protected static final Color XFORM_POST_COLOR = new Color(255, 219, 160); protected static final BasicStroke SELECTED_LINE_NEW = new BasicStroke(2.0f); protected static final BasicStroke NORMAL_CIRCLE_LINE = new BasicStroke(1.0f); protected static final BasicStroke SELECTED_CIRCLE_LINE = new BasicStroke(2.0f); protected static final BasicStroke NORMAL_LINE_NEW = new BasicStroke(2.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 0, new float[] { 10, 4 }, 0); protected static final int SHADOW_DIST = 1; // Apophysis-compatible colors protected static final Color[] XFORM_COLORS = new Color[] { new Color(255, 0, 0), new Color(204, 204, 0), new Color(0, 204, 0), new Color(0, 204, 204), new Color(64, 64, 255), new Color(204, 0, 204), new Color(204, 128, 0), new Color(128, 0, 79), new Color(128, 128, 34), new Color(96, 128, 96), new Color(80, 128, 128), new Color(79, 79, 128), new Color(128, 80, 128), new Color(128, 96, 34) }; public abstract void drawXForm(Graphics2D g, XForm pXForm, int pIndex, int pXFormCount, boolean pIsFinal, boolean pShadow, boolean pIsSelected); public abstract boolean isInsideXForm(XForm pXForm, int pX, int pY); public abstract T convertXFormToShape(XForm pXForm); public abstract int selectNearestPoint(XForm pXForm, int pViewX, int pViewY); // Algorithm from http://www.blackpawn.com/texts/pointinpoly/default.html protected boolean insideTriange(TriangleControlShape pTriangle, int pViewX, int pViewY) { // Compute vectors // v0 = C - A // v1 = B - A // v2 = P - A // A: pTriangle,view[0] // B: pTriangle,view[1] // C: pTriangle,view[2] double v0x = pTriangle.viewX[2] - pTriangle.viewX[0]; double v0y = pTriangle.viewY[2] - pTriangle.viewY[0]; double v1x = pTriangle.viewX[1] - pTriangle.viewX[0]; double v1y = pTriangle.viewY[1] - pTriangle.viewY[0]; double v2x = pViewX - pTriangle.viewX[0]; double v2y = pViewY - pTriangle.viewY[0]; // Compute dot products double dot00 = v0x * v0x + v0y * v0y; double dot01 = v0x * v1x + v0y * v1y; double dot02 = v0x * v2x + v0y * v2y; double dot11 = v1x * v1x + v1y * v1y; double dot12 = v1x * v2x + v1y * v2y; // Compute barycentric coordinates double invDenom = 1 / (dot00 * dot11 - dot01 * dot01); double u = (dot11 * dot02 - dot01 * dot12) * invDenom; double v = (dot00 * dot12 - dot01 * dot02) * invDenom; // Check if point is in triangle return (u >= 0) && (v >= 0) && (u + v < 1); } protected int selectNearestPointFromTriangle(TriangleControlShape pTriangle, int viewX, int viewY) { double dx, dy; dx = pTriangle.viewX[0] - viewX; dy = pTriangle.viewY[0] - viewY; double dr0 = MathLib.sqrt(dx * dx + dy * dy); dx = pTriangle.viewX[1] - viewX; dy = pTriangle.viewY[1] - viewY; double dr1 = MathLib.sqrt(dx * dx + dy * dy); dx = pTriangle.viewX[2] - viewX; dy = pTriangle.viewY[2] - viewY; double dr2 = MathLib.sqrt(dx * dx + dy * dy); return dr0 < dr1 ? (dr0 < dr2 ? 0 : 2) : (dr1 < dr2 ? 1 : 2); } }