fr.arakne.utils.maps.sight.NotAlignedLineOfSightIterator   A
last analyzed

Complexity

Total Complexity 10

Size/Duplication

Total Lines 83
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 46
c 1
b 0
f 0
dl 0
loc 83
ccs 29
cts 29
cp 1
rs 10
wmc 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A getCurrentCell() 0 2 1
A computeNextY() 0 11 2
A hasNext() 0 3 1
A next() 0 13 2
A init() 0 5 1
A NotAlignedLineOfSightIterator(BattlefieldSight,CoordinateCell,CoordinateCell) 0 11 3
1
/*
2
 * This file is part of ArakneUtils.
3
 *
4
 * ArakneUtils is free software: you can redistribute it and/or modify
5
 * it under the terms of the GNU Lesser General Public License as published by
6
 * the Free Software Foundation, either version 3 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * ArakneUtils is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU Lesser General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU Lesser General Public License
15
 * along with ArakneUtils.  If not, see <https://www.gnu.org/licenses/>.
16
 *
17
 * Copyright (c) 2017-2021 Vincent Quatrevieux
18
 */
19
20
package fr.arakne.utils.maps.sight;
21
22
import fr.arakne.utils.maps.BattlefieldCell;
23
import fr.arakne.utils.maps.CoordinateCell;
24
import org.checkerframework.checker.nullness.qual.NonNull;
25
26
import java.util.Iterator;
27
28
/**
29
 * Iterate between cells of the line of sight of two not aligned cells
30
 *
31
 * @param <C> The cell type
32
 */
33
final class NotAlignedLineOfSightIterator<C extends @NonNull BattlefieldCell> implements Iterator<C> {
34
    private final BattlefieldSight<C> battlefield;
35
    private final CoordinateCell<C> source;
36
    private final CoordinateCell<C> target;
37
38
    private final int xDirection;
39
    private final int yDirection;
40
    private final double ySlope;
41
    private final double yAtZero;
42
43
    private int currentX;
44
    private int currentY;
45
46
    private int lastY;
47
    private int nextY;
48
49 1
    public NotAlignedLineOfSightIterator(BattlefieldSight<C> battlefield, CoordinateCell<C> source, CoordinateCell<C> target) {
50 1
        this.battlefield = battlefield;
51 1
        this.source = source;
52 1
        this.target = target;
53
54 1
        this.xDirection = source.x() > target.x() ? -1 : 1;
55 1
        this.yDirection = source.y() > target.y() ? -1 : 1;
56 1
        this.ySlope = (double) (target.y() - source.y()) / (double) (target.x() - source.x());
57 1
        this.yAtZero = source.y() - ySlope * source.x();
58
59 1
        init();
60 1
    }
61
62
    @Override
63
    public boolean hasNext() {
64 1
        return !target.is(currentX, currentY);
65
    }
66
67
    @Override
68
    public C next() {
0 ignored issues
show
Bug introduced by
Iteration beyond the the end of a collection should throw a NoSuchElementException.
Loading history...
69 1
        currentY += yDirection;
70
71
        // lastY is exceeded : increment the X value
72 1
        if (currentY * yDirection > lastY * yDirection) {
73 1
            currentX += xDirection;
74 1
            currentY = nextY;
75
76 1
            computeNextY();
77
        }
78
79 1
        return getCurrentCell();
80
    }
81
82
    /**
83
     * Initialise iterator
84
     */
85
    private void init() {
86 1
        currentX = source.x();
87 1
        currentY = source.y();
88
89 1
        computeNextY();
90 1
    }
91
92
    /**
93
     * Compute the target Y coordinate for the current X value
94
     * The value lastY is used as ending boundary for the Y coordinate iteration
95
     * The value nextY is used as start boundary for the Y coordinate iteration for the next X value
96
     */
97
    private void computeNextY() {
98
        // yMax is the value of Y at the current X
99
        // + 0.5 permit to ignore cells around the line of sight on diagonal (i.e. ySlope = 1)
100 1
        final double yAtCurrentX = (currentX + xDirection * 0.5) * ySlope + yAtZero;
101
102 1
        if (yDirection > 0) {
103 1
            nextY = (int) Math.round(yAtCurrentX);
104 1
            lastY = (int) Math.ceil(yAtCurrentX - 0.5);
105
        } else {
106 1
            nextY = (int) Math.ceil(yAtCurrentX - 0.5);
107 1
            lastY = (int) Math.round(yAtCurrentX);
108
        }
109 1
    }
110
111
    /**
112
     * @return The cell on the current coordinates
113
     */
114
    private C getCurrentCell() {
115 1
        return battlefield.getCellByCoordinates(currentX, currentY);
116
    }
117
}
118