/** * Calculate course, distance and reachability from the current position * to the elements contained in the limited list. If a glider is defined * the glide path is taken into account and the arrival altitude is * calculated too. */ void ReachableList::calculateDataInList() { // QTime t; // t.start(); int counter = 0; setInitValues(); arrivalAltMap.clear(); distanceMap.clear(); for (int i = 0; i < count(); i++) { // recalculate Distance ReachablePoint& p = (*this)[i]; WGSPoint pt = p.getWaypoint()->wgsPoint; Altitude arrivalAlt; Distance distance; Speed bestSpeed; distance.setKilometers( MapCalc::dist(&lastPosition, &pt) ); if ( lastPosition == pt || distance.getMeters() <= 100.0 ) { // @AP: there is nearly no difference between the two points, // therefore we have no distance and no bearing distance.setMeters(0.0); p.setDistance( distance ); p.setBearing( 0 ); p.setArrivalAlt( calculator->getAltitudeCollection().gpsAltitude ); } else { p.setDistance( distance ); // recalculate Bearing p.setBearing( short (rint(MapCalc::getBearingWgs(lastPosition, pt) * 180/M_PI)) ); // Calculate glide path. Returns false, if no glider is known. calculator->glidePath( p.getBearing(), p.getDistance(), Altitude(p.getElevation()), arrivalAlt, bestSpeed ); // Save arrival altitude. Is set to invalid, if no glider is defined in calculator. p.setArrivalAlt( arrivalAlt ); } if ( arrivalAlt.isValid() ) { // add only valid altitudes to the map arrivalAltMap[ coordinateString ( pt ) ] = (int) arrivalAlt.getMeters() + safetyAlt; } distanceMap[ coordinateString ( pt ) ] = distance; if ( arrivalAlt.getMeters() > 0 ) { counter++; } } // sorting of items depends on the glider selection if ( calculator->glider() ) { modeAltitude = true; // glider is known, sort by arrival altitudes } else { modeAltitude = false; // glider is unknown, sort by distances } qSort( begin(), end() ); // qDebug("Number of reachable sites (arriv >0): %d", counter ); // qDebug("Time for glide path calculation: %d msec", t.restart() ); emit newReachList(); }
QVector<float> TransformationMatrix::getFullMapTransformationMatrix( const Distance& wallWidth, QPair<double, double> physicalMazeSize, QPair<int, int> fullMapPosition, QPair<int, int> fullMapSize, QPair<int, int> windowSize) { // The purpose of this function is to produce a 4x4 matrix which, when // applied to the physical coordinate within the vertex shader, transforms // it into an OpenGL coordinate for the full map. In this case, the zoomed // map always contains the entirety of the maze. // Step 1: The physical point (0,0) corresponds to the middle of the // bottom-left corner piece: // | | // +-------+--- // | | // | X | // | | // +-------+--- // // However, we want to make sure that the entire maze is visible within the // map window. To ensure this, we first have to translate the physical // positions so that (0,0) actually refers to the bottom-left corner of the // bottom-left corner: // // | | // +-------+--- // | | // | | // | | // X-------+--- // QVector<float> initialTranslationMatrix = { 1.0, 0.0, 0.0, static_cast<float>(0.5 * wallWidth.getMeters()), 0.0, 1.0, 0.0, static_cast<float>(0.5 * wallWidth.getMeters()), 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, }; // Ensure that the maze width and height always appear equally scaled. double physicalWidth = physicalMazeSize.first; double physicalHeight = physicalMazeSize.second; // Note that this is not literally the number of pixels per meter of the // screen. Rather, it's our desired number of pixels per simulation meter. double pixelsPerMeter = std::min(fullMapSize.first / physicalWidth, fullMapSize.second / physicalHeight); double pixelWidth = pixelsPerMeter * physicalWidth; double pixelHeight = pixelsPerMeter * physicalHeight; QPair<double, double> openGlOrigin = mapPixelCoordinateToOpenGlCoordinate({0, 0}, windowSize); QPair<double, double> openGlMazeSize = mapPixelCoordinateToOpenGlCoordinate({pixelWidth, pixelHeight}, windowSize); double openGlWidth = openGlMazeSize.first - openGlOrigin.first; double openGlHeight = openGlMazeSize.second - openGlOrigin.second; double horizontalScaling = openGlWidth / physicalWidth; double verticalScaling = openGlHeight / physicalHeight; QVector<float> scalingMatrix = { static_cast<float>(horizontalScaling), 0.0, 0.0, 0.0, 0.0, static_cast<float>(verticalScaling), 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, }; // Step 3: Construct the translation matrix. Note that here we ensure that // the maze is centered within the map boundaries. double pixelLowerLeftCornerX = fullMapPosition.first + 0.5 * (fullMapSize.first - pixelWidth); double pixelLowerLeftCornerY = fullMapPosition.second + 0.5 * (fullMapSize.second - pixelHeight); QPair<double, double> openGlLowerLeftCorner = mapPixelCoordinateToOpenGlCoordinate({pixelLowerLeftCornerX, pixelLowerLeftCornerY}, windowSize); QVector<float> translationMatrix = { 1.0, 0.0, 0.0, static_cast<float>(openGlLowerLeftCorner.first), 0.0, 1.0, 0.0, static_cast<float>(openGlLowerLeftCorner.second), 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, }; // Step 4: Compose the matrices QVector<float> transformationMatrix = multiply4x4Matrices(translationMatrix, multiply4x4Matrices(scalingMatrix, initialTranslationMatrix)); return transformationMatrix; }