📄 channelmodel.java
字号:
// <<<< Get visible obstacle candidates inside this angle interval >>>> Vector<Rectangle2D> visibleObstacleCandidates = myObstacleWorld.getAllObstaclesInAngleInterval(source, angleIntervalToCheck); //logger.info("Obstacle candidates count = " + visibleObstacleCandidates.size()); if (visibleObstacleCandidates.isEmpty()) { //logger.info("Visible obstacles candidates empty"); unhandledAngles.remove(angleIntervalToCheck); break; // Restart without this angle } // <<<< Get visible line candidates of these obstacles >>>> Vector<Line2D> visibleLineCandidates = new Vector<Line2D>(); for (int i=0; i < visibleObstacleCandidates.size(); i++) { Rectangle2D obstacle = visibleObstacleCandidates.get(i); int outcode = obstacle.outcode(source); if ((outcode & Rectangle2D.OUT_BOTTOM) != 0) visibleLineCandidates.add( new Line2D.Double(obstacle.getMinX(), obstacle.getMaxY(), obstacle.getMaxX(), obstacle.getMaxY())); if ((outcode & Rectangle2D.OUT_TOP) != 0) visibleLineCandidates.add( new Line2D.Double(obstacle.getMinX(), obstacle.getMinY(), obstacle.getMaxX(), obstacle.getMinY())); if ((outcode & Rectangle2D.OUT_LEFT) != 0) visibleLineCandidates.add( new Line2D.Double(obstacle.getMinX(), obstacle.getMinY(), obstacle.getMinX(), obstacle.getMaxY())); if ((outcode & Rectangle2D.OUT_RIGHT) != 0) visibleLineCandidates.add( new Line2D.Double(obstacle.getMaxX(), obstacle.getMinY(), obstacle.getMaxX(), obstacle.getMaxY())); } //logger.info("Line candidates count = " + visibleLineCandidates.size()); if (visibleLineCandidates.isEmpty()) { //logger.info("Visible line candidates empty"); unhandledAngles.remove(angleIntervalToCheck); break; // Restart without this angle } // <<<< Get cropped visible line candidates of these lines >>>> Vector<Line2D> croppedVisibleLineCandidates = new Vector<Line2D>(); for (int i=0; i < visibleLineCandidates.size(); i++) { Line2D lineCandidate = visibleLineCandidates.get(i); // Create angle interval of this line AngleInterval lineAngleInterval = AngleInterval.getAngleIntervalOfLine(source, lineCandidate); AngleInterval intersectionInterval = null; // Add entire line if it is fully inside our visible angle interval if (angleIntervalToCheck.contains(lineAngleInterval)) { if (lookThrough != null) { // Check if the candidate is "equal" to the see through line if (Math.abs(lineCandidate.getX1() - lookThrough.getX1()) + Math.abs(lineCandidate.getY1() - lookThrough.getY1()) + Math.abs(lineCandidate.getX2() - lookThrough.getX2()) + Math.abs(lineCandidate.getY2() - lookThrough.getY2()) < 0.01) { // See through line and candidate line are the same - skip this candidate } // Check if the candidate is on our side of the see through line else if (new Line2D.Double( lineCandidate.getBounds2D().getCenterX(), lineCandidate.getBounds2D().getCenterY(), sourceX, sourceY ).intersectsLine(lookThrough)) { croppedVisibleLineCandidates.add(lineCandidate); } // else Skip line } else croppedVisibleLineCandidates.add(lineCandidate); } // Add part of line if it is partly inside our visible angle interval else if ((intersectionInterval = lineAngleInterval.intersectWith(angleIntervalToCheck)) != null) { // Get lines towards the visible segment Line2D lineToStartAngle = AngleInterval.getDirectedLine( source, intersectionInterval.getStartAngle(), 1.0 ); Line2D lineToEndAngle = AngleInterval.getDirectedLine( source, intersectionInterval.getEndAngle(), 1.0 ); // Calculate intersection points Point2D intersectionStart = getIntersectionPointInfinite( lineCandidate, lineToStartAngle ); Point2D intersectionEnd = getIntersectionPointInfinite( lineCandidate, lineToEndAngle ); if ( intersectionStart != null && intersectionEnd != null && intersectionStart.distance(intersectionEnd) > 0.001 // Rounding error limit (1 mm) ) { Line2D newCropped = new Line2D.Double(intersectionStart, intersectionEnd); if (lookThrough != null) { // Check if the candidate is "equal" to the see through line if (Math.abs(newCropped.getX1() - lookThrough.getX1()) + Math.abs(newCropped.getY1() - lookThrough.getY1()) + Math.abs(newCropped.getX2() - lookThrough.getX2()) + Math.abs(newCropped.getY2() - lookThrough.getY2()) < 0.01) { // See through line and candidate line are the same - skip this candidate } // Check if the candidate is on our side of the see through line else if (new Line2D.Double( newCropped.getBounds2D().getCenterX(), newCropped.getBounds2D().getCenterY(), sourceX, sourceY ).intersectsLine(lookThrough)) { croppedVisibleLineCandidates.add(newCropped); } // else Skip line } else croppedVisibleLineCandidates.add(newCropped); } } // Skip line completely if not in our visible angle interval else { } } //logger.info("Cropped line candidates count = " + croppedVisibleLineCandidates.size()); if (croppedVisibleLineCandidates.isEmpty()) { //logger.info("Cropped visible line candidates empty"); unhandledAngles.remove(angleIntervalToCheck); break; // Restart without this angle } // <<<< Get visible lines from these line candidates >>>> for (int i=0; i < croppedVisibleLineCandidates.size(); i++) { Line2D visibleLineCandidate = croppedVisibleLineCandidates.get(i); AngleInterval visibleLineCandidateAngleInterval = AngleInterval.getAngleIntervalOfLine(source, visibleLineCandidate).intersectWith(angleIntervalToCheck); //logger.info("Incoming angle interval " + angleIntervalToCheck); //logger.info(". => line interval " + visibleLineCandidateAngleInterval); // Area to test for shadowing objects GeneralPath testArea = new GeneralPath(); testArea.moveTo((float) sourceX, (float) sourceY); testArea.lineTo((float) visibleLineCandidate.getX1(), (float) visibleLineCandidate.getY1()); testArea.lineTo((float) visibleLineCandidate.getX2(), (float) visibleLineCandidate.getY2()); testArea.closePath(); // Does any other line shadow this line? boolean unshadowed = true; boolean unhandledAnglesChanged = false; for (int j=0; j < croppedVisibleLineCandidates.size(); j++) { // Create shadow rectangle Line2D shadowLineCandidate = croppedVisibleLineCandidates.get(j); Rectangle2D shadowRectangleCandidate = shadowLineCandidate.getBounds2D(); double minDelta = 0.01*Math.max( shadowRectangleCandidate.getWidth(), shadowRectangleCandidate.getHeight() ); shadowRectangleCandidate.add( shadowRectangleCandidate.getCenterX() + minDelta, shadowRectangleCandidate.getCenterY() + minDelta ); // Find the shortest of the two double shadowDistance = shadowLineCandidate.getP1().distance(source) + shadowLineCandidate.getP2().distance(source); double visibleDistance = visibleLineCandidate.getP1().distance(source) + visibleLineCandidate.getP2().distance(source); double shadowCloseDistance = Math.min( shadowLineCandidate.getP1().distance(source), shadowLineCandidate.getP2().distance(source)); double visibleFarDistance = Math.max( visibleLineCandidate.getP1().distance(source), visibleLineCandidate.getP2().distance(source)); // Does shadow rectangle intersect test area? if (visibleLineCandidate != shadowLineCandidate && testArea.intersects(shadowRectangleCandidate) && shadowCloseDistance <= visibleFarDistance) { // Shadow line candidate seems to shadow (part of) our visible candidate AngleInterval shadowLineCandidateAngleInterval = AngleInterval.getAngleIntervalOfLine(source, shadowLineCandidate).intersectWith(angleIntervalToCheck); if (shadowLineCandidateAngleInterval.contains(visibleLineCandidateAngleInterval)) { // Covers us entirely, do nothing // Special case, both shadow and visible candidate have the same interval if (visibleLineCandidateAngleInterval.contains(shadowLineCandidateAngleInterval)) { if (visibleDistance > shadowDistance) { unshadowed = false; break; } } else { unshadowed = false; break; } } else if (visibleLineCandidateAngleInterval.intersects(shadowLineCandidateAngleInterval)) { // Covers us partly, split angle interval Vector<AngleInterval> newIntervalsToAdd = new Vector<AngleInterval>(); // Create angle interval of intersection between shadow and visible candidate AngleInterval intersectedInterval = visibleLineCandidateAngleInterval.intersectWith(shadowLineCandidateAngleInterval); if (intersectedInterval != null) { Vector<AngleInterval> tempVector1 = AngleInterval.intersect(unhandledAngles, intersectedInterval); if (tempVector1 != null) for (int k=0; k < tempVector1.size(); k++) if (tempVector1.get(k) != null && !tempVector1.get(k).isEmpty()) { newIntervalsToAdd.add(tempVector1.get(k)); } } // Add angle interval of visible candidate without shadow candidate Vector<AngleInterval> tempVector2 = visibleLineCandidateAngleInterval.subtract(shadowLineCandidateAngleInterval); if (tempVector2 != null) for (int k=0; k < tempVector2.size(); k++) if (tempVector2.get(k) != null && !tempVector2.get(k).isEmpty()) newIntervalsToAdd.addAll(AngleInterval.intersect(unhandledAngles, tempVector2.get(k))); // Subtract angle interval of visible candidate unhandledAngles = AngleInterval.subtract(unhandledAngles, visibleLineCandidateAngleInterval); unhandledAnglesChanged = true; // Add new angle intervals //logger.info("Split angle interval: " + visibleLineCandidateAngleInterval); for (int k=0; k < newIntervalsToAdd.size(); k++) { if (newIntervalsToAdd.get(k) != null && !newIntervalsToAdd.get(k).isEmpty()) { //logger.info("> into: " + newIntervalsToAdd.get(k)); unhandledAngles.add(newIntervalsToAdd.get(k)); unhandledAnglesChanged = true; } } unshadowed = false; break; } else { // Not intersecting after all, just ignore this } } if (!unshadowed) break; } if (unhandledAnglesChanged) { //logger.info("Unhandled angles changed, restarting.."); break; } if (unshadowed) { // No other lines shadow this line => this line must be visible! unhandledAngles = AngleInterval.subtract(unhandledAngles, visibleLineCandidateAngleInterval); visibleLines.add(visibleLineCandidate); //logger.info("Added visible line and removed angle interval: " + visibleLineCandidateAngleInterval); //logger.info("Number of visible lines sofar: " + visibleLines.size()); break; } } } } // End of outer loop // Save results in order to speed up later calculations int size = calculatedVisibleSides.size(); // Crop saved sides vectors if (size >= maxSavedVisibleSides) { calculatedVisibleSides.remove(size-1); calculatedVisibleSidesSources.remove(size-1); calculatedVisibleSidesAngleIntervals.remove(size-1); calculatedVisibleSidesLines.remove(size-1); } calculatedVisibleSides.add(0, visibleLines); calculatedVisibleSidesSources.add(0, source); calculatedVisibleSidesAngleIntervals.add(0, angleInterval); calculatedVisibleSidesLines.add(0, lookThrough); return visibleLines; } /** * Calculates and returns the received signal strength (dBm) of a signal sent * from the given source position to the given destination position as a * random variable. This method uses current parameters such as transmitted * power, obstacles, overall system loss etc. * * @param sourceX * Source position X * @param sourceY * Source position Y * @param destX * Destination position X * @param destY
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -