001/* =========================================================== 002 * Orson Charts : a 3D chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C)opyright 2013-2022, by David Gilbert. All rights reserved. 006 * 007 * https://github.com/jfree/orson-charts 008 * 009 * This program is free software: you can redistribute it and/or modify 010 * it under the terms of the GNU General Public License as published by 011 * the Free Software Foundation, either version 3 of the License, or 012 * (at your option) any later version. 013 * 014 * This program is distributed in the hope that it will be useful, 015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 017 * GNU General Public License for more details. 018 * 019 * You should have received a copy of the GNU General Public License 020 * along with this program. If not, see <http://www.gnu.org/licenses/>. 021 * 022 * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. 023 * Other names may be trademarks of their respective owners.] 024 * 025 * If you do not wish to be bound by the terms of the GPL, an alternative 026 * commercial license can be purchased. For details, please see visit the 027 * Orson Charts home page: 028 * 029 * http://www.object-refinery.com/orsoncharts/index.html 030 * 031 */ 032 033package org.jfree.chart3d.marker; 034 035import java.awt.geom.Point2D; 036import java.util.Map; 037import java.util.HashMap; 038import org.jfree.chart3d.graphics2d.Anchor2D; 039import org.jfree.chart3d.internal.Args; 040 041/** 042 * A record holder for data relating to markers that needs to be passed 043 * to the 3D engine. 044 * 045 * @since 1.2 046 */ 047public class MarkerData { 048 049 /** 050 * The key used to store the marker on the axis. We can use this key 051 * to retrieve the actual marker to get the label, font, color etc. 052 */ 053 private String markerKey; 054 055 /** 056 * The type of marker data (value or range). A value marker will have 057 * a 'valueLine' stored in the data map. A range marker will have 058 * a 'startLine' and an 'endLine' stored in the data map. 059 */ 060 private MarkerDataType type; 061 062 /** Storage for data values (using a map for future expansion). */ 063 private Map<String, Object> data; 064 065 /** 066 * Creates marker data for the case where there is a single line 067 * (for example, the {@link NumberMarker} class). 068 * 069 * @param key the key for the marker ({@code null} not permitted). 070 * @param pos the relative position along the axis (in the range 0.0 to 071 * 1.0). 072 */ 073 public MarkerData(String key, double pos) { 074 Args.nullNotPermitted(key, "key"); 075 this.markerKey = key; 076 this.type = MarkerDataType.VALUE; 077 this.data = new HashMap<>(); 078 this.data.put("valueLine", new MarkerLine(pos, false)); 079 } 080 081 /** 082 * Creates marker data for the case where there are two lines. 083 * (for example, the {@link RangeMarker} class). 084 * 085 * @param key the key ({@code null} not permitted). 086 * @param startPos the relative start position. 087 * @param startPegged is the start position pegged? 088 * @param endPos the relative end position. 089 * @param endPegged is the end position pegged? 090 */ 091 public MarkerData(String key, double startPos, boolean startPegged, 092 double endPos, boolean endPegged) { 093 Args.nullNotPermitted(key, "key"); 094 this.markerKey = key; 095 this.type = MarkerDataType.RANGE; 096 this.data = new HashMap<>(); 097 this.data.put("startLine", new MarkerLine(startPos, startPegged)); 098 this.data.put("endLine", new MarkerLine(endPos, endPegged)); 099 } 100 101 /** 102 * Creates a new instance based on an existing source that has type 103 * {@code MarkerDataType.VALUE}. 104 * 105 * @param source the source ({@code null} not permitted). 106 * @param v0 the vertex index for the start of the line. 107 * @param v1 the vertex index for the end of the line. 108 */ 109 public MarkerData(MarkerData source, int v0, int v1) { 110 Args.nullNotPermitted(source, "source"); 111 if (!source.getType().equals(MarkerDataType.VALUE)) { 112 throw new IllegalArgumentException("Must be MarkerDataType.VALUE"); 113 } 114 this.markerKey = source.markerKey; 115 this.type = source.type; 116 this.data = new HashMap<>(source.data); 117 double pos = source.getValueLine().getPos(); 118 MarkerLine valueLine = new MarkerLine(pos, false, v0, v1); 119 this.data.put("valueLine", valueLine); 120 } 121 122 /** 123 * Creates a new instance based on an existing source that has type 124 * {@code MarkerDataType.Range}. 125 * 126 * @param source the source ({@code null} not permitted). 127 * @param v0 the vertex index for the start of the first line. 128 * @param v1 the vertex index for the end of the first line. 129 * @param v2 the vertex index for the start of the second line. 130 * @param v3 the vertex index for the end of the second line. 131 */ 132 public MarkerData(MarkerData source, int v0, int v1, int v2, int v3) { 133 Args.nullNotPermitted(source, "source"); 134 if (!source.getType().equals(MarkerDataType.RANGE)) { 135 throw new IllegalArgumentException("Must be MarkerDataType.RANGE"); 136 } 137 this.markerKey = source.markerKey; 138 this.type = MarkerDataType.RANGE; 139 this.data = new HashMap<>(source.data); 140 double startPos = source.getStartLine().getPos(); 141 boolean startPegged = source.getStartLine().isPegged(); 142 MarkerLine startLine = new MarkerLine(startPos, startPegged, v0, v1); 143 this.data.put("startLine", startLine); 144 double endPos = source.getEndLine().getPos(); 145 boolean endPegged = source.getEndLine().isPegged(); 146 MarkerLine endLine = new MarkerLine(endPos, endPegged, v2, v3); 147 this.data.put("endLine", endLine); 148 } 149 150 /** 151 * Returns the marker key (allows retrieval of the original marker object 152 * when required). 153 * 154 * @return The marker key (never {@code null}). 155 */ 156 public String getMarkerKey() { 157 return this.markerKey; 158 } 159 160 /** 161 * Returns the type of marker data (value or range). 162 * 163 * @return The type (never {@code null}). 164 */ 165 public MarkerDataType getType() { 166 return this.type; 167 } 168 169 /** 170 * A convenience method that returns the value line data for a value marker. 171 * 172 * @return The value line (or {@code null}). 173 */ 174 public MarkerLine getValueLine() { 175 return (MarkerLine) this.data.get("valueLine"); 176 } 177 178 /** 179 * A convenience method that returns the start line data for a range marker. 180 * 181 * @return The start line (or {@code null}). 182 */ 183 public MarkerLine getStartLine() { 184 return (MarkerLine) this.data.get("startLine"); 185 } 186 187 /** 188 * A convenience method that returns the end line data for a range marker. 189 * 190 * @return The end line (or {@code null}). 191 */ 192 public MarkerLine getEndLine() { 193 return (MarkerLine) this.data.get("endLine"); 194 } 195 196 /** 197 * Returns the label anchor. 198 * 199 * @return The label anchor. 200 */ 201 public Anchor2D getLabelAnchor() { 202 return (Anchor2D) this.data.get("labelAnchor"); 203 } 204 205 /** 206 * Sets the label anchor. 207 * 208 * @param anchor the label anchor. 209 */ 210 public void setLabelAnchor(Anchor2D anchor) { 211 this.data.put("labelAnchor", anchor); 212 } 213 214 /** 215 * Returns the label vertex index. 216 * 217 * @return The label vertex index. 218 */ 219 public int getLabelVertexIndex() { 220 Integer i = (Integer) this.data.get("labelVertexIndex"); 221 return (i != null ? i : -1); 222 } 223 224 /** 225 * Sets the label vertex index. 226 * 227 * @param labelVertexIndex the label vertex index. 228 */ 229 public void setLabelVertexIndex(int labelVertexIndex) { 230 this.data.put("labelVertexIndex", labelVertexIndex); 231 } 232 233 /** 234 * Returns the label projection point. 235 * 236 * @return The label projection point (possibly {@code null}). 237 */ 238 public Point2D getLabelPoint() { 239 return (Point2D) this.data.get("labelPoint"); 240 } 241 242 /** 243 * Updates the projected points for this marker. This needs to be done 244 * before the markers can be drawn. 245 * 246 * @param pts the projected points for the world. 247 */ 248 public void updateProjection(Point2D[] pts) { 249 if (this.type.equals(MarkerDataType.VALUE)) { 250 MarkerLine line = getValueLine(); 251 line.setStartPoint(pts[line.getV0()]); 252 line.setEndPoint(pts[line.getV1()]); 253 } else if (this.type.equals(MarkerDataType.RANGE)) { 254 MarkerLine startLine = getStartLine(); 255 startLine.setStartPoint(pts[startLine.getV0()]); 256 startLine.setEndPoint(pts[startLine.getV1()]); 257 MarkerLine endLine = getEndLine(); 258 endLine.setStartPoint(pts[endLine.getV0()]); 259 endLine.setEndPoint(pts[endLine.getV1()]); 260 } 261 int labelVertex = getLabelVertexIndex(); 262 if (labelVertex >= 0) { 263 this.data.put("labelPoint", pts[labelVertex]); 264 } else { 265 this.data.put("labelPoint", null); 266 } 267 } 268 269 @Override 270 public String toString() { 271 return "MarkerData[key=" + this.markerKey + "]"; 272 } 273}