1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369
|
/**
* Les traits permettants de créer un équipement
*/
public class EquipmentLine implements Serializable {
private static final long serialVersionUID = 1L;
private float xStart;
private float yStart;
private float xEnd;
private float yEnd;
private EquipmentLine lineAtStart;
private EquipmentLine lineAtEnd;
private float thickness;
private transient float [][] pointsCache;
/**
* Création de lignes depuis (<code>xStart</code>,<code>yStart</code>)
* to (<code>xEnd</code>, <code>yEnd</code>), avec une épaiseur donnée
*/
public EquipmentLine(float xStart, float yStart, float xEnd, float yEnd, float thickness) {
this.xStart = xStart;
this.yStart = yStart;
this.xEnd = xEnd;
this.yEnd = yEnd;
this.thickness = thickness;
}
/**
* Créations de lignes depuis une ligne donnée
*/
public EquipmentLine(EquipmentLine line) {
this(line.getXStart(), line.getYStart(),
line.getXEnd(), line.getYEnd(), line.getEquipmentThickness());
}
/**
* Renvoie le point d'abscisse de début de ce trait
*/
public float getXStart() {
return this.xStart;
}
/**
* Modifie le point d'abscisse de début de ce trait
*/
void setXStart(float xStart) {
this.xStart = xStart;
System.out.println("EquipmentLine setXStart "+xStart);
clearPointsCache();
}
/**
* Renvoie le point d'ordonnée de début de ce trait
*/
public float getYStart() {
return this.yStart;
}
/**
* Modifie le point d'ordonnée de début de ce trait
*/
void setYStart(float yStart) {
this.yStart = yStart;
System.out.println("EquipmentLine setYStart "+yStart);
clearPointsCache();
}
/**
* Renvoie le point d'abscisse de fin de ce trait
*/
public float getXEnd() {
return this.xEnd;
}
/**
* Modifie le point d'abscisse de fin de ce trait
*/
void setXEnd(float xEnd) {
this.xEnd = xEnd;
System.out.println("EquipmentLine setXEnd "+xEnd);
clearPointsCache();
}
/**
* Renvoie le point d'ordonnée de fin de ce trait
*/
public float getYEnd() {
return this.yEnd;
}
/**
* Modifie le point d'ordonnée de fin de ce trait
*/
void setYEnd(float yEnd) {
this.yEnd = yEnd;
System.out.println("EquipmentLine setYEnd "+yEnd);
clearPointsCache();
}
/**
* Renvoie le trait joint à ce trait au point de début
*/
public EquipmentLine getEquipmentLineAtStart() {
return this.lineAtStart;
}
/**
* Modifie le trait joint à ce trait au point de début
* cette methode ne peut être appeller uniquement par {@link Slip}
* avec une notification lorsque le trait à été modifié
*/
void setEquipmentLineAtStart(EquipmentLine lineAtStart) {
this.lineAtStart = lineAtStart;
clearPointsCache();
}
/**
* Renvoie le trait joint à ce trait au point de fin
*/
public EquipmentLine getEquipmentLineAtEnd() {
return this.lineAtEnd;
}
/**
* Modifie le trait joint à ce trait au point de fin
* cette methode ne peut être appeller uniquement par {@link Slip}
* avec une notification lorsque le trait à été modifié
*/
void setEquipmentLineAtEnd(EquipmentLine lineAtEnd) {
this.lineAtEnd = lineAtEnd;
clearPointsCache();
}
/**
* Renvoie l'épaisseur du trait
*/
public float getEquipmentThickness() {
return this.thickness;
}
/**
* Set wall thickness.
* This method should be called only from {@link Home}, which
* controls notifications when a wall changed.
*/
void setEquipmentThickness(float thickness) {
this.thickness = thickness;
clearPointsCache();
}
/**
* Clears the points cache of this line and of the lines attached to it.
*/
private void clearPointsCache() {
this.pointsCache = null;
if (this.lineAtStart != null ) {
this.lineAtStart.pointsCache = null;
}
if (this.lineAtEnd != null) {
this.lineAtEnd.pointsCache = null;
}
}
/**
* Renvoie les coordonées des quatres points
* décrivant le contour de ce trait
* @return an array of the 4 (x,y) coordinates of the line corners.
*/
public float [][] getPoints() {
if (this.pointsCache == null) {
//Calcul des points du contour du rectangle de ce trait
float [][] linePoints = getRectanglePoints();
float limit = 2 * this.thickness;
// Si le trait est joint à son extremité de départ
// à un autre trait lineAtStart....
if (this.lineAtStart != null) {
float [][] lineAtStartPoints = this.lineAtStart.getRectanglePoints();
// Si le trait lineAtStart est joint à ce trait
// à son extremité de fin....
if (this.lineAtStart.getEquipmentLineAtEnd() == this) {
//....calcul de l'intersection POi de la ligne
//(P0,P1) du trait avec la ligne(P1,P0) du trait
// lineAtStart, et de l'intersection P3i de la ligne
//(P3,P2) de cetrait avec la ligne (P2,P3)
//du trait lineAtStart...
computeIntersection(linePoints [0], linePoints [1],
lineAtStartPoints [1], lineAtStartPoints [0], limit);
computeIntersection(linePoints [3], linePoints [2],
lineAtStartPoints [2], lineAtStartPoints [3], limit);
//...si le trait lineAtStart est joint à ce trait
//à son extrémité de départ, faire le m^me calcul
//en inversant les points P0,P1,P2,P3 du trait lineAtStart
} else if (this.lineAtStart.getEquipmentLineAtStart() == this) {
computeIntersection(linePoints [0], linePoints [1],
lineAtStartPoints [2], lineAtStartPoints [3], limit);
computeIntersection(linePoints [3], linePoints [2],
lineAtStartPoints [0], lineAtStartPoints [1], limit);
}
}
// Si le trait à son extremité de fin à un autre
//trait lineAtEnd...
if (this.lineAtEnd != null) {
float [][] lineAtEndPoints = this.lineAtEnd.getRectanglePoints();
//Si le trait lineAtEnd est joint à ce trait
//à son extrémité de départ...
if (lineAtEnd.getEquipmentLineAtStart() == this) {
//....calcul de l'intersection P1i de la ligne
//(P1,P0) du trait avec la ligne(P0,P1) du trait
// lineAtEnd, et de l'intersection P2i de la ligne
//(P2,P3) de cetrait avec la ligne (P3,P2)
//du trait lineAtEnd...
computeIntersection(linePoints [1], linePoints [0],
lineAtEndPoints [0], lineAtEndPoints [1], limit);
computeIntersection(linePoints [2], linePoints [3],
lineAtEndPoints [3], lineAtEndPoints [2], limit);
//...si le trait lineAtEnd est joint à ce trait
//à son extrémité de fin, faire le même calcul
//en inversant les points P0,P1,P2,P3 du trait lineAtEnd
} else if (lineAtEnd.getEquipmentLineAtEnd() == this) {
computeIntersection(linePoints [1], linePoints [0],
lineAtEndPoints [3], lineAtEndPoints [2], limit);
computeIntersection(linePoints [2], linePoints [3],
lineAtEndPoints [0], lineAtEndPoints [1], limit);
}
}
// Cache shape
this.pointsCache = linePoints;
}
return new float [][] {
{this.pointsCache [0][0], this.pointsCache [0][1]},
{this.pointsCache [1][0], this.pointsCache [1][1]},
{this.pointsCache [2][0], this.pointsCache [2][1]},
{this.pointsCache [3][0], this.pointsCache [3][1]}};
}
/**
* Renvoie les points du controleur du rectangle de ce trait
*/
private float [][] getRectanglePoints() {
double angle = Math.atan2(this.yEnd - this.yStart,
this.xEnd - this.xStart);
float dx = (float)Math.sin(angle) * this.thickness / 2;
float dy = (float)Math.cos(angle) * this.thickness / 2;
//renvoie d'un tableau qui contient les coordonées
// des quatres points P0,P1,P2,P3 du rectangle du trait
return new float [][] {
{this.xStart + dx, this.yStart - dy},
{this.xEnd + dx, this.yEnd - dy},
{this.xEnd - dx, this.yEnd + dy},
{this.xStart - dx, this.yStart + dy}};
}
/**
* Calcule l'intersection entre la droite joignant les points
* point1 et point2 et la droite joignant les points point3
* et point4, puis stocke le résultat dans le point point1
*/
private void computeIntersection(float [] point1, float [] point2,
float [] point3, float [] point4, float limit) {
float x = point1 [0];
float y = point1 [1];
//Calcul des coefficient a1, b1,et a2 b2
//des équations des deux droites
float alpha1 = (point2 [1] - point1 [1]) / (point2 [0] - point1 [0]);
float beta1 = point2 [1] - alpha1 * point2 [0];
float alpha2 = (point4 [1] - point3 [1]) / (point4 [0] - point3 [0]);
float beta2 = point4 [1] - alpha2 * point4 [0];
// Si les deux droites ne sont pas parallèles...
if (alpha1 != alpha2) {
// ...calcul de l'intersection si la première
//droite est verticale
if (point1 [0] == point2 [0]) {
x = point1 [0];
y = alpha2 * x + beta2;
//...calcul de l'intersection si la seconde
//droite est verticale
} else if (point3 [0] == point4 [0]) {
x = point3 [0];
y = alpha1 * x + beta1;
//...sinon calcul de l'intesection et le point
//point est inférieur à la limite fixée, stockage
// de l'intersection dans point1
} else {
x = (beta2 - beta1) / (alpha1 - alpha2);
y = alpha1 * x + beta1;
}
}
//Si la distance entre l'intersection et le point
//point1 est inférieure à la limite fixée, stockage
//de l'intersection dans point1
if (Point2D.distanceSq(x, y, point1 [0], point1 [1]) < limit * limit) {
point1 [0] = x;
point1 [1] = y;
}
}
/**
* Renvoie true si ce trait a une intersection non vide
* avec le rectangle de points opposées (x0,y0) et (x1,y1)
*/
public boolean intersectsRectangle(float x0, float y0, float x1, float y1) {
Rectangle2D rectangle = new Rectangle2D.Float(x0, y0, 0, 0);
rectangle.add(x1, y1);
return getShape().intersects(rectangle);
}
/**
* Renvoie true si ce trait line contient le point
* de coordonnées(x,y) avec une tolérance de margin cm
*/
public boolean containsPoint(float x, float y, float margin) {
return containsShapeAtWithMargin(getShape(), x, y, margin);
}
/**
* Renvoie true si l'extremité de départ de ce trait
* contient le point(x,y)
*/
public boolean containsEquipmentLineStartAt(float x, float y, float margin) {
//Récuparation des points du trait
float [][] linePoints = getPoints();
//recherche avec une tolérance margin de
//l'intersection entre le point (x,y) et
//la ligne(P0,P3) qui correspond à l'extrémité
//de départ du trait
Line2D startLine = new Line2D.Float(linePoints [0][0], linePoints [0][1], linePoints [3][0], linePoints [3][1]);
return containsShapeAtWithMargin(startLine, x, y, margin);
}
/**
* Renvoie true si l'extremité de fin de ce trait
* contient le point(x,y)
*/
public boolean containsEquipmentLineEndAt(float x, float y, float margin) {
//Récuparation des points du trait
float [][] linePoints = getPoints();
//recherche avec une tolérance margin de
//l'intersection entre le point (x,y) et
//la ligne(P1,P2) qui correspond à l'extrémité
//de fin du trait
Line2D endLine = new Line2D.Float(linePoints [1][0], linePoints [1][1], linePoints [2][0], linePoints [2][1]);
return containsShapeAtWithMargin(endLine, x, y, margin);
}
/**
* Renvoie true si la forme shape contient le point
* de coordonées (x,y)avec une tolérance de 2 pixels
*/
private boolean containsShapeAtWithMargin(Shape shape, float x, float y, float margin) {
return shape.intersects(x - margin, y - margin, 2 * margin, 2 * margin);
}
/**
* Renvoie la forme de ce trait
*/
private Shape getShape() {
float [][] linePoints = getPoints();
GeneralPath linePath = new GeneralPath();
linePath.moveTo(linePoints [0][0], linePoints [0][1]);
for (int i = 1; i < linePoints.length; i++) {
linePath.lineTo(linePoints [i][0], linePoints [i][1]);
}
linePath.closePath();
return linePath;
} |
Partager