📄 channelmodel.java
字号:
while (treeEnum.hasMoreElements()) { // For every element, // check if it is the origin, a diffraction, refraction or a reflection source DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) treeEnum.nextElement(); RayData rayData = (RayData) treeNode.getUserObject(); Point2D sourcePoint = rayData.getSourcePoint(); Line2D line = rayData.getLine(); RayData.RayType type = rayData.getType(); Line2D pseudoSourceToDest = new Line2D.Double(sourcePoint, dest); boolean directPathExists = false; Point2D justBeforeDestination = null; // Get ray path point just before destination (if path exists at all) if (type == RayData.RayType.ORIGIN) { // Check if direct path exists justBeforeDestination = sourcePoint; if (!getParameterBooleanValue("rt_disallow_direct_path")) directPathExists = isDirectPath(justBeforeDestination, dest); else directPathExists = false; } else if (type == RayData.RayType.REFRACTION && pseudoSourceToDest.intersectsLine(line)) { // Destination is inside refraction interval justBeforeDestination = getIntersectionPoint(pseudoSourceToDest, line); // Check if direct path exists (but ignore when leaving obstacle) directPathExists = isDirectPath(justBeforeDestination, dest); } else if (type == RayData.RayType.REFLECTION && pseudoSourceToDest.intersectsLine(line)) { // Destination is inside reflection interval justBeforeDestination = getIntersectionPoint(pseudoSourceToDest, line); // Check if direct path exists (ignore reflection line) directPathExists = isDirectPath(justBeforeDestination, dest); } else if (type == RayData.RayType.DIFFRACTION) { // Check if direct path exists (travelling through object not allowed justBeforeDestination = sourcePoint; directPathExists = isDirectPath(justBeforeDestination, dest); } // If a direct path exists, traverse up tree to find entire path if (directPathExists) { // Create new empty ray path boolean pathBroken = false; RayPath currentPath = new RayPath(); // Add those parts we already know currentPath.addPoint(dest, RayData.RayType.DESTINATION); currentPath.addPoint(justBeforeDestination, type); Point2D lastPoint = dest; Point2D newestPoint = justBeforeDestination; // Check that this ray subpath is long enough to be considered if (newestPoint.distance(lastPoint) < 0.01 && type != RayData.RayType.ORIGIN) { pathBroken = true; } // Subpath must be double-direct if from diffraction if (type == RayData.RayType.DIFFRACTION && !isDirectPath(lastPoint, newestPoint)) { pathBroken = true; } // Data used when traversing path DefaultMutableTreeNode currentlyTracedNode = treeNode; RayData currentlyTracedRayData = (RayData) currentlyTracedNode.getUserObject(); RayData.RayType currentlyTracedNodeType = currentlyTracedRayData.getType(); Point2D currentlyTracedSource = currentlyTracedRayData.getSourcePoint(); Line2D currentlyTracedLine = currentlyTracedRayData.getLine(); // Traverse upwards until origin found while (!pathBroken && currentlyTracedNodeType != RayData.RayType.ORIGIN) { // Update new ray data currentlyTracedNode = (DefaultMutableTreeNode) currentlyTracedNode.getParent(); currentlyTracedRayData = (RayData) currentlyTracedNode.getUserObject(); currentlyTracedNodeType = currentlyTracedRayData.getType(); currentlyTracedSource = currentlyTracedRayData.getSourcePoint(); currentlyTracedLine = currentlyTracedRayData.getLine(); if (currentlyTracedNodeType == RayData.RayType.ORIGIN) { // We finally found the path origin, path ends here lastPoint = newestPoint; newestPoint = origin; currentPath.addPoint(newestPoint, currentlyTracedNodeType); // Check that this ray subpath is long enough to be considered if (newestPoint.distance(lastPoint) < 0.01) pathBroken = true; } else { // Trace further up in the tree if (currentlyTracedNodeType == RayData.RayType.REFRACTION || currentlyTracedNodeType == RayData.RayType.REFLECTION) { // Traced tree element is a reflection/refraction - get intersection point and keep climbing lastPoint = newestPoint; Line2D newToOldIntersection = new Line2D.Double(currentlyTracedSource, lastPoint); newestPoint = getIntersectionPointInfinite(newToOldIntersection, currentlyTracedLine); } else { // Traced tree element is a diffraction - save point and keep climbing lastPoint = newestPoint; newestPoint = currentlyTracedSource; } currentPath.addPoint(newestPoint, currentlyTracedNodeType); // Check that this ray subpath is long enough to be considered if (newestPoint == null || lastPoint == null || newestPoint.distance(lastPoint) < 0.01) pathBroken = true; } // Subpath must be double-direct if from diffraction if (currentlyTracedNodeType == RayData.RayType.DIFFRACTION && !isDirectPath(lastPoint, newestPoint)) { pathBroken = true; } if (pathBroken) break; } // Save ray path if (!pathBroken) { allPaths.add(currentPath); // Stop here if no other paths should be considered if (type == RayData.RayType.ORIGIN && getParameterBooleanValue("rt_ignore_non_direct")) { return allPaths; } } } } return allPaths; } /** * True if a line drawn from the given source and given destination does * not intersect with any obstacle outer lines in the current obstacle world. * This method only checks for intersection with the obstacles lines "visible" * from source. Hence, if source is inside an obstacle, that obstacles will * not cause this method to return false. (Note that method is not symmetric) * * @param source Source * @param dest Destination * @return True if no obstacles between source and destination */ private boolean isDirectPath(Point2D source, Point2D dest) { Line2D sourceToDest = new Line2D.Double(source, dest); // Get angle double deltaX = dest.getX() - source.getX(); double deltaY = dest.getY() - source.getY(); double angleSourceToDest = Math.atan2(deltaY, deltaX); // Get all visible sides near angle Vector<Line2D> visibleSides = getAllVisibleSides( source.getX(), source.getY(), new AngleInterval(angleSourceToDest - 0.1, angleSourceToDest + 0.1), null ); // Check for intersections if (visibleSides != null) { for (int i=0; i < visibleSides.size(); i++) { if (visibleSides.get(i).intersectsLine(sourceToDest)) { // Check that intersection point is not destination Point2D intersectionPoint = getIntersectionPointInfinite(visibleSides.get(i), sourceToDest); if (dest.distance(intersectionPoint) > 0.01) return false; } } } return true; } /** * Returns the Fast fading factor (in dB), which depends on * the multiple paths from source to destination via reflections * on registered obstacles. * TODO Only first-order multipath... * * @param sourceX Transmitter X coordinate * @param sourceY Transmitter Y coordinate * @param destX Receiver X coordinate * @param destY Receiver Y coordinate * @return Slow fading factor */ protected double getFastFading(double sourceX, double sourceY, double destX, double destY) { Point2D dest = new Point2D.Double(destX, destY); Point2D source = new Point2D.Double(sourceX, sourceY); // Destination inside an obstacle? => no reflection factor for (int i=0; i < myObstacleWorld.getNrObstacles(); i++) { if (myObstacleWorld.getObstacle(i).contains(dest)) { //logger.debug("Destination inside obstacle, aborting fast fading"); return 0; } } return 0; } /** * Returns all possible diffraction sources, by checking which * of the endpoints of the given visible lines that are on a corner * of a obstacle structure. * * @param allVisibleLines Lines which may hold diffraction sources * @return All diffraction sources */ private Vector<Point2D> getAllDiffractionSources(Vector<Line2D> allVisibleLines) { Vector<Point2D> allDiffractionSources = new Vector<Point2D>(); Enumeration<Line2D> allVisibleLinesEnum = allVisibleLines.elements(); while (allVisibleLinesEnum.hasMoreElements()) { Line2D visibleLine = allVisibleLinesEnum.nextElement(); // Check both end points of line for possible diffraction point if (myObstacleWorld.pointIsNearCorner(visibleLine.getP1())) { allDiffractionSources.add(visibleLine.getP1()); } if (myObstacleWorld.pointIsNearCorner(visibleLine.getP2())) { allDiffractionSources.add(visibleLine.getP2()); } } return allDiffractionSources; } /** * Return all obstacle sides visible from given source when looking * in the given angle interval. * The sides may partly be shadowed by other obstacles. * If the angle interval is null, it will be regarded as the entire interval * If the line argument is non-null, all returned lines will be on the far side * of this line, as if one was looking through that line. * * @param sourceX Source X * @param sourceY Source Y * @param angleInterval Angle interval (or null) * @param lookThrough Line to look through (or null) * @return All visible sides */ private Vector<Line2D> getAllVisibleSides(double sourceX, double sourceY, AngleInterval angleInterval, Line2D lookThrough) { Point2D source = new Point2D.Double(sourceX, sourceY); // Check if results were already calculated earlier for (int i=0; i < calculatedVisibleSidesSources.size(); i++) { if ( // Compare sources source.equals(calculatedVisibleSidesSources.get(i)) && // Compare angle intervals (angleInterval == calculatedVisibleSidesAngleIntervals.get(i) || angleInterval != null && angleInterval.equals(calculatedVisibleSidesAngleIntervals.get(i)) ) && // Compare lines (lookThrough == calculatedVisibleSidesLines.get(i) || lookThrough != null && lookThrough.equals(calculatedVisibleSidesLines.get(i)) ) ) { // Move to top of list Point2D oldSource = calculatedVisibleSidesSources.remove(i); Line2D oldLine = calculatedVisibleSidesLines.remove(i); AngleInterval oldAngleInterval = calculatedVisibleSidesAngleIntervals.remove(i); Vector<Line2D> oldVisibleLines = calculatedVisibleSides.remove(i); calculatedVisibleSidesSources.add(0, oldSource); calculatedVisibleSidesLines.add(0, oldLine); calculatedVisibleSidesAngleIntervals.add(0, oldAngleInterval); calculatedVisibleSides.add(0, oldVisibleLines); // Return old results return oldVisibleLines; } } Vector<Line2D> visibleLines = new Vector<Line2D>(); Vector<AngleInterval> unhandledAngles = new Vector<AngleInterval>(); if (lookThrough != null) { if (angleInterval == null) unhandledAngles.add(AngleInterval.getAngleIntervalOfLine(source, lookThrough)); else unhandledAngles.add(AngleInterval.getAngleIntervalOfLine(source, lookThrough).intersectWith(angleInterval)); } else { if (angleInterval == null) unhandledAngles.add(new AngleInterval(0, 2*Math.PI)); else unhandledAngles.add(angleInterval); } // Do forever (will break when no more unhandled angles exist) while (!unhandledAngles.isEmpty()) { // While unhandled angles still exist, keep searching for visible lines while (!unhandledAngles.isEmpty()) { //logger.info("Beginning of while-loop, unhandled angles left = " + unhandledAngles.size()); AngleInterval angleIntervalToCheck = unhandledAngles.firstElement(); // Check that interval is not empty or "infinite small" if (angleIntervalToCheck == null || angleIntervalToCheck.isEmpty()) { //logger.info("Angle interval (almost) empty, ignoring"); unhandledAngles.remove(angleIntervalToCheck); break; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -