/******************************************************************************* * See the NOTICE file distributed with this work for additional information * regarding copyright ownership. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package hr.fer.zemris.vhdllab.applets.editor.schema2.misc; /** * Klasa za opis vertikalnog ili horizontalnog segmenta zice. * * @author Axel * */ public final class WireSegment { private XYLocation loc1; private XYLocation loc2; public WireSegment() { loc1 = new XYLocation(); loc2 = new XYLocation(); } public WireSegment(int x1, int y1, int x2, int y2) { loc1 = new XYLocation(x1, y1); loc2 = new XYLocation(x2, y2); check(); } /** * Vraca sjeciste s drugim zicnim segmentom ako ono postoji. * Pritom NE RAZMATRA sjecista koja nastaju na rubovima oba * zicna segmenta. Npr.: * * 1) * ----* * | * | 2) * | * * Zvjezdica se nece smatrati sjecistem. * U sljedecem primjeru: * * 1) * -------*------ * | * | 2) * | * * Zvjezdica se smatra sjecistem. * * U slucaju da su oba segmenta vertikalna ili horizontalna, i pritom * se preklapaju, sjecistem ce se smatrati pocetna ili zavrsna tocka * jednog od segmenata, pri cemu prednost ima pocetna tocka. * * @param other * @return * Vraca null ako nema sjecista. * Povratna vrijednost je kopija. */ public XYLocation intersection(WireSegment other) { if (this.isVertical()) { if (other.isVertical()) { if (this.loc1.x == other.loc1.x) { if (SMath.insideOrd(this.loc1.y, other.loc1.y, other.loc2.y)) return new XYLocation(this.loc1); if (SMath.insideOrd(this.loc2.y, other.loc1.y, other.loc2.y)) return new XYLocation(this.loc2); } } else { if (SMath.insideOrd(other.loc1.y, this.loc1.y, this.loc2.y)) { if (SMath.withinOrd(this.loc1.x, other.loc1.x, other.loc2.x)) return new XYLocation(this.loc1.x, other.loc1.y); } if (SMath.insideOrd(this.loc1.x, other.loc1.x, other.loc2.x)) { if (other.loc1.y == this.loc1.y) return new XYLocation(this.loc1); if (other.loc1.y == this.loc2.y) return new XYLocation(this.loc2); } } } else { if (!other.isVertical()) { if (this.loc1.y == other.loc1.y) { if (SMath.insideOrd(this.loc1.x, other.loc1.x, other.loc2.x)) return new XYLocation(this.loc1); if (SMath.insideOrd(this.loc2.x, other.loc1.x, other.loc2.x)) return new XYLocation(this.loc2); } } else { if (SMath.insideOrd(other.loc1.x, this.loc1.x, this.loc2.x)) { if (SMath.withinOrd(this.loc1.y, other.loc1.y, other.loc2.y)) return new XYLocation(other.loc1.x, this.loc1.y); } if (SMath.insideOrd(this.loc1.y, other.loc1.y, other.loc2.y)) { if (other.loc1.x == this.loc1.x) return new XYLocation(this.loc1); if (other.loc1.x == this.loc2.x) return new XYLocation(this.loc2); } } } return null; } /** * Odreduje tocku dodira ovog segmenta i segmenta <code>other</code>, * pri cemu je tocka dodira ona tocka koja je na rubu jednog i na rubu * drugog segmenta istovremeno (rubovi se dodiruju). Npr.: * * 1) * ----* * | * | 2) * | * * Zvjezdica je tocka dodira. * * @param other * @return * Vraca null ako se ovaj i drugi segment ne diraju na rubovima. * Povratna vrijednost je kopija. */ public XYLocation edgepoint(WireSegment other) { if (other.loc1.equals(this.loc1) || other.loc1.equals(this.loc2)) return new XYLocation(other.loc1); if (other.loc2.equals(this.loc1) || other.loc2.equals(this.loc2)) return new XYLocation(other.loc2); return null; } public void setEnd(XYLocation loc2) { this.loc2 = loc2; check(); } public XYLocation getEnd() { return loc2; } public void setStart(XYLocation loc1) { this.loc1 = loc1; check(); } public XYLocation getStart() { return loc1; } private final void check() { if (loc1.x != loc2.x && loc1.y != loc2.y) { System.out.println("Segment not ortogonal: " + loc1.toString() + " ... " + loc2.toString()); throw new IllegalArgumentException("WireSegment can only be vertical or horizontal."); } } /** * Odreduje da li je zica okomita. * */ public final boolean isVertical() { return (loc1.x == loc2.x); } /** * Odreduje da li je zadana tocka na tom segmentu. * @param x * @param y */ public final boolean hasPoint(int x, int y) { if (loc1.x == loc2.x) { /* vertical */ return loc1.x == x && SMath.withinOrd(y, loc1.y, loc2.y); } /* horizontal */ return loc1.y == y && SMath.withinOrd(x, loc1.x, loc2.x); } public final void setX1(int x1) { loc1.x = x1; } public final void setY1(int y1) { loc1.y = y1; } public final void setX2(int x2) { loc2.x = x2; } public final void setY2(int y2) { loc2.y = y2; } /** * Vraca udaljenost segmenta * od neke tocke. * * @param xlkp * @param ylkp */ public final int calcDist(int xlkp, int ylkp) { if (this.isVertical()) { int ly = (this.loc1.y > this.loc2.y) ? (this.loc2.y) : (this.loc1.y); int hy = (ly == this.loc1.y) ? (this.loc2.y) : (this.loc1.y); if (ylkp >= ly && ylkp <= hy) { return Math.abs(xlkp - this.loc1.x); } else if (ylkp > hy) { return getlen(xlkp - this.loc1.x, ylkp - hy); } else { return getlen(xlkp - this.loc1.x, ylkp - ly); } } int lx = (this.loc1.x > this.loc2.x) ? (this.loc2.x) : (this.loc1.x); int rx = (lx == this.loc1.x) ? (this.loc2.x) : (this.loc1.x); if (xlkp >= lx && xlkp <= rx) { return Math.abs(ylkp - this.loc1.y); } else if (xlkp > rx) { return getlen(xlkp - rx, ylkp - this.loc1.y); } else { return getlen(xlkp - lx, ylkp - this.loc1.y); } } public final int length() { return (isVertical()) ? (Math.abs(loc2.y - loc1.y)) : (Math.abs(loc2.x - loc1.x)); } private final int getlen(int dx, int dy) { return (int)Math.round(Math.sqrt(dx * dx + dy * dy)); } @Override public boolean equals(Object obj) { if (obj == null || !(obj instanceof WireSegment)) return false; WireSegment ws = (WireSegment)obj; return (ws.loc1.equals(loc1) && ws.loc2.equals(loc2)); } @Override public int hashCode() { return loc1.hashCode() << 16 + loc2.hashCode(); } @Override public String toString() { return "WireSegment[(" + loc1.x + ", " + loc1.y + "), (" + loc2.x + ", " + loc2.y + ")"; } }