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 BLOCKCONTENTSICON; 131 132 /** 133 * @param hitType the hit point type 134 * @return true if this is for a connection to a LayoutTrack 135 */ 136 protected static boolean isConnectionHitType(HitPointType hitType) { 137 switch (hitType) { 138 case POS_POINT: 139 case TURNOUT_A: 140 case TURNOUT_B: 141 case TURNOUT_C: 142 case TURNOUT_D: 143 case LEVEL_XING_A: 144 case LEVEL_XING_B: 145 case LEVEL_XING_C: 146 case LEVEL_XING_D: 147 case TRACK: 148 case SLIP_A: 149 case SLIP_B: 150 case SLIP_C: 151 case SLIP_D: 152 return true; // these are all connection types 153 case NONE: 154 case TURNOUT_CENTER: 155 case LEVEL_XING_CENTER: 156 case TURNTABLE_CENTER: 157 case LAYOUT_POS_LABEL: 158 case LAYOUT_POS_JCOMP: 159 case MULTI_SENSOR: 160 case MARKER: 161 case TRACK_CIRCLE_CENTRE: 162 case SLIP_CENTER: 163 case SLIP_LEFT: 164 case SLIP_RIGHT: 165 return false; // these are not 166 default: 167 break; 168 } 169 if (isBezierHitType(hitType)) { 170 return false; // these are not 171 } else if (isTurntableRayHitType(hitType)) { 172 return true; // these are all connection types 173 } 174 return false; // This is unexpected 175 } 176 177 /** 178 * @param hitType the hit point type 179 * @return true if this hit type is for a layout control 180 */ 181 protected static boolean isControlHitType(HitPointType hitType) { 182 switch (hitType) { 183 case TURNOUT_CENTER: 184 case SLIP_CENTER: 185 case SLIP_LEFT: 186 case SLIP_RIGHT: 187 return true; // these are all control types 188 case POS_POINT: 189 case TURNOUT_A: 190 case TURNOUT_B: 191 case TURNOUT_C: 192 case TURNOUT_D: 193 case LEVEL_XING_A: 194 case LEVEL_XING_B: 195 case LEVEL_XING_C: 196 case LEVEL_XING_D: 197 case TRACK: 198 case SLIP_A: 199 case SLIP_B: 200 case SLIP_C: 201 case SLIP_D: 202 case NONE: 203 case LEVEL_XING_CENTER: 204 case TURNTABLE_CENTER: 205 case LAYOUT_POS_LABEL: 206 case LAYOUT_POS_JCOMP: 207 case MULTI_SENSOR: 208 case MARKER: 209 case TRACK_CIRCLE_CENTRE: 210 return false; // these are not 211 default: 212 break; 213 } 214 if (isBezierHitType(hitType)) { 215 return false; // these are not control types 216 } else if (isTurntableRayHitType(hitType)) { 217 return true; // these are all control types 218 } 219 return false; // This is unexpected 220 } 221 222 protected static boolean isTurnoutHitType(HitPointType hitType) { 223 return (hitType.compareTo(HitPointType.TURNOUT_A) >= 0) && (hitType.compareTo(HitPointType.TURNOUT_D) <= 0); 224 } 225 226 protected static boolean isSlipHitType(HitPointType hitType) { 227 return (hitType.compareTo(HitPointType.SLIP_A) >= 0) && (hitType.compareTo(HitPointType.SLIP_RIGHT) <= 0); 228 } 229 230 protected static boolean isBezierHitType(HitPointType hitType) { 231 return (hitType.compareTo(HitPointType.BEZIER_CONTROL_POINT_0) >= 0) && (hitType.compareTo(HitPointType.BEZIER_CONTROL_POINT_8) <= 0); 232 } 233 234 protected static boolean isLevelXingHitType(HitPointType hitType) { 235 return (hitType.compareTo(HitPointType.LEVEL_XING_A) >= 0) && (hitType.compareTo(HitPointType.LEVEL_XING_D) <= 0); 236 } 237 238 protected static boolean isTurntableRayHitType(HitPointType hitType) { 239 return (hitType.compareTo(HitPointType.TURNTABLE_RAY_0) >= 0) && (hitType.compareTo(HitPointType.TURNTABLE_RAY_63) <= 0); 240 } 241 242 /** 243 * @param hitType the hit point type 244 * @return true if this is for a popup menu 245 */ 246 protected static boolean isPopupHitType(HitPointType hitType) { 247 switch (hitType) { 248 case LEVEL_XING_CENTER: 249 case POS_POINT: 250 case SLIP_CENTER: 251 case SLIP_LEFT: 252 case SLIP_RIGHT: 253 case TRACK: 254 case TRACK_CIRCLE_CENTRE: 255 case TURNOUT_CENTER: 256 case TURNTABLE_CENTER: 257 return true; 258 case LAYOUT_POS_JCOMP: 259 case LAYOUT_POS_LABEL: 260 case LEVEL_XING_A: 261 case LEVEL_XING_B: 262 case LEVEL_XING_C: 263 case LEVEL_XING_D: 264 case MARKER: 265 case MULTI_SENSOR: 266 case NONE: 267 case SLIP_A: 268 case SLIP_B: 269 case SLIP_C: 270 case SLIP_D: 271 case TURNOUT_A: 272 case TURNOUT_B: 273 case TURNOUT_C: 274 case TURNOUT_D: 275 return false; // these are not 276 default: 277 break; 278 } 279 if (isBezierHitType(hitType)) { 280 return true; // these are all popup hit types 281 } else if (isTurntableRayHitType(hitType)) { 282 return true; // these are all popup hit types 283 } 284 return false; 285 } 286 287 // ***************************************************************** 288 // TURNTABLE_RAY support 289 // ***************************************************************** 290 /** 291 * Find the 0-63 index with respect to TURNTABLE_RAY_0 292 * of a given enum entry. Throws {@link IllegalArgumentException} if 293 * the given enum value isn't one of the TURNTABLE_RAY_n entries. 294 * <p> 295 * Ideally, this would be replaced by turntable code that works 296 * directly with the enum values as a step toward using objects 297 * to implement hit points. 298 * @return (Temporary) 0-63 index of the enum element 299 */ 300 protected int turntableTrackIndex() { 301 int result = this.ordinal() - HitPointType.TURNTABLE_RAY_0.ordinal(); 302 if (result < 0) { 303 throw new IllegalArgumentException(this.toString() + " is not a valid TURNTABLE_RAY"); 304 } 305 if (result > 63) { 306 throw new IllegalArgumentException(this.toString() + " is not a valid TURNTABLE_RAY"); 307 } 308 return result; 309 } 310 311 /** 312 * Return a specific TURNTABLE_RAY from its 0-63 index. 313 * Throws {@link IllegalArgumentException} if 314 * the given index value isn't valid for the TURNTABLE_RAY entries. 315 * <p> 316 * Ideally, this would be replaced by turntable code that works 317 * directly with the enum values as a step toward using objects 318 * to implement hit points. 319 * @param i (Temporary) 0-63 index of the enum element 320 * @return Requested enum element 321 */ 322 protected static HitPointType turntableTrackIndexedValue(int i) { 323 if (i < 0 || i > 63) { 324 throw new IllegalArgumentException(i + " is not a valid TURNTABLE_RAY index"); 325 } 326 return HitPointType.values()[(TURNTABLE_RAY_0.ordinal() + i)]; 327 } 328 329 /** 330 * Return an array of the valid TURNTABLE_RAY enum values. 331 * Meant for interations over the set of rays. Order is 332 * from 0 to 63. 333 * @return (Temporary) Array containing TURNTABLE_RAY_0 through TURNTABLE_RAY_63 334 */ 335 protected static HitPointType[] turntableValues() { 336 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}; 337 } 338 339 // ***************************************************************** 340 // SHAPE_POINT support 341 // ***************************************************************** 342 /** 343 * Find the 0-9 index with respect to SHAPE_POINT_0 344 * of a given enum entry. Throws {@link IllegalArgumentException} if 345 * the given enum value isn't one of the SHAPE_POINT_n entries. 346 * <p> 347 * Ideally, this would be replaced by shape code that works 348 * directly with the enum values as a step toward using objects 349 * to implement hit points. 350 * @return (Temporary) 0-9 index of the enum element 351 */ 352 protected int shapePointIndex() { 353 int result = this.ordinal() - HitPointType.SHAPE_POINT_0.ordinal(); 354 if (result < 0) { 355 throw new IllegalArgumentException(this.toString() + " is not a valid SHAPE_POINT"); 356 } 357 if (result > 9) { 358 throw new IllegalArgumentException(this.toString() + " is not a valid SHAPE_POINT"); 359 } 360 return result; 361 } 362 363 /** 364 * Return a specific SHAPE_POINT from its 0-9 index. 365 * Throws {@link IllegalArgumentException} if 366 * the given index value isn't valid for the SHAPE_POINT entries. 367 * <p> 368 * Ideally, this would be replaced by shape code that works 369 * directly with the enum values as a step toward using objects 370 * to implement hit points. 371 * @param i (Temporary) 0-9 index of the enum element 372 * @return Requested enum element 373 */ 374 protected static HitPointType shapePointIndexedValue(int i) { 375 if (i < 0 || i > 9) { 376 throw new IllegalArgumentException(i + " is not a valid SHAPE_POINT index"); 377 } 378 return HitPointType.values()[(SHAPE_POINT_0.ordinal() + i)]; 379 } 380 381 /** 382 * Return an array of the valid SHAPE_POINT enum values. 383 * Meant for interations over the set of points. Order is 384 * from 0 to 9. 385 * @return (Temporary) Array containing SHAPE_POINT_0 through SHAPE_POINT_9 386 */ 387 protected static HitPointType[] shapePointValues() { 388 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}; 389 } 390 391 protected static boolean isShapePointOffsetHitPointType(HitPointType t) { 392 return (t.compareTo(SHAPE_POINT_0) >= 0) && (t.compareTo(SHAPE_POINT_9) <= 0); 393 } 394 // limited use, remove? 395 public static final int NUM_SHAPE_POINTS = 10; 396 397 // ***************************************************************** 398 // BEZIER_CONTROL_POINT support 399 // ***************************************************************** 400 /** 401 * Find the 0-8 index with respect to BEZIER_CONTROL_POINT_0 402 * of this enum entry. Throws {@link IllegalArgumentException} if 403 * the enum value isn't one of the BEZIER_CONTROL_POINT_n entries. 404 * <p> 405 * Ideally, this would be replaced by bezier code that works 406 * directly with the enum values as a step toward using objects 407 * to implement hit points. 408 * @return (Temporary) 0-8 index of this enum 409 */ 410 protected int bezierPointIndex() { 411 int result = this.ordinal() - HitPointType.BEZIER_CONTROL_POINT_0.ordinal(); 412 if (result < 0) { 413 throw new IllegalArgumentException(this.toString() + " is not a valid BEZIER_CONTROL_POINT"); 414 } 415 if (result > 8) { 416 throw new IllegalArgumentException(this.toString() + " is not a valid BEZIER_CONTROL_POINT"); 417 } 418 return result; 419 } 420 421 /** 422 * Return a specific BEZIER_CONTROL_POINT from its 0-8 index. 423 * Throws {@link IllegalArgumentException} if 424 * the given index value isn't valid for the SHAPE_POINT entries. 425 * <p> 426 * Ideally, this would be replaced by shape code that works 427 * directly with the enum values as a step toward using objects 428 * to implement hit points. 429 * @param i (Temporary) 0-8 index of the enum element 430 * @return Requested enum element 431 */ 432 protected static HitPointType bezierPointIndexedValue(int i) { 433 if (i < 0 || i > 8) { 434 throw new IllegalArgumentException(i + " is not a valid BEZIER_CONTROL_POINT index"); 435 } 436 return HitPointType.values()[(BEZIER_CONTROL_POINT_0.ordinal() + i)]; 437 } 438 // limited use, remove? 439 public static final int NUM_BEZIER_CONTROL_POINTS = 9; 440 441}