void HeightMatrix::Fill(const RasterMap &map, const WindowProjection &projection, unsigned quantisation_pixels, bool interpolate) { const unsigned screen_width = projection.GetScreenWidth(); const unsigned screen_height = projection.GetScreenHeight(); SetSize((screen_width + quantisation_pixels - 1) / quantisation_pixels, (screen_height + quantisation_pixels - 1) / quantisation_pixels); minimum = 0x7fff; maximum = 0; for (unsigned y = 0; y < screen_height; y += quantisation_pixels) { const FastRowRotation rotation = projection.GetScreenAngleRotation(y - projection.GetScreenOrigin().y); short *p = data.begin() + y * width / quantisation_pixels; for (unsigned x = 0; x < screen_width; x += quantisation_pixels) { #ifndef SLOW_TERRAIN_STUFF const FastRowRotation::Pair r = rotation.Rotate(x - projection.GetScreenOrigin().x); GeoPoint gp; gp.Latitude = projection.GetGeoLocation().Latitude - projection.PixelsToAngle(r.second); gp.Longitude = projection.GetGeoLocation().Longitude + projection.PixelsToAngle(r.first) * gp.Latitude.invfastcosine(); #else GeoPoint gp = projection.ScreenToGeo(x, y); #endif short h = interpolate ? map.GetFieldInterpolated(gp) : map.GetField(gp); if (!RasterBuffer::is_special(h)) { if (h < minimum) minimum = h; if (h > maximum) maximum = h; } *p++ = h; } assert(p <= data.end()); } }
void ApplyProjection(const WindowProjection &projection, const GeoPoint &reference) { fixed angle = projection.GetScreenAngle().Degrees(); fixed scale = projection.GetScale(); const RasterPoint &screen_origin = projection.GetScreenOrigin(); const GeoPoint &screen_location = projection.GetGeoLocation(); const GeoPoint projection_delta = reference - screen_location; const fixed scale_r = scale * FAISphere::REARTH; const fixed scale_x = scale_r * screen_location.latitude.fastcosine(); const fixed scale_y = -scale_r; #ifdef HAVE_GLES #ifdef FIXED_MATH GLfixed fixed_angle = angle.as_glfixed(); #else GLfixed fixed_angle = angle * (1<<16); #endif glTranslatex((int)screen_origin.x << 16, (int)screen_origin.y << 16, 0); glRotatex(fixed_angle, 0, 0, -(1<<16)); #else glTranslatef(screen_origin.x, screen_origin.y, 0.); glRotatef((GLfloat)angle, 0., 0., -1.); #endif glScalef(GLfloat(scale_x), GLfloat(scale_y), 1.); glTranslatef(GLfloat(projection_delta.longitude.Native()), GLfloat(projection_delta.latitude.Native()), 0.); }
glm::mat4 ToGLM(const WindowProjection &projection, const GeoPoint &reference) { fixed angle = projection.GetScreenAngle().Degrees(); fixed scale = projection.GetScale(); const RasterPoint &screen_origin = projection.GetScreenOrigin(); const GeoPoint &screen_location = projection.GetGeoLocation(); const GeoPoint projection_delta = reference - screen_location; const fixed scale_r = scale * FAISphere::REARTH; const fixed scale_x = scale_r * screen_location.latitude.fastcosine(); const fixed scale_y = -scale_r; const glm::vec3 scale_vec(GLfloat(scale_x), GLfloat(scale_y), 1); glm::mat4 matrix = glm::scale(glm::rotate(glm::translate(glm::mat4(), glm::vec3(screen_origin.x, screen_origin.y, 0)), GLfloat(angle), glm::vec3(0, 0, -1)), scale_vec); matrix = glm::translate(matrix, glm::vec3(GLfloat(projection_delta.longitude.Native()), GLfloat(projection_delta.latitude.Native()), 0.)); return matrix; }
void TopographyFileRenderer::PaintLabels(Canvas &canvas, const WindowProjection &projection, LabelBlock &label_block) { if (file.IsEmpty()) return; fixed map_scale = projection.GetMapScale(); if (!file.IsVisible(map_scale) || !file.IsLabelVisible(map_scale)) return; UpdateVisibleShapes(projection); if (visible_labels.empty()) return; // TODO code: only draw inside screen! // this will save time with rendering pixmaps especially // we already do an outer visibility test, but may need a test // in screen coords canvas.Select(file.IsLabelImportant(map_scale) ? Fonts::map_label_important : Fonts::map_label); canvas.SetTextColor(Color(0x20, 0x20, 0x20)); canvas.SetBackgroundTransparent(); // get drawing info int iskip = file.GetSkipSteps(map_scale); #ifdef ENABLE_OPENGL Matrix2D m1; m1.Translate(projection.GetScreenOrigin()); m1.Rotate(projection.GetScreenAngle()); m1.Scale(projection.GetScale()); #endif // Iterate over all shapes in the file for (auto it = visible_labels.begin(), end = visible_labels.end(); it != end; ++it) { const XShape &shape = **it; if (!projection.GetScreenBounds().Overlaps(shape.get_bounds())) continue; // Skip shapes without a label const TCHAR *label = shape.get_label(); if (label == NULL) continue; const unsigned short *lines = shape.get_lines(); const unsigned short *end_lines = lines + shape.get_number_of_lines(); #ifdef ENABLE_OPENGL const ShapePoint *points = shape.get_points(); Matrix2D m2(m1); m2.Translatex(shape.shape_translation(projection.GetGeoLocation())); #else const GeoPoint *points = shape.get_points(); #endif for (; lines < end_lines; ++lines) { int minx = canvas.get_width(); int miny = canvas.get_height(); #ifdef ENABLE_OPENGL const ShapePoint *end = points + *lines; #else const GeoPoint *end = points + *lines; #endif for (; points < end; points += iskip) { #ifdef ENABLE_OPENGL RasterPoint pt = m2.Apply(*points); #else RasterPoint pt = projection.GeoToScreen(*points); #endif if (pt.x <= minx) { minx = pt.x; miny = pt.y; } } points = end; minx += 2; miny += 2; PixelSize tsize = canvas.CalcTextSize(label); PixelRect brect; brect.left = minx; brect.right = brect.left + tsize.cx; brect.top = miny; brect.bottom = brect.top + tsize.cy; if (!label_block.check(brect)) continue; canvas.text(minx, miny, label); } } }
void TopographyFileRenderer::Paint(Canvas &canvas, const WindowProjection &projection) { if (file.IsEmpty()) return; fixed map_scale = projection.GetMapScale(); if (!file.IsVisible(map_scale)) return; UpdateVisibleShapes(projection); if (visible_shapes.empty()) return; // TODO code: only draw inside screen! // this will save time with rendering pixmaps especially // we already do an outer visibility test, but may need a test // in screen coords #ifdef ENABLE_OPENGL pen.Set(); brush.Set(); #else shape_renderer.Configure(&pen, &brush); #endif // get drawing info #ifdef ENABLE_OPENGL const unsigned level = file.GetThinningLevel(map_scale); const unsigned min_distance = file.GetMinimumPointDistance(level) / Layout::Scale(1); #ifndef HAVE_GLES float opengl_matrix[16]; glGetFloatv(GL_MODELVIEW_MATRIX, opengl_matrix); #endif glPushMatrix(); fixed angle = projection.GetScreenAngle().Degrees(); fixed scale = projection.GetScale(); const RasterPoint &screen_origin = projection.GetScreenOrigin(); #ifdef HAVE_GLES #ifdef FIXED_MATH GLfixed fixed_angle = angle.as_glfixed(); GLfixed fixed_scale = scale.as_glfixed_scale(); #else GLfixed fixed_angle = angle * (1<<16); GLfixed fixed_scale = scale * (1LL<<32); #endif glTranslatex((int)screen_origin.x << 16, (int)screen_origin.y << 16, 0); glRotatex(fixed_angle, 0, 0, -(1<<16)); glScalex(fixed_scale, fixed_scale, 1<<16); #else glTranslatef(screen_origin.x, screen_origin.y, 0.); glRotatef((GLfloat)angle, 0., 0., -1.); glScalef((GLfloat)scale, (GLfloat)scale, 1.); #endif #else // !ENABLE_OPENGL const GeoClip clip(projection.GetScreenBounds().Scale(fixed(1.1))); AllocatedArray<GeoPoint> geo_points; int iskip = file.GetSkipSteps(map_scale); #endif for (auto it = visible_shapes.begin(), end = visible_shapes.end(); it != end; ++it) { const XShape &shape = **it; if (!projection.GetScreenBounds().Overlaps(shape.get_bounds())) continue; #ifdef ENABLE_OPENGL const ShapePoint *points = shape.get_points(); const ShapePoint translation = shape.shape_translation(projection.GetGeoLocation()); glPushMatrix(); #ifdef HAVE_GLES glTranslatex(translation.x, translation.y, 0); #else glTranslatef(translation.x, translation.y, 0.); #endif #else // !ENABLE_OPENGL const unsigned short *lines = shape.get_lines(); const unsigned short *end_lines = lines + shape.get_number_of_lines(); const GeoPoint *points = shape.get_points(); #endif switch (shape.get_type()) { case MS_SHAPE_NULL: break; case MS_SHAPE_POINT: #ifdef ENABLE_OPENGL #ifdef HAVE_GLES PaintPoint(canvas, projection, shape, NULL); #else PaintPoint(canvas, projection, shape, opengl_matrix); #endif #else // !ENABLE_OPENGL PaintPoint(canvas, projection, lines, end_lines, points); #endif break; case MS_SHAPE_LINE: { #ifdef ENABLE_OPENGL #ifdef HAVE_GLES glVertexPointer(2, GL_FIXED, 0, &points[0].x); #else glVertexPointer(2, GL_INT, 0, &points[0].x); #endif const GLushort *indices, *count; if (level == 0 || (indices = shape.get_indices(level, min_distance, count)) == NULL) { count = shape.get_lines(); const GLushort *end_count = count + shape.get_number_of_lines(); for (int offset = 0; count < end_count; offset += *count++) glDrawArrays(GL_LINE_STRIP, offset, *count); } else { const GLushort *end_count = count + shape.get_number_of_lines(); for (; count < end_count; indices += *count++) glDrawElements(GL_LINE_STRIP, *count, GL_UNSIGNED_SHORT, indices); } #else // !ENABLE_OPENGL for (; lines < end_lines; ++lines) { unsigned msize = *lines; shape_renderer.Begin(msize); const GeoPoint *end = points + msize - 1; for (; points < end; ++points) shape_renderer.AddPointIfDistant(projection.GeoToScreen(*points)); // make sure we always draw the last point shape_renderer.AddPoint(projection.GeoToScreen(*points)); shape_renderer.FinishPolyline(canvas); } #endif } break; case MS_SHAPE_POLYGON: #ifdef ENABLE_OPENGL { const GLushort *index_count; const GLushort *triangles = shape.get_indices(level, min_distance, index_count); #ifdef HAVE_GLES glVertexPointer(2, GL_FIXED, 0, &points[0].x); #else glVertexPointer(2, GL_INT, 0, &points[0].x); #endif glDrawElements(GL_TRIANGLE_STRIP, *index_count, GL_UNSIGNED_SHORT, triangles); } #else // !ENABLE_OPENGL for (; lines < end_lines; ++lines) { unsigned msize = *lines / iskip; /* copy all polygon points into the geo_points array and clip them, to avoid integer overflows (as RasterPoint may store only 16 bit integers on some platforms) */ geo_points.GrowDiscard(msize * 3); for (unsigned i = 0; i < msize; ++i) geo_points[i] = points[i * iskip]; msize = clip.ClipPolygon(geo_points.begin(), geo_points.begin(), msize); if (msize < 3) continue; shape_renderer.Begin(msize); for (unsigned i = 0; i < msize; ++i) { GeoPoint g = geo_points[i]; shape_renderer.AddPointIfDistant(projection.GeoToScreen(g)); } shape_renderer.FinishPolygon(canvas); } #endif break; } #ifdef ENABLE_OPENGL glPopMatrix(); #endif } #ifdef ENABLE_OPENGL glPopMatrix(); #else shape_renderer.Commit(); #endif }