virtual void EndFan() { if (fans.full()) return; // remove unnecessary inclusion of origin if next and last points are identical unsigned start = 0; const size_t gsize = g.size(); if (gsize > 2 && g[gsize - 1] == g[1]) start = 1; if (gsize < start + 3) return; // Perform clipping on the GeoPointVector (Result: clipped) unsigned size = clip.ClipPolygon(clipped, g.raw() + start, gsize - start); // With less than three points we can't draw a polygon if (size < 3) return; // Work directly on the RasterPoints in the fans vector fans.Append(size); // Convert GeoPoints to RasterPoints for (unsigned i = 0; i < size; ++i) fans.Append(proj.GeoToScreen(clipped[i])); }
static void test_clip_line(const GeoClip &clip, GeoPoint a, GeoPoint b, const GeoPoint a2, const GeoPoint b2) { clip.clip_line(a, b); ok1(equals(a, a2)); ok1(equals(b, b2)); }
static void test_clip_polygon(const GeoClip &clip, const GeoPoint *src, unsigned src_size, const GeoPoint *result, unsigned result_size) { GeoPoint dest[64]; unsigned dest_size = clip.clip_polygon(dest, src, src_size); ok1(equals(result, result_size, dest, dest_size)); }
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 }