/** * Copyright 2013 OpenSocial Foundation * Copyright 2013 International Business Machines Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Utility library for working with Activity Streams Actions * Requires underscorejs. * * @author James M Snell (jasnell@us.ibm.com) */ package com.ibm.common.geojson; import static com.google.common.primitives.Floats.concat; import static com.google.common.primitives.Floats.toArray; import java.io.ObjectStreamException; import java.io.Serializable; import java.util.Arrays; import java.util.Iterator; import com.google.common.base.Supplier; import com.google.common.collect.ImmutableList; import com.google.common.primitives.Floats; /** * A GeoJSON Position * see http://geojson.org/geojson-spec.html#positions. * * Position objects consist primarily of three distinct values: * a northing (latitude or x), easting (longitude or y) and altitude (z). * * @author james * */ public final class Position implements Iterable<Float>, Serializable { public static final class Builder implements Supplier<Position> { private float x,y,z; private boolean hasz = false; private ImmutableList.Builder<Float> rest = ImmutableList.builder(); public Builder northing(float x) { this.x = x; return this; } public Builder easting(float y) { this.y = y; return this; } public Builder altitude(float z) { this.hasz = true; this.z = z; return this; } public Builder additional(float m) { this.rest.add(m); return this; } public Position get() { return new Position(this); } } private final float x,y,z; private final boolean hasz; private final float[] rest; Position(Builder builder) { this.x = builder.x; this.y = builder.y; this.z = builder.z; this.hasz = builder.hasz; this.rest = toArray(builder.rest.build()); } public float northing() { return x; } public float easting() { return y; } public float altitude() { return z; } public boolean hasAltitude() { return hasz; } public int size() { return values().length; } private float[] values() { return hasz? concat(new float[] {x,y,z}, rest) : concat(new float[] {x,y}, rest); } public String toString() { return Arrays.toString(values()); } @Override public Iterator<Float> iterator() { return Floats.asList(values()).iterator(); } Object writeReplace() throws java.io.ObjectStreamException { return new SerializedForm(this); } private static class SerializedForm implements Serializable { private static final long serialVersionUID = -2060301713159936285L; private float x,y,z; private boolean hasz; private float[] rest; protected SerializedForm(Position obj) { this.x = obj.x; this.y = obj.y; this.z = obj.z; this.hasz = obj.hasz; this.rest = obj.rest; } Object readResolve() throws ObjectStreamException { Position.Builder position = new Position.Builder() .northing(x) .easting(y) .altitude(z); position.hasz = this.hasz; if (rest != null) for (float f : rest) position.additional(f); return position.get(); } } }