/* * (non-Javadoc) * * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Hit other = (Hit) obj; if (!getOuterType().equals(other.getOuterType())) return false; if (mDistance == null) { if (other.mDistance != null) return false; } else if (!mDistance.equals(other.mDistance)) return false; if (mHitRay == null) { if (other.mHitRay != null) return false; } else if (!mHitRay.equals(other.mHitRay)) return false; if (mIntersection == null) { if (other.mIntersection != null) return false; } else if (!mIntersection.equals(other.mIntersection)) return false; return true; }
/** * Methode prueft, ob der gesetzte Schnittpunkt Startpunkt des getroffenen Strahls ist. Sofern * dies der Fall ist, wird das Start-Flag gesetzt. */ private void isPointStart() { // teste, ob der Schnittpunkt dem Startpunkt entspricht MyVector3f rayStart = mHitRay.getStart(); if (rayStart.equals(mIntersection)) { mIsStart = true; return; } MyVectormath mathHelper = MyVectormath.getInstance(); // teste nun, ob die Distanz zwischen den Punkten innerhalb eines // Toleranzbereichs liegt // sofern dies der Fall ist, werden die Punkte als "gleich" // angesehen float distance = mathHelper.calculatePointPointDistance(rayStart, mIntersection); if (mathHelper.isWithinTolerance(distance, 0.0f, 0.01f)) { mIsStart = true; return; } mIsStart = false; }
/** * Methode durchlaeuft alle Strahlen im uebergebenen Vektor und testet auf Schnitte mit dem * uebergebenen Strahl. Hierbei wird immer der Strahl zurueckgegeben, dessen Schnitt mit dem * uebergebenen Strahl dem Ausgangspunkt am naechsten liegt (darum kann man auch nicht abbrechen, * sobald man den ersten Schnitt gefunden hat) * * @param current Strahl, fuer den im Strahlenvektor nach Schnitten gesucht wird * @param bucket Eimer, fuer den der gemergte Grundriss berechnet wird und der alle Strahlen fuer * diese Rechnung enthaelt * @param lastIntersected Im letzten Durchlauf geschnittener Strahl. So wird ein Ping-Pong-Effekt * zwischen Iterationen vermieden * @param lastIntersection Vektor, der den letzten berechneten Schnittpunkt beschreibt * @return Hit-Datenstruktur, die den getroffenen Strahl sowie den Schnittpunkt enthaelt */ private Hit findIntersectingRay( final Ray current, final FootprintBucket bucket, final Ray lastIntersected, final MyVector3f lastIntersection) { Ray currentTestRay = null; float currentIntersectionDistance = Float.MAX_VALUE, lastIntersectionDistance = -Float.MAX_VALUE; MyVector3f currentIntersection = null; List<Hit> hits = new ArrayList<Hit>(); Hit currentHit = null; LOGGER.debug("Aktueller Teststrahl: " + current); LOGGER.debug("Letzter Schnittpunkt: " + lastIntersection); Iterator<Ray> allRayIter = bucket.getAllRays().iterator(); while (allRayIter.hasNext()) { currentTestRay = allRayIter.next(); // sich selber nicht testen if (currentTestRay.equals(current)) continue; // den zuletzt geschnittenen Strahl ebenfalls ueberspringen if (currentTestRay.equals(lastIntersected)) continue; // sonst Schnittpunkt berechnen currentIntersection = mMathHelper.calculateRay2RayIntersectionApproximation(currentTestRay, current); // Entfernung des letzten Schnittpunkts zum Startpunkt bestimmen if (lastIntersection != null) lastIntersectionDistance = mMathHelper.calculatePointPointDistance(lastIntersection, current.getStart()); if (currentIntersection != null) { // das Verfahren wird einen Strahl finden, der den Startpunkt // des aktuellen Strahls als Endpunkt besitzt, diesen // ueberspringen if (currentIntersection.equals(current.getStart())) continue; // wenn Vertices auf Strahlen liegen, kann der Fall auftreten, // dass der Schnittpunkt des letzten Durchlaufs erneut gefunden // wird if (currentIntersection.equals(lastIntersection)) continue; // logger.trace("CurrentIntersection: " + currentIntersection); // befindet sich der Strahl auf den Liniensegmenten beider // Teststrahlen? if (mMathHelper.isPointOnLineSegment(currentIntersection, currentTestRay) && mMathHelper.isPointOnLineSegment(currentIntersection, current)) { // sortiere solche Hits aus, bei denen der Schnittpunkt der // Endpunkt der getroffenen Kante ist double rayParameter = mMathHelper.calculateParameterOnRayForPoint(currentIntersection, currentTestRay); if (mMathHelper.isWithinTolerance(rayParameter, 1.0d, 0.001d)) { continue; } // Entfernung bestimmen currentIntersectionDistance = mMathHelper.calculatePointPointDistance(currentIntersection, current.getStart()); // wenn der neue Schnittpunkt naeher am Startpunkt liegt,als // der im vorheringen Startpunkt berechnete, breche ab! // Dieser Schnittpunkt liegt auf dem Eingabestrahl und muss // nicht mit dem Startpunkt identisch sein, darum muss // jeder neue Schnittpunkt, der auf dem Strahl ermittelt // wird, zwingend weiter vom Start des Eingabestrahls // entfernt liegen if (lastIntersectionDistance > currentIntersectionDistance) { continue; } // erzeuge eine Treffer-Instanz currentHit = new Hit(currentTestRay, currentIntersectionDistance, currentIntersection); if (!hits.contains(currentHit)) { hits.add(currentHit); // logger.info("Kandidat: " + currentHit); } // suche nach Strahlen, die eine Verlaengerung des // Ausgangsstrahls sind und somit durch Schnittpunkttests // nicht gefunden werden koennen List<Ray> additionalRays = searchForRaysContainingGivenPoint(currentIntersection, current, bucket.getAllRays()); // wenn Strahlen gefunden wurden, adde sie zum Hit-Vetor if (additionalRays.size() > 0) { Ray additionalRay = null; Iterator<Ray> additionalRayIter = additionalRays.iterator(); while (additionalRayIter.hasNext()) { additionalRay = additionalRayIter.next(); currentHit = new Hit(additionalRay, currentIntersectionDistance, currentIntersection); if (!hits.contains(currentHit)) { hits.add(currentHit); // logger.info("Kandidat: " + currentHit); } } } } } } LOGGER.debug("Insgesamt wurden " + hits.size() + " potentielle Kandidaten bestimmt."); // wenn kein Strahl gefunden wurde, werfe eine Exception assert hits.size() > 0 : "Fehler: Es konnte kein Strahl gefunden werden, der sich mit dem Eingabestrahl schneidet! Eingabe: " + current; /* * logger.info("Potentielle Treffer: "); for(int i = 0; i < hits.size(); * i++) logger.info(hits.get(i)); */ // es wurde nur ein Strahl getroffen if (hits.size() == 1) { return hits.get(0); } currentHit = chooseResultRay(hits, current, bucket); if (currentHit == null) return hits.get(0); else return currentHit; }