/******************************************************************************* * 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.utils.geom; import java.awt.geom.Point2D; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Set; import org.simantics.g2d.utils.GeometryUtils; /** * A set of compass [0..360) directions */ public class DirectionSet extends HashSet { public static final DirectionSet NESW = new DirectionSet(0.0, 90.0, 180.0, 270.0); public static final DirectionSet N = new DirectionSet(0.0); public static final DirectionSet NE = new DirectionSet(0.0, 90.0); public static final DirectionSet E = new DirectionSet(90.0); public static final DirectionSet SE = new DirectionSet(90.0,180.0); public static final DirectionSet S = new DirectionSet(180.0); public static final DirectionSet SW = new DirectionSet(180.0, 270.0); public static final DirectionSet W = new DirectionSet(270.0); public static final DirectionSet NW = new DirectionSet(270.0, 0.0); public static final DirectionSet NE2 = new DirectionSet(0.0, 90.0, 45.0); public static final DirectionSet SE2 = new DirectionSet(90.0,180.0, 135.0); public static final DirectionSet SW2 = new DirectionSet(180.0, 270.0, 225.0); public static final DirectionSet NW2 = new DirectionSet(270.0, 0.0, 315.0); public static final DirectionSet HORIZ = new DirectionSet(90.0, 270.0); public static final DirectionSet VERT = new DirectionSet(0.0, 180.0); public static final DirectionSet ANY = new DirectionSet( 0, 15, 30, 45, 60, 75, 90, 105, 120, 135, 150, 165, 180, 195, 210, 225, 240, 255, 270, 285, 300, 315, 330, 345); private Set unitVectors; public DirectionSet(double ... directions) { for (double d : directions) add(d); } private static final long serialVersionUID = 1L; private boolean add(double e) { if (e<0 || e>=360.0) e = Math.IEEEremainder(e, 360.0); if (e<0) e = 360.0-e; return super.add(e); } @Override public boolean add(Double e) { unitVectors = null; if (e==null) return false; return add((double)e); } @Override public boolean addAll(Collection c) { unitVectors = null; return super.addAll(c); } @Override public boolean remove(Object o) { unitVectors = null; return super.remove(o); } @Override public boolean removeAll(Collection c) { unitVectors = null; return super.removeAll(c); } @Override public void clear() { unitVectors = null; super.clear(); } public Double getClosestDirection(double d2) { Double closest = null; for (Double d1 : this) { double diff = d1>180==d2>180 ? Math.abs(d1-d2) : d1180==d2>180 ? Math.abs(d1-d2) : d1tolerance) continue; if (closest==null || closest360.0) dir-=360.0; result.add(dir); } return result; } /** * Get directions as unit vectors * @return collection where to add unit vectors */ private Set createUnitVectors() { HashSet result = new HashSet(size()); for (double d : this) result.add( GeometryUtils.toUnitVector(d, new Point2D.Double()) ); return result; } public Set getUnitVectors() { if (unitVectors==null) { unitVectors = createUnitVectors(); unitVectors = Collections.unmodifiableSet(unitVectors); } return unitVectors; } }