001package jmri.jmrit.display.layoutEditor; 002 003/** 004 * Enum denoting the different behaviors of different 005 * types of "HitPoints". 006 * <p> 007 * Extracted from static in constants in LayoutEditor 008 * 009 * @author Dave Duchamp Copyright: (c) 2004-2007 010 * @author George Warner Copyright: (c) 2017-2019 011 * @author Bob Jacobsen Copyright: (c) 2020 012 */ 013 014public enum HitPointType { 015 // Historical numerical values, used in old files, now ordinals with tests 016 NONE, // 0 017 POS_POINT, // 1 018 TURNOUT_A, // 2 throat for RH, LH, and WYE turnouts 019 TURNOUT_B, // 3 continuing route for RH and LH turnouts 020 TURNOUT_C, // 4 diverging route for RH and LH turnouts 021 TURNOUT_D, // 5 4th route for crossovers 022 LEVEL_XING_A, // 6 023 LEVEL_XING_B, // 7 024 LEVEL_XING_C, // 8 025 LEVEL_XING_D, // 9 026 TRACK, // 10 027 TURNOUT_CENTER, // 11 non-connection points should be last 028 LEVEL_XING_CENTER, // 12 029 TURNTABLE_CENTER, // 13 030 LAYOUT_POS_LABEL, // 14 031 LAYOUT_POS_JCOMP, // 15 032 MULTI_SENSOR, // 16 033 MARKER, // 17 034 TRACK_CIRCLE_CENTRE, // 18 035 UNUSED_19, // 19 036 SLIP_CENTER, // 20 TODO: should be deprecated (use SLIP_LEFT & SLIP_RIGHT instead) 037 SLIP_A, // 21 038 SLIP_B, // 22 039 SLIP_C, // 23 040 SLIP_D, // 24 041 SLIP_LEFT, // 25 042 SLIP_RIGHT, // 26 043 UNUSED_27, // 27 044 UNUSED_28, // 28 045 UNUSED_29, // 29 046 BEZIER_CONTROL_POINT_0, // 30 offset for TrackSegment Bezier control points , minimum) 047 BEZIER_CONTROL_POINT_1, // 31 \ 048 BEZIER_CONTROL_POINT_2, // 32 \ 049 BEZIER_CONTROL_POINT_3, // 33 \ 050 BEZIER_CONTROL_POINT_4, // 34 } -- DON'T USE THESE; PLACEHOLDERS ONLY 051 BEZIER_CONTROL_POINT_5, // 35 / 052 BEZIER_CONTROL_POINT_6, // 36 / 053 BEZIER_CONTROL_POINT_7, // 37 / 054 BEZIER_CONTROL_POINT_8, // 38 offset for TrackSegment Bezier control points , maximum) 055 SHAPE_CENTER, // 39 056 SHAPE_POINT_0, // 40 offset for Shape points, minimum) 057 SHAPE_POINT_1, // 41 \ 058 SHAPE_POINT_2, // 42 \ 059 SHAPE_POINT_3, // 43 \ 060 SHAPE_POINT_4, // 44 \ __ DON'T USE THESE; PLACEHOLDERS ONLY 061 SHAPE_POINT_5, // 45 / 062 SHAPE_POINT_6, // 46 / 063 SHAPE_POINT_7, // 47 / 064 SHAPE_POINT_8, // 48 / 065 SHAPE_POINT_9, // 49 offset for Shape points , // maximum) 066 TURNTABLE_RAY_0, // 50 offset for turntable connection points , // minimum) 067 TURNTABLE_RAY_1, // 51 \ 068 TURNTABLE_RAY_2, // 52 \ 069 TURNTABLE_RAY_3, // 53 \ 070 TURNTABLE_RAY_4, // 54 \ 071 TURNTABLE_RAY_5, // 55 \ 072 TURNTABLE_RAY_6, // 56 \ 073 TURNTABLE_RAY_7, // 57 | 074 TURNTABLE_RAY_8, // 58 | 075 TURNTABLE_RAY_9, // 59 | 076 TURNTABLE_RAY_10, // 60 | 077 TURNTABLE_RAY_11, // 61 | 078 TURNTABLE_RAY_12, // 62 | 079 TURNTABLE_RAY_13, // 63 | 080 TURNTABLE_RAY_14, // 64 | 081 TURNTABLE_RAY_15, // 65 | 082 TURNTABLE_RAY_16, // 66 | 083 TURNTABLE_RAY_17, // 67 | 084 TURNTABLE_RAY_18, // 68 | 085 TURNTABLE_RAY_19, // 69 | 086 TURNTABLE_RAY_20, // 70 | 087 TURNTABLE_RAY_21, // 71 | 088 TURNTABLE_RAY_22, // 72 | 089 TURNTABLE_RAY_23, // 73 | 090 TURNTABLE_RAY_24, // 74 | 091 TURNTABLE_RAY_25, // 75 | 092 TURNTABLE_RAY_26, // 76 | 093 TURNTABLE_RAY_27, // 77 | 094 TURNTABLE_RAY_28, // 78 | 095 TURNTABLE_RAY_29, // 79 | 096 TURNTABLE_RAY_30, // 80 | 097 TURNTABLE_RAY_31, // 81 | 098 TURNTABLE_RAY_32, // 82 | 099 TURNTABLE_RAY_33, // 83 | 100 TURNTABLE_RAY_34, // 84 | 101 TURNTABLE_RAY_35, // 85 | 102 TURNTABLE_RAY_36, // 86 | 103 TURNTABLE_RAY_37, // 87 | 104 TURNTABLE_RAY_38, // 88 | 105 TURNTABLE_RAY_39, // 89 | 106 TURNTABLE_RAY_40, // 90 | 107 TURNTABLE_RAY_41, // 91 | 108 TURNTABLE_RAY_42, // 92 | 109 TURNTABLE_RAY_43, // 93 | 110 TURNTABLE_RAY_44, // 94 | 111 TURNTABLE_RAY_45, // 95 | -- DON'T USE THESE; PLACEHOLDERS ONLY 112 TURNTABLE_RAY_46, // 96 | 113 TURNTABLE_RAY_47, // 97 | 114 TURNTABLE_RAY_48, // 98 | 115 TURNTABLE_RAY_49, // 99 | 116 TURNTABLE_RAY_50, // 100 | 117 TURNTABLE_RAY_51, // 101 | 118 TURNTABLE_RAY_52, // 102 | 119 TURNTABLE_RAY_53, // 103 | 120 TURNTABLE_RAY_54, // 104 | 121 TURNTABLE_RAY_55, // 105 | 122 TURNTABLE_RAY_56, // 106 | 123 TURNTABLE_RAY_57, // 107 | 124 TURNTABLE_RAY_58, // 108 / 125 TURNTABLE_RAY_59, // 109 / 126 TURNTABLE_RAY_60, // 110 / 127 TURNTABLE_RAY_61, // 111 / 128 TURNTABLE_RAY_62, // 112 / 129 TURNTABLE_RAY_63; // 113 130 131 /** 132 * @param hitType the hit point type 133 * @return true if this is for a connection to a LayoutTrack 134 */ 135 protected static boolean isConnectionHitType(HitPointType hitType) { 136 switch (hitType) { 137 case POS_POINT: 138 case TURNOUT_A: 139 case TURNOUT_B: 140 case TURNOUT_C: 141 case TURNOUT_D: 142 case LEVEL_XING_A: 143 case LEVEL_XING_B: 144 case LEVEL_XING_C: 145 case LEVEL_XING_D: 146 case TRACK: 147 case SLIP_A: 148 case SLIP_B: 149 case SLIP_C: 150 case SLIP_D: 151 return true; // these are all connection types 152 case NONE: 153 case TURNOUT_CENTER: 154 case LEVEL_XING_CENTER: 155 case TURNTABLE_CENTER: 156 case LAYOUT_POS_LABEL: 157 case LAYOUT_POS_JCOMP: 158 case MULTI_SENSOR: 159 case MARKER: 160 case TRACK_CIRCLE_CENTRE: 161 case SLIP_CENTER: 162 case SLIP_LEFT: 163 case SLIP_RIGHT: 164 return false; // these are not 165 default: 166 break; 167 } 168 if (isBezierHitType(hitType)) { 169 return false; // these are not 170 } else if (isTurntableRayHitType(hitType)) { 171 return true; // these are all connection types 172 } 173 return false; // This is unexpected 174 } 175 176 /** 177 * @param hitType the hit point type 178 * @return true if this hit type is for a layout control 179 */ 180 protected static boolean isControlHitType(HitPointType hitType) { 181 switch (hitType) { 182 case TURNOUT_CENTER: 183 case SLIP_CENTER: 184 case SLIP_LEFT: 185 case SLIP_RIGHT: 186 return true; // these are all control types 187 case POS_POINT: 188 case TURNOUT_A: 189 case TURNOUT_B: 190 case TURNOUT_C: 191 case TURNOUT_D: 192 case LEVEL_XING_A: 193 case LEVEL_XING_B: 194 case LEVEL_XING_C: 195 case LEVEL_XING_D: 196 case TRACK: 197 case SLIP_A: 198 case SLIP_B: 199 case SLIP_C: 200 case SLIP_D: 201 case NONE: 202 case LEVEL_XING_CENTER: 203 case TURNTABLE_CENTER: 204 case LAYOUT_POS_LABEL: 205 case LAYOUT_POS_JCOMP: 206 case MULTI_SENSOR: 207 case MARKER: 208 case TRACK_CIRCLE_CENTRE: 209 return false; // these are not 210 default: 211 break; 212 } 213 if (isBezierHitType(hitType)) { 214 return false; // these are not control types 215 } else if (isTurntableRayHitType(hitType)) { 216 return true; // these are all control types 217 } 218 return false; // This is unexpected 219 } 220 221 protected static boolean isTurnoutHitType(HitPointType hitType) { 222 return (hitType.compareTo(HitPointType.TURNOUT_A) >= 0) && (hitType.compareTo(HitPointType.TURNOUT_D) <= 0); 223 } 224 225 protected static boolean isSlipHitType(HitPointType hitType) { 226 return (hitType.compareTo(HitPointType.SLIP_A) >= 0) && (hitType.compareTo(HitPointType.SLIP_RIGHT) <= 0); 227 } 228 229 protected static boolean isBezierHitType(HitPointType hitType) { 230 return (hitType.compareTo(HitPointType.BEZIER_CONTROL_POINT_0) >= 0) && (hitType.compareTo(HitPointType.BEZIER_CONTROL_POINT_8) <= 0); 231 } 232 233 protected static boolean isLevelXingHitType(HitPointType hitType) { 234 return (hitType.compareTo(HitPointType.LEVEL_XING_A) >= 0) && (hitType.compareTo(HitPointType.LEVEL_XING_D) <= 0); 235 } 236 237 protected static boolean isTurntableRayHitType(HitPointType hitType) { 238 return (hitType.compareTo(HitPointType.TURNTABLE_RAY_0) >= 0) && (hitType.compareTo(HitPointType.TURNTABLE_RAY_63) <= 0); 239 } 240 241 /** 242 * @param hitType the hit point type 243 * @return true if this is for a popup menu 244 */ 245 protected static boolean isPopupHitType(HitPointType hitType) { 246 switch (hitType) { 247 case LEVEL_XING_CENTER: 248 case POS_POINT: 249 case SLIP_CENTER: 250 case SLIP_LEFT: 251 case SLIP_RIGHT: 252 case TRACK: 253 case TRACK_CIRCLE_CENTRE: 254 case TURNOUT_CENTER: 255 case TURNTABLE_CENTER: 256 return true; 257 case LAYOUT_POS_JCOMP: 258 case LAYOUT_POS_LABEL: 259 case LEVEL_XING_A: 260 case LEVEL_XING_B: 261 case LEVEL_XING_C: 262 case LEVEL_XING_D: 263 case MARKER: 264 case MULTI_SENSOR: 265 case NONE: 266 case SLIP_A: 267 case SLIP_B: 268 case SLIP_C: 269 case SLIP_D: 270 case TURNOUT_A: 271 case TURNOUT_B: 272 case TURNOUT_C: 273 case TURNOUT_D: 274 return false; // these are not 275 default: 276 break; 277 } 278 if (isBezierHitType(hitType)) { 279 return true; // these are all popup hit types 280 } else if (isTurntableRayHitType(hitType)) { 281 return true; // these are all popup hit types 282 } 283 return false; 284 } 285 286 // ***************************************************************** 287 // TURNTABLE_RAY support 288 // ***************************************************************** 289 /** 290 * Find the 0-63 index with respect to TURNTABLE_RAY_0 291 * of a given enum entry. Throws {@link IllegalArgumentException} if 292 * the given enum value isn't one of the TURNTABLE_RAY_n entries. 293 * <p> 294 * Ideally, this would be replaced by turntable code that works 295 * directly with the enum values as a step toward using objects 296 * to implement hit points. 297 * @return (Temporary) 0-63 index of the enum element 298 */ 299 protected int turntableTrackIndex() { 300 int result = this.ordinal() - HitPointType.TURNTABLE_RAY_0.ordinal(); 301 if (result < 0) { 302 throw new IllegalArgumentException(this.toString() + " is not a valid TURNTABLE_RAY"); 303 } 304 if (result > 63) { 305 throw new IllegalArgumentException(this.toString() + " is not a valid TURNTABLE_RAY"); 306 } 307 return result; 308 } 309 310 /** 311 * Return a specific TURNTABLE_RAY from its 0-63 index. 312 * Throws {@link IllegalArgumentException} if 313 * the given index value isn't valid for the TURNTABLE_RAY entries. 314 * <p> 315 * Ideally, this would be replaced by turntable code that works 316 * directly with the enum values as a step toward using objects 317 * to implement hit points. 318 * @param i (Temporary) 0-63 index of the enum element 319 * @return Requested enum element 320 */ 321 protected static HitPointType turntableTrackIndexedValue(int i) { 322 if (i < 0 || i > 63) { 323 throw new IllegalArgumentException(i + " is not a valid TURNTABLE_RAY index"); 324 } 325 return HitPointType.values()[(TURNTABLE_RAY_0.ordinal() + i)]; 326 } 327 328 /** 329 * Return an array of the valid TURNTABLE_RAY enum values. 330 * Meant for interations over the set of rays. Order is 331 * from 0 to 63. 332 * @return (Temporary) Array containing TURNTABLE_RAY_0 through TURNTABLE_RAY_63 333 */ 334 protected static HitPointType[] turntableValues() { 335 return new HitPointType[]{TURNTABLE_RAY_0, TURNTABLE_RAY_1, TURNTABLE_RAY_2, TURNTABLE_RAY_3, TURNTABLE_RAY_4, TURNTABLE_RAY_5, TURNTABLE_RAY_6, TURNTABLE_RAY_7, TURNTABLE_RAY_8, TURNTABLE_RAY_9, TURNTABLE_RAY_10, TURNTABLE_RAY_11, TURNTABLE_RAY_12, TURNTABLE_RAY_13, TURNTABLE_RAY_14, TURNTABLE_RAY_15, TURNTABLE_RAY_16, TURNTABLE_RAY_17, TURNTABLE_RAY_18, TURNTABLE_RAY_19, TURNTABLE_RAY_20, TURNTABLE_RAY_21, TURNTABLE_RAY_22, TURNTABLE_RAY_23, TURNTABLE_RAY_24, TURNTABLE_RAY_25, TURNTABLE_RAY_26, TURNTABLE_RAY_27, TURNTABLE_RAY_28, TURNTABLE_RAY_29, TURNTABLE_RAY_30, TURNTABLE_RAY_31, TURNTABLE_RAY_32, TURNTABLE_RAY_33, TURNTABLE_RAY_34, TURNTABLE_RAY_35, TURNTABLE_RAY_36, TURNTABLE_RAY_37, TURNTABLE_RAY_38, TURNTABLE_RAY_39, TURNTABLE_RAY_40, TURNTABLE_RAY_41, TURNTABLE_RAY_42, TURNTABLE_RAY_43, TURNTABLE_RAY_44, TURNTABLE_RAY_45, TURNTABLE_RAY_46, TURNTABLE_RAY_47, TURNTABLE_RAY_48, TURNTABLE_RAY_49, TURNTABLE_RAY_50, TURNTABLE_RAY_51, TURNTABLE_RAY_52, TURNTABLE_RAY_53, TURNTABLE_RAY_54, TURNTABLE_RAY_55, TURNTABLE_RAY_56, TURNTABLE_RAY_57, TURNTABLE_RAY_58, TURNTABLE_RAY_59, TURNTABLE_RAY_60, TURNTABLE_RAY_61, TURNTABLE_RAY_62, TURNTABLE_RAY_63}; 336 } 337 338 // ***************************************************************** 339 // SHAPE_POINT support 340 // ***************************************************************** 341 /** 342 * Find the 0-9 index with respect to SHAPE_POINT_0 343 * of a given enum entry. Throws {@link IllegalArgumentException} if 344 * the given enum value isn't one of the SHAPE_POINT_n entries. 345 * <p> 346 * Ideally, this would be replaced by shape code that works 347 * directly with the enum values as a step toward using objects 348 * to implement hit points. 349 * @return (Temporary) 0-9 index of the enum element 350 */ 351 protected int shapePointIndex() { 352 int result = this.ordinal() - HitPointType.SHAPE_POINT_0.ordinal(); 353 if (result < 0) { 354 throw new IllegalArgumentException(this.toString() + " is not a valid SHAPE_POINT"); 355 } 356 if (result > 9) { 357 throw new IllegalArgumentException(this.toString() + " is not a valid SHAPE_POINT"); 358 } 359 return result; 360 } 361 362 /** 363 * Return a specific SHAPE_POINT from its 0-9 index. 364 * Throws {@link IllegalArgumentException} if 365 * the given index value isn't valid for the SHAPE_POINT entries. 366 * <p> 367 * Ideally, this would be replaced by shape code that works 368 * directly with the enum values as a step toward using objects 369 * to implement hit points. 370 * @param i (Temporary) 0-9 index of the enum element 371 * @return Requested enum element 372 */ 373 protected static HitPointType shapePointIndexedValue(int i) { 374 if (i < 0 || i > 9) { 375 throw new IllegalArgumentException(i + " is not a valid SHAPE_POINT index"); 376 } 377 return HitPointType.values()[(SHAPE_POINT_0.ordinal() + i)]; 378 } 379 380 /** 381 * Return an array of the valid SHAPE_POINT enum values. 382 * Meant for interations over the set of points. Order is 383 * from 0 to 9. 384 * @return (Temporary) Array containing SHAPE_POINT_0 through SHAPE_POINT_9 385 */ 386 protected static HitPointType[] shapePointValues() { 387 return new HitPointType[]{SHAPE_POINT_0, SHAPE_POINT_1, SHAPE_POINT_2, SHAPE_POINT_3, SHAPE_POINT_4, SHAPE_POINT_5, SHAPE_POINT_6, SHAPE_POINT_7, SHAPE_POINT_8, SHAPE_POINT_9}; 388 } 389 390 protected static boolean isShapePointOffsetHitPointType(HitPointType t) { 391 return (t.compareTo(SHAPE_POINT_0) >= 0) && (t.compareTo(SHAPE_POINT_9) <= 0); 392 } 393 // limited use, remove? 394 public static final int NUM_SHAPE_POINTS = 10; 395 396 // ***************************************************************** 397 // BEZIER_CONTROL_POINT support 398 // ***************************************************************** 399 /** 400 * Find the 0-8 index with respect to BEZIER_CONTROL_POINT_0 401 * of this enum entry. Throws {@link IllegalArgumentException} if 402 * the enum value isn't one of the BEZIER_CONTROL_POINT_n entries. 403 * <p> 404 * Ideally, this would be replaced by bezier code that works 405 * directly with the enum values as a step toward using objects 406 * to implement hit points. 407 * @return (Temporary) 0-8 index of this enum 408 */ 409 protected int bezierPointIndex() { 410 int result = this.ordinal() - HitPointType.BEZIER_CONTROL_POINT_0.ordinal(); 411 if (result < 0) { 412 throw new IllegalArgumentException(this.toString() + " is not a valid BEZIER_CONTROL_POINT"); 413 } 414 if (result > 8) { 415 throw new IllegalArgumentException(this.toString() + " is not a valid BEZIER_CONTROL_POINT"); 416 } 417 return result; 418 } 419 420 /** 421 * Return a specific BEZIER_CONTROL_POINT from its 0-8 index. 422 * Throws {@link IllegalArgumentException} if 423 * the given index value isn't valid for the SHAPE_POINT entries. 424 * <p> 425 * Ideally, this would be replaced by shape code that works 426 * directly with the enum values as a step toward using objects 427 * to implement hit points. 428 * @param i (Temporary) 0-8 index of the enum element 429 * @return Requested enum element 430 */ 431 protected static HitPointType bezierPointIndexedValue(int i) { 432 if (i < 0 || i > 8) { 433 throw new IllegalArgumentException(i + " is not a valid BEZIER_CONTROL_POINT index"); 434 } 435 return HitPointType.values()[(BEZIER_CONTROL_POINT_0.ordinal() + i)]; 436 } 437 // limited use, remove? 438 public static final int NUM_BEZIER_CONTROL_POINTS = 9; 439 440}