Java tutorial
/* * Copyright (c) 2004-2016 Universidade do Porto - Faculdade de Engenharia * Laboratrio de Sistemas e Tecnologia Subaqutica (LSTS) * All rights reserved. * Rua Dr. Roberto Frias s/n, sala I203, 4200-465 Porto, Portugal * * This file is part of Neptus, Command and Control Framework. * * Commercial Licence Usage * Licencees holding valid commercial Neptus licences may use this file * in accordance with the commercial licence agreement provided with the * Software or, alternatively, in accordance with the terms contained in a * written agreement between you and Universidade do Porto. For licensing * terms, conditions, and further information contact lsts@fe.up.pt. * * European Union Public Licence - EUPL v.1.1 Usage * Alternatively, this file may be used under the terms of the EUPL, * Version 1.1 only (the "Licence"), appearing in the file LICENSE.md * included in the packaging of this file. You may not use this work * except in compliance with the Licence. Unless required by applicable * law or agreed to in writing, software distributed under the Licence is * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF * ANY KIND, either express or implied. See the Licence for the specific * language governing permissions and limitations at * http://ec.europa.eu/idabc/eupl.html. * * For more information please see <http://lsts.fe.up.pt/neptus>. * * Author: pdias * 28/04/2016 */ package pt.lsts.neptus.mp.maneuvers; import java.awt.Graphics2D; import java.awt.event.MouseEvent; import java.util.LinkedHashMap; import java.util.Vector; import org.dom4j.Document; import org.dom4j.DocumentHelper; import org.dom4j.Element; import org.dom4j.Node; import com.l2fprod.common.propertysheet.DefaultProperty; import com.l2fprod.common.propertysheet.Property; import pt.lsts.imc.IMCMessage; import pt.lsts.neptus.NeptusLog; import pt.lsts.neptus.i18n.I18n; import pt.lsts.neptus.mp.ManeuverLocation; import pt.lsts.neptus.plugins.NeptusProperty; import pt.lsts.neptus.renderer2d.StateRenderer2D; import pt.lsts.neptus.types.map.PlanElement; import pt.lsts.neptus.util.AngleUtils; import pt.lsts.neptus.util.MathMiscUtils; /** * @author pdias * */ public class ExpandingSquarePattern extends FollowPath { @NeptusProperty(name = "Width", description = "Width of the volume to cover, in meters") private double width = 100; @NeptusProperty(name = "Horizontal Step", description = "Horizontal distance between rows, in meters") private double hstep = 50; @NeptusProperty(name = "Bearing", description = "The outgoing bearing (from starting location) in degrees") private double bearingDeg = 0; @NeptusProperty(name = "First Curve Right", description = "If the first curve should be to the right or left") private boolean firstCurveRight = true; static { registerPattern(ExpandingSquarePattern.class); } public ExpandingSquarePattern() { super(); editingHelpText = I18n.text("Ctrl+Click to grow | Shift+Click to rotate"); recalcPoints(); } @Override public String getName() { return "ExpandingSquarePattern"; } @Override public void paintOnMap(Graphics2D g2d, PlanElement planElement, StateRenderer2D renderer) { super.paintOnMap(g2d, planElement, renderer); double zoom = renderer.getZoom(); g2d.rotate(-renderer.getRotation()); g2d.rotate(-Math.PI / 2); ManeuversUtil.paintBox(g2d, zoom, width, width, -width / 2, -width / 2, Math.toRadians(bearingDeg), 0, false, false, editing); ManeuversUtil.paintPointLineList(g2d, zoom, points, false, 0, editing); g2d.rotate(Math.PI / 2); g2d.rotate(renderer.getRotation()); } /** * Call this to update the maneuver points. */ protected void recalcPoints() { Vector<double[]> newPoints = ManeuversUtil.calcExpansiveSquarePatternPointsMaxBox(width, hstep, Math.toRadians(bearingDeg), !firstCurveRight); points = newPoints; } /* (non-Javadoc) * @see pt.lsts.neptus.mp.maneuvers.LocationProvider#getFirstPosition() */ @Override public ManeuverLocation getStartLocation() { try { double[] first = points.firstElement(); ManeuverLocation loc = getManeuverLocation().clone(); loc.translatePosition(first[X], first[Y], first[Z]); return loc; } catch (Exception e) { return getManeuverLocation(); } } /* (non-Javadoc) * @see pt.lsts.neptus.mp.maneuvers.LocationProvider#getLastPosition() */ @Override public ManeuverLocation getEndLocation() { try { double[] last = points.lastElement(); ManeuverLocation loc = getManeuverLocation().clone(); loc.translatePosition(last[X], last[Y], last[Z]); return loc; } catch (Exception e) { return getManeuverLocation(); } } /* (non-Javadoc) * @see pt.lsts.neptus.mp.maneuvers.LocationProvider#setPosition(pt.lsts.neptus.types.coord.AbstractLocationPoint) */ @Override public void setManeuverLocation(ManeuverLocation location) { super.setManeuverLocation(location); recalcPoints(); } /* (non-Javadoc) * @see pt.lsts.neptus.renderer2d.StateRendererInteraction#mouseClicked(java.awt.event.MouseEvent, pt.lsts.neptus.renderer2d.StateRenderer2D) */ @Override public void mouseClicked(MouseEvent event, StateRenderer2D source) { adapter.mouseClicked(event, source); } /* (non-Javadoc) * @see pt.lsts.neptus.renderer2d.StateRendererInteraction#mouseDragged(java.awt.event.MouseEvent, pt.lsts.neptus.renderer2d.StateRenderer2D) */ @Override public void mouseDragged(MouseEvent event, StateRenderer2D source) { if (lastDragPoint == null) { adapter.mouseDragged(event, source); lastDragPoint = event.getPoint(); return; } double xammount = event.getPoint().getX() - lastDragPoint.getX(); double yammount = event.getPoint().getY() - lastDragPoint.getY(); yammount = -yammount; if (event.isControlDown()) { double norm = Math.sqrt(xammount * xammount + yammount * yammount); double angle = AngleUtils.calcAngle(lastDragPoint.getY(), lastDragPoint.getX(), event.getPoint().getY(), event.getPoint().getX()); double nx = norm * Math.cos(Math.toDegrees(bearingDeg) - angle); // double ny = norm * Math.sin(Math.toDegrees(bearingDeg) - angle); width += nx / (Math.abs(nx) < 30 ? 10 : 2); width = MathMiscUtils.round(width, 1); width = Math.max(1, width); recalcPoints(); } else if (event.isShiftDown()) { bearingDeg = MathMiscUtils.round(Math.toDegrees( Math.toRadians(bearingDeg) + Math.toRadians(yammount / (Math.abs(yammount) < 30 ? 10 : 2))), 2); while (bearingDeg > 360) bearingDeg -= 360; while (bearingDeg < 0) bearingDeg += 360; recalcPoints(); } else { adapter.mouseDragged(event, source); } lastDragPoint = event.getPoint(); } @Override public void translate(double offsetNorth, double offsetEast, double offsetDown) { super.translate(offsetNorth, offsetEast, offsetDown); recalcPoints(); } @Override public void loadFromXML(String xml) { try { Document doc = DocumentHelper.parseText(xml); Node node = doc.selectSingleNode("//basePoint/point"); ManeuverLocation loc = new ManeuverLocation(); loc.load(node.asXML()); setManeuverLocation(loc); // Speed Node speedNode = doc.selectSingleNode("//speed"); speed = Double.parseDouble(speedNode.getText()); // speed_units = speedNode.valueOf("@unit"); SPEED_UNITS sUnits = ManeuversXMLUtil.parseSpeedUnits((Element) speedNode); setSpeedUnits(sUnits); bearingDeg = Double.parseDouble(doc.selectSingleNode("//bearing").getText()); // area width = Double.parseDouble(doc.selectSingleNode("//width").getText()); //steps hstep = Double.parseDouble(doc.selectSingleNode("//hstep").getText()); node = doc.selectSingleNode("//firstCurveRight"); if (node != null) firstCurveRight = Boolean.parseBoolean(node.getText()); else firstCurveRight = true; } catch (Exception e) { NeptusLog.pub().error(this, e); return; } finally { recalcPoints(); } } @Override public Document getManeuverAsDocument(String rootElementName) { Document document = DocumentHelper.createDocument(); Element root = document.addElement(rootElementName); root.addAttribute("kind", "automatic"); //basePoint Element basePoint = root.addElement("basePoint"); Element point = getManeuverLocation().asElement("point"); basePoint.add(point); basePoint.addAttribute("type", "pointType"); root.addElement("width").setText("" + width); root.addElement("hstep").setText("" + hstep); root.addElement("bearing").setText("" + bearingDeg); if (!firstCurveRight) root.addElement("firstCurveRight").setText("" + firstCurveRight); //speed Element speedElem = root.addElement("speed"); speedElem.addAttribute("unit", speedUnits.getString()); speedElem.setText("" + speed); return document; } @Override public IMCMessage serializeToIMC() { IMCMessage msg = super.serializeToIMC(); LinkedHashMap<String, Object> customValues = new LinkedHashMap<String, Object>(); customValues.put("Pattern", getName()); customValues.put("bearingRad", Math.toRadians(bearingDeg)); customValues.put("width", width); customValues.put("hstep", hstep); customValues.put("firstCurveRight", firstCurveRight); String customValuesTL = IMCMessage.encodeTupleList(customValues); msg.setValue("custom", customValuesTL); return msg; } @Override public void parseIMCMessage(IMCMessage message) { super.parseIMCMessage(message); LinkedHashMap<String, String> customValues = customSettings; // message.getTupleList("custom"); String pattern = customValues.remove("Pattern"); if (!getName().equalsIgnoreCase(pattern)) return; String value = customValues.remove("bearingRad"); try { bearingDeg = Math.toDegrees(Double.parseDouble(value)); } catch (NumberFormatException e) { e.printStackTrace(); } value = customValues.remove("width"); try { width = Double.parseDouble(value); } catch (NumberFormatException e) { e.printStackTrace(); } value = customValues.remove("hstep"); try { hstep = Double.parseDouble(value); } catch (NumberFormatException e) { e.printStackTrace(); } value = customValues.remove("firstCurveRight"); firstCurveRight = Boolean.parseBoolean(value); recalcPoints(); } @Override protected Vector<DefaultProperty> additionalProperties() { return ManeuversUtil.getPropertiesFromManeuver(this); } @Override public void setProperties(Property[] properties) { super.setProperties(properties); ManeuversUtil.setPropertiesToManeuver(this, properties); recalcPoints(); } /* (non-Javadoc) * @see pt.lsts.neptus.mp.Maneuver#clone() */ @Override public Object clone() { ExpandingSquarePattern clone = (ExpandingSquarePattern) super.clone(); clone.bearingDeg = bearingDeg; clone.width = width; clone.hstep = hstep; clone.firstCurveRight = firstCurveRight; clone.recalcPoints(); return clone; } }