X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.g2d%2Fsrc%2Forg%2Fsimantics%2Fg2d%2Felementclass%2Fwheel%2FRotatorHandler.java;h=f364f5040b05a908bd4bbdc04109ab1fd85eb08d;hp=53df784f0b88a612227afd9e74bc2432f9bd22f7;hb=fe9ef5837d666acca45b00de17b94034f8edcee3;hpb=969bd23cab98a79ca9101af33334000879fb60c5 diff --git a/bundles/org.simantics.g2d/src/org/simantics/g2d/elementclass/wheel/RotatorHandler.java b/bundles/org.simantics.g2d/src/org/simantics/g2d/elementclass/wheel/RotatorHandler.java index 53df784f0..f364f5040 100644 --- a/bundles/org.simantics.g2d/src/org/simantics/g2d/elementclass/wheel/RotatorHandler.java +++ b/bundles/org.simantics.g2d/src/org/simantics/g2d/elementclass/wheel/RotatorHandler.java @@ -1,293 +1,286 @@ -/******************************************************************************* - * Copyright (c) 2007, 2010 Association for Decentralized Information Management - * in Industry THTH ry. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * VTT Technical Research Centre of Finland - initial API and implementation - *******************************************************************************/ -package org.simantics.g2d.elementclass.wheel; - -import java.awt.geom.Point2D; -import java.awt.geom.Rectangle2D; - -import javax.vecmath.Vector2d; -import javax.vecmath.Vector3d; - -import org.simantics.g2d.canvas.ICanvasContext; -import org.simantics.g2d.diagram.IDiagram; -import org.simantics.g2d.element.ElementHints; -import org.simantics.g2d.element.IElement; -import org.simantics.g2d.element.handler.InternalSize; -import org.simantics.g2d.element.handler.Stateful; -import org.simantics.g2d.element.handler.HandleMouseEvent; -import org.simantics.g2d.element.handler.Heartbeat; -import org.simantics.g2d.element.handler.LifeCycle; -import org.simantics.g2d.element.handler.Rotate; -import org.simantics.g2d.element.handler.impl.AbstractGrabbable; -import org.simantics.utils.datastructures.hints.IHintContext.Key; -import org.simantics.utils.datastructures.hints.IHintContext.KeyOf; - -/** - * This handlerer rotates element when it is touched. - * - * Hints used: - * KEY_VALUE - * KEY_MIN_VALUE optional - * KEY_MAX_VALUE optional - * KEY_FRICTION - * KEY_FACTOR - * KEY_GRAB_FRICTION - * KEY_MIN_POINTERS - * KEY_LOCKED - * - * @author Toni Kalajainen - */ -public class RotatorHandler extends AbstractGrabbable implements HandleMouseEvent, LifeCycle, Heartbeat { - - private static final long serialVersionUID = -3588513675880482627L; - - public static final RotatorHandler INSTANCE = new RotatorHandler(); - - public static final double STRAY_DISTANCE = 1000; - - public double initial_friction = 0.20; - public double initial_grab_friction = 0.99; - public double initial_factor = 0.025; - // When ang vel goes under tolerance, the motion is considered stopped - public double angVelTolerance = 0.5; - - /** Angular velocity, canvas specific variable */ - public static final Key KEY_ANG_VEL = new KeyOf(Double.class); - /** Minimum number of pointers */ - public static final Key KEY_MIN_POINTERS = new KeyOf(Integer.class); - public static final Key KEY_GRAB_FRICTION = new KeyOf(Double.class); - public static final Key KEY_FRICTION = new KeyOf(Double.class); - public static final Key KEY_FACTOR = new KeyOf(Double.class); - - public RotatorHandler() { - super(1000.0); - } - - @Override - protected void onDrag(GrabInfo gi, ICanvasContext ctx) { - IElement e = gi.e; - Point2D origo = getOrigo(e, null); - Point2D prevPos = gi.prevPosElement; - Point2D p = gi.dragPosElement; - - // ---- Wheel is held! ---- - // position vector 0 - Vector2d p0 = new Vector2d(prevPos.getX(), prevPos.getY()); - // position vector 1 - Vector2d p1 = new Vector2d(p.getX(), p.getY()); - // motion vector - Vector2d f = new Vector2d(p1); - f.sub(p0); - // no movement - if (f.length()==0) return; - - // -- We are holding the wheel and we have moved the pointer -- - - // vector from origo to mouse - Vector2d odp0 = new Vector2d(p0.x - origo.getX(), p0.y - origo.getY()); - Vector2d odp1 = new Vector2d(p1.x - origo.getX(), p1.y - origo.getY()); - // convert motion into tangential and normal vectors - // normal vector of the motion - Vector2d fn = new Vector2d(odp0); - fn.scale( f.dot(odp0) / odp0.lengthSquared() ); - // tangential vector of the motion - Vector2d ft = new Vector2d(f); - ft.sub(fn); - - // momentum - Vector3d r = new Vector3d(odp0.x, odp0.y, 0); - Vector3d F = new Vector3d(ft.x, ft.y, 0); - Vector3d M = new Vector3d(); - M.cross(r, F); - if (!isGrabbed(e, ctx)) return; - - // Turn the wheel - double deltaAngle = odp0.angle(odp1); - if (M.z<0) deltaAngle *= -1; - - double deltaAngularVelocity = deltaAngle * 20; - setAngVel(e, getAngVel(e)+deltaAngularVelocity); - - deltaAngle *= 0.297; - modifyValue(e, ctx, deltaAngle); - } - - @Override - protected void onGrab(GrabInfo gi, ICanvasContext ctx) { - } - - @Override - protected void onGrabCancel(GrabInfo gi, ICanvasContext ctx) { - } - - @Override - protected boolean onGrabCheck(IElement e, ICanvasContext ctx, int pointerId, Point2D pickPos) { - return isEnabled(e); - } - - @Override - protected void onRelease(GrabInfo gi, ICanvasContext ctx) { - } - - @Override - public void heartbeat(IElement e, long time, long deltaTime, ICanvasContext ctx) { - - boolean isGrabbed = isGrabbed(e, ctx); - boolean isMoving = isMoving(e); - boolean isLocked = isLocked(e); - - - // Check if the value has changed in the value source - if ((!isGrabbed && !isMoving)||isLocked) { - setAngVel(e, 0.0); - return; - } - - double angVel = getAngVel(e); - //System.out.println(angVel); - // not moving - if (angVel==0) return; - - // motion under tolerance - if (Math.abs(angVel)max) value = max; - e.setHint(ElementHints.KEY_VALUE, value); - - Point2D origo = getOrigo(e, null); - - Rotate r = e.getElementClass().getSingleItem(Rotate.class); - double angle = r.getAngle(e); - ///System.out.println(angle); - double targetAngle = Math.IEEEremainder(value, Math.PI*2); - double diffrence = targetAngle - angle; - r.rotate(e, diffrence, origo); - } - - public Point2D getOrigo(IElement e, Point2D origo) - { - Rectangle2D size = new Rectangle2D.Double(); - InternalSize b = e.getElementClass().getSingleItem(InternalSize.class); - b.getBounds(e, size); - if (origo==null) origo = new Point2D.Double(size.getCenterX(),size.getCenterY()); - return origo; - } - - public synchronized void modifyValue(IElement e, ICanvasContext ctx, double modification) { - Double position = getValue(e); - double value = position + modification; - setValue(e, ctx, value); - } - - - public int getMinPointers(IElement e) { - Integer i = e.getHint(KEY_MIN_POINTERS); - if (i==null) return 1; - return i; - } - - public double getAngVel(IElement e) - { - Double d = e.getHint(KEY_ANG_VEL); - if (d==null) return 0.0; - return d; - } - - public void setAngVel(IElement e, double value) - { - e.setHint(KEY_ANG_VEL, value); - } - - public boolean isGrabbed(IElement e, ICanvasContext ctx) { - return (getGrabCount(e, ctx)>=getMinPointers(e)) || !isEnabled(e); - } - - public boolean isMoving(IElement e) { - return getAngVel(e)!=0; - } - - public boolean isLocked(IElement e) { - Boolean b = e.getHint(ElementHints.KEY_LOCKED); - return b==null?false:b; - } - - public boolean isEnabled(IElement e) { - Stateful enabled = e.getElementClass().getAtMostOneItemOfClass(Stateful.class); - if (enabled==null) return true; - return enabled.isEnabled(e); - } - - public boolean isMoveable(IElement e) { - return true; - } - - - -} +/******************************************************************************* + * Copyright (c) 2007, 2010 Association for Decentralized Information Management + * in Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.g2d.elementclass.wheel; + +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; + +import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; +import org.apache.commons.math3.geometry.euclidean.twod.Vector2D; +import org.simantics.g2d.canvas.ICanvasContext; +import org.simantics.g2d.diagram.IDiagram; +import org.simantics.g2d.element.ElementHints; +import org.simantics.g2d.element.IElement; +import org.simantics.g2d.element.handler.InternalSize; +import org.simantics.g2d.element.handler.Stateful; +import org.simantics.g2d.element.handler.HandleMouseEvent; +import org.simantics.g2d.element.handler.Heartbeat; +import org.simantics.g2d.element.handler.LifeCycle; +import org.simantics.g2d.element.handler.Rotate; +import org.simantics.g2d.element.handler.impl.AbstractGrabbable; +import org.simantics.utils.datastructures.hints.IHintContext.Key; +import org.simantics.utils.datastructures.hints.IHintContext.KeyOf; + +/** + * This handlerer rotates element when it is touched. + * + * Hints used: + * KEY_VALUE + * KEY_MIN_VALUE optional + * KEY_MAX_VALUE optional + * KEY_FRICTION + * KEY_FACTOR + * KEY_GRAB_FRICTION + * KEY_MIN_POINTERS + * KEY_LOCKED + * + * @author Toni Kalajainen + */ +public class RotatorHandler extends AbstractGrabbable implements HandleMouseEvent, LifeCycle, Heartbeat { + + private static final long serialVersionUID = -3588513675880482627L; + + public static final RotatorHandler INSTANCE = new RotatorHandler(); + + public static final double STRAY_DISTANCE = 1000; + + public double initial_friction = 0.20; + public double initial_grab_friction = 0.99; + public double initial_factor = 0.025; + // When ang vel goes under tolerance, the motion is considered stopped + public double angVelTolerance = 0.5; + + /** Angular velocity, canvas specific variable */ + public static final Key KEY_ANG_VEL = new KeyOf(Double.class); + /** Minimum number of pointers */ + public static final Key KEY_MIN_POINTERS = new KeyOf(Integer.class); + public static final Key KEY_GRAB_FRICTION = new KeyOf(Double.class); + public static final Key KEY_FRICTION = new KeyOf(Double.class); + public static final Key KEY_FACTOR = new KeyOf(Double.class); + + public RotatorHandler() { + super(1000.0); + } + + @Override + protected void onDrag(GrabInfo gi, ICanvasContext ctx) { + IElement e = gi.e; + Point2D origo = getOrigo(e, null); + Point2D prevPos = gi.prevPosElement; + Point2D p = gi.dragPosElement; + + // ---- Wheel is held! ---- + // position vector 0 + Vector2D p0 = new Vector2D(prevPos.getX(), prevPos.getY()); + // position vector 1 + Vector2D p1 = new Vector2D(p.getX(), p.getY()); + // motion vector + Vector2D f = p1.subtract(p0); + // no movement + if (f.getNormSq()==0) return; + + // -- We are holding the wheel and we have moved the pointer -- + + // vector from origo to mouse + Vector2D odp0 = new Vector2D(p0.getX() - origo.getX(), p0.getY() - origo.getY()); + Vector2D odp1 = new Vector2D(p1.getX() - origo.getX(), p1.getY() - origo.getY()); + // convert motion into tangential and normal vectors + // normal vector of the motion + Vector2D fn = odp0.scalarMultiply( f.dotProduct(odp0) / odp0.getNormSq() ); + // tangential vector of the motion + Vector2D ft = f.subtract(fn); + + // momentum + Vector3D r = new Vector3D(odp0.getX(), odp0.getY(), 0); + Vector3D F = new Vector3D(ft.getX(), ft.getY(), 0); + Vector3D M = r.crossProduct(F); + if (!isGrabbed(e, ctx)) return; + + // Turn the wheel + double deltaAngle = Vector2D.angle(odp0, odp1); + if (M.getZ()<0) deltaAngle *= -1; + + double deltaAngularVelocity = deltaAngle * 20; + setAngVel(e, getAngVel(e)+deltaAngularVelocity); + + deltaAngle *= 0.297; + modifyValue(e, ctx, deltaAngle); + } + + @Override + protected void onGrab(GrabInfo gi, ICanvasContext ctx) { + } + + @Override + protected void onGrabCancel(GrabInfo gi, ICanvasContext ctx) { + } + + @Override + protected boolean onGrabCheck(IElement e, ICanvasContext ctx, int pointerId, Point2D pickPos) { + return isEnabled(e); + } + + @Override + protected void onRelease(GrabInfo gi, ICanvasContext ctx) { + } + + @Override + public void heartbeat(IElement e, long time, long deltaTime, ICanvasContext ctx) { + + boolean isGrabbed = isGrabbed(e, ctx); + boolean isMoving = isMoving(e); + boolean isLocked = isLocked(e); + + + // Check if the value has changed in the value source + if ((!isGrabbed && !isMoving)||isLocked) { + setAngVel(e, 0.0); + return; + } + + double angVel = getAngVel(e); + //System.out.println(angVel); + // not moving + if (angVel==0) return; + + // motion under tolerance + if (Math.abs(angVel)max) value = max; + e.setHint(ElementHints.KEY_VALUE, value); + + Point2D origo = getOrigo(e, null); + + Rotate r = e.getElementClass().getSingleItem(Rotate.class); + double angle = r.getAngle(e); + ///System.out.println(angle); + double targetAngle = Math.IEEEremainder(value, Math.PI*2); + double diffrence = targetAngle - angle; + r.rotate(e, diffrence, origo); + } + + public Point2D getOrigo(IElement e, Point2D origo) + { + Rectangle2D size = new Rectangle2D.Double(); + InternalSize b = e.getElementClass().getSingleItem(InternalSize.class); + b.getBounds(e, size); + if (origo==null) origo = new Point2D.Double(size.getCenterX(),size.getCenterY()); + return origo; + } + + public synchronized void modifyValue(IElement e, ICanvasContext ctx, double modification) { + Double position = getValue(e); + double value = position + modification; + setValue(e, ctx, value); + } + + + public int getMinPointers(IElement e) { + Integer i = e.getHint(KEY_MIN_POINTERS); + if (i==null) return 1; + return i; + } + + public double getAngVel(IElement e) + { + Double d = e.getHint(KEY_ANG_VEL); + if (d==null) return 0.0; + return d; + } + + public void setAngVel(IElement e, double value) + { + e.setHint(KEY_ANG_VEL, value); + } + + public boolean isGrabbed(IElement e, ICanvasContext ctx) { + return (getGrabCount(e, ctx)>=getMinPointers(e)) || !isEnabled(e); + } + + public boolean isMoving(IElement e) { + return getAngVel(e)!=0; + } + + public boolean isLocked(IElement e) { + Boolean b = e.getHint(ElementHints.KEY_LOCKED); + return b==null?false:b; + } + + public boolean isEnabled(IElement e) { + Stateful enabled = e.getElementClass().getAtMostOneItemOfClass(Stateful.class); + if (enabled==null) return true; + return enabled.isEnabled(e); + } + + public boolean isMoveable(IElement e) { + return true; + } + +}