/* * $Id$ * This file is a part of the Arakhne Foundation Classes, http://www.arakhne.org/afc * * Copyright (c) 2000-2012 Stephane GALLAND. * Copyright (c) 2005-10, Multiagent Team, Laboratoire Systemes et Transports, * Universite de Technologie de Belfort-Montbeliard. * Copyright (c) 2013-2016 The original authors, and other authors. * * 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. */ package org.arakhne.afc.math.graph.simple; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import org.eclipse.xtext.xbase.lib.Pure; import org.arakhne.afc.math.graph.GraphSegment; import org.arakhne.afc.vmutil.asserts.AssertMessages; /** This class provides a simple implementation of a graph's segment * for a {@link SGraph}. * * @author $Author: sgalland$ * @version $FullVersion$ * @mavengroupid $GroupId$ * @mavenartifactid $ArtifactId$ * @since 13.0 */ public class SGraphSegment implements GraphSegment<SGraphSegment, SGraphPoint> { private final WeakReference<SGraph> graph; private double length; private SGraphPoint startPoint; private SGraphPoint endPoint; private List<Object> userData; /** * @param graph1 is the graph in which the segment is. */ public SGraphSegment(SGraph graph1) { this(graph1, Double.NaN); } /** * @param graph1 is the graph in which the segment is. * @param length1 is the length of the segment. */ public SGraphSegment(SGraph graph1, double length1) { assert graph1 != null; this.length = length1; graph1.add(this); this.graph = new WeakReference<>(graph1); this.startPoint = new SGraphPoint(graph1); this.endPoint = new SGraphPoint(graph1); } /** Replies the graph in which this segment is. * * @return the graph in which this segment is. */ @Pure public SGraph getGraph() { return this.graph.get(); } private void setBegin(SGraphPoint pt) { if (this.startPoint != null) { pt.add(this.startPoint.getConnectedSegments()); this.startPoint.clear(); } this.startPoint = pt; } private void setEnd(SGraphPoint pt) { if (this.endPoint != null) { pt.add(this.endPoint.getConnectedSegments()); this.endPoint.clear(); } this.endPoint = pt; } /** Connect the begin point of this segment to the * begin point of the given segment. * This function change the connection points of the two segments. * * @param segment the segment. * @throws IllegalArgumentException if the given segment is not in the same graph. */ public void connectBeginToBegin(SGraphSegment segment) { if (segment.getGraph() != getGraph()) { throw new IllegalArgumentException(); } final SGraphPoint point = new SGraphPoint(getGraph()); setBegin(point); segment.setBegin(point); final SGraph g = getGraph(); assert g != null; g.updatePointCount(-1); } /** Connect the begin point of this segment to the * end point of the given segment. * This function change the connection points of the two segments. * * @param segment the segment. * @throws IllegalArgumentException if the given segment is not in the same graph. */ public void connectBeginToEnd(SGraphSegment segment) { if (segment.getGraph() != getGraph()) { throw new IllegalArgumentException(); } final SGraphPoint point = new SGraphPoint(getGraph()); setBegin(point); segment.setEnd(point); final SGraph g = getGraph(); assert g != null; g.updatePointCount(-1); } /** Connect the end point of this segment to the * begin point of the given segment. * This function change the connection points of the two segments. * * @param segment the segment. * @throws IllegalArgumentException if the given segment is not in the same graph. */ public void connectEndToBegin(SGraphSegment segment) { if (segment.getGraph() != getGraph()) { throw new IllegalArgumentException(); } final SGraphPoint point = new SGraphPoint(getGraph()); setEnd(point); segment.setBegin(point); final SGraph g = getGraph(); assert g != null; g.updatePointCount(-1); } /** Connect the end point of this segment to the * end point of the given segment. * This function change the connection points of the two segments. * * @param segment the segment. * @throws IllegalArgumentException if the given segment is not in the samegraph. */ public void connectEndToEnd(SGraphSegment segment) { if (segment.getGraph() != getGraph()) { throw new IllegalArgumentException(); } final SGraphPoint point = new SGraphPoint(getGraph()); setEnd(point); segment.setEnd(point); final SGraph g = getGraph(); assert g != null; g.updatePointCount(-1); } /** Disconnect the begin point of this segment. */ public void disconnectBegin() { if (this.startPoint != null) { this.startPoint.remove(this); } this.startPoint = new SGraphPoint(getGraph()); this.startPoint.add(this); } /** Disconnect the end point of this segment. */ public void disconnectEnd() { if (this.endPoint != null) { this.endPoint.remove(this); } this.endPoint = new SGraphPoint(getGraph()); this.endPoint.add(this); } @Override public SGraphPoint getBeginPoint() { return this.startPoint; } @Pure @Override public SGraphPoint getEndPoint() { return this.endPoint; } @Pure @Override public SGraphPoint getOtherSidePoint(SGraphPoint point) { if (point != null) { if (point.equals(this.startPoint)) { return this.endPoint; } if (point.equals(this.endPoint)) { return this.startPoint; } } return null; } @Pure @Override public double getLength() { return this.length; } /** Set the length of the segment. * * @param length is the length of the segment. */ public void setLength(double length) { assert length >= 0. : AssertMessages.positiveOrZeroParameter(); this.length = length; } /** Add a user data in the data associated to this point. * * @param userData the user data to add. * @return <code>true</code> if the data was added; otherwise <code>false</code>. */ public boolean addUserData(Object userData) { if (this.userData == null) { this.userData = new ArrayList<>(); } return this.userData.add(userData); } /** Remove a user data from the data associated to this point. * * @param userData the user data to remove. * @return <code>true</code> if the data was removed; otherwise <code>false</code>. */ public boolean removeUserData(Object userData) { return this.userData != null && this.userData.remove(userData); } /** Replies the number of user data. * * @return the number of user data. */ @Pure public int getUserDataCount() { return (this.userData == null) ? 0 : this.userData.size(); } /** Replies the user data at the given index. * * @param index is the index of the data. * @return the data */ @Pure public Object getUserDataAt(int index) { if (this.userData == null) { throw new IndexOutOfBoundsException(); } return this.userData.get(index); } /** Set the user data at the given index. * * @param index is the index of the data. * @param data is the data */ public void setUserDataAt(int index, Object data) { if (this.userData == null) { throw new IndexOutOfBoundsException(); } this.userData.set(index, data); } /** Replies all the user data. * * @return an unmodifiable collection of user data. */ @Pure public Collection<Object> getAllUserData() { if (this.userData == null) { return Collections.emptyList(); } return Collections.unmodifiableCollection(this.userData); } }