Opened 16 years ago

Closed 15 years ago

Last modified 15 years ago

#1262 closed bug (fixed)

Point and Multipoint symbols are not drawn centered at location

Reported by: smizuno Owned by: homann
Priority: minor: annoyance Milestone:
Component: Marker Symbols Version: Trunk
Keywords: Cc:
Must Fix for Release: No Platform: All
Platform Version: Awaiting user input: no

Description

Point symbols are drawn approximately 2 pixels left and up from where they should be. I'm not quite sure of the amount, due to rounding errors in calculating the display location.

Multipoint symbols are drawn with the upper left corner of the symbol at the location of the point.

Expect that the symbol center would be at the point location.

This causes some frustration when using Identify, especially if the Search Radius is less than 0.5% or so.

attached is a 16x extract from a screen shot of examples - the blue square symbol is a POINT, the magenta square is a MULTIPOINT, three dark magenta lines start at the location the two point types are located at. I painted a black pixel at that location for reference. Also shown is an Identify highlight for the point/multipoint (both get the highlight as shown) centered at the location as expected.

Attachments (3)

Point_Multipoint_position_error.png (8.6 KB ) - added by smizuno 16 years ago.
data_for_1262.zip (3.0 KB ) - added by smizuno 16 years ago.
data files to test point alignment
patch_for_1262.txt (11.9 KB ) - added by smizuno 15 years ago.
patches QgsMarkerCatalogue

Download all attachments as: .zip

Change History (12)

comment:1 by timlinux, 16 years ago

Hi

Could you provide a small dataset I can use to replicate? I am interested to see if this patch will fix the point / multipoint alignment issues:

Index: ../src/core/qgsvectorlayer.cpp =================================================================== --- ../src/core/qgsvectorlayer.cpp (revision 9238) +++ ../src/core/qgsvectorlayer.cpp (working copy) @@ -3293,7 +3293,8 @@

transformPoint( x, y, theMapToPixelTransform, ct ); QPointF pt(x - (marker->width()/2), y - (marker->height()/2)); QPointF pt(x/markerScaleFactor - (marker->width()/2), y/markerScaleFactor - (marker->height()/2));

  • QPointF pt( x, y );

+ QPointF pt( x*rasterScaleFactor - ( marker->width() / 2 ), y*rasterScaleFactor - ( marker->height() / 2 ) ); + QPointF pt( x, y );

#if defined(Q_WS_X11)

Work around a +/- 32768 limitation on coordinates in X11

by smizuno, 16 years ago

Attachment: data_for_1262.zip added

data files to test point alignment

comment:2 by smizuno, 16 years ago

data_for_1262.zip contains point.shp, multipoint.shp, linestring.shp, postgis_create_tables.txt. The PostGIS tables are what was used to show the point alignment problem screenshot. The shapefiles created from the PostGIS layers and also show the same.

The CRS for all is EPSG:26915. Use the filled square symbol of size 10.0 or so for the points. For the linestring use outline width of 0.00 which gives a 1 pixel line.

The point symbols should be centered at the convergence of the three lines.

comment:3 by smizuno, 16 years ago

On further testing I have found that at least some SVG symbols are drawn centered on the point location (within one pixel).

The internal symbols are the ones that are off by two pixels. I have also noticed that they appear clipped under some conditions. Observe the filled circle and square in the Point Symbol list. The left and top are clipped on my Windows installation.

comment:4 by homann, 16 years ago

Owner: changed from nobody to homann
Priority: major: does not work as expectedminor: annoyance or enhancement
Status: newassigned

I did look into similar error two(?) years ago, and was then uable to draw the images correctly. Something wrong within Qt I believe. maybe it's fixed now, I'll have a look again.

Did you compiel it yourself, ans if so, which Qt version?

comment:5 by homann, 16 years ago

It's coming back to me. The points are bitmaps which are referenced with the upper left corner. There is some fudging needed to find the delta-X and delta-Y from top left to center, and it is not reliable.

comment:6 by homann, 16 years ago

Resolution: wontfix
Status: assignedclosed

I think we can close this bug, multipoints are now drawn exactly like pointts, but not in dead center. Adjusting the outline width of the symbol changes the center placement of the symbol slightly. I don't think we can dio better as long as we use QImage?

comment:7 by smizuno, 15 years ago

Resolution: wontfix
Status: closedreopened

I reopen this ticket because I have a patch for QgsMarkerCatalogue that draws the hard-coded point symbols more accurately than the existing one does.

I took this as a challenge as I believed that it was possible to draw the point symbols accurately, at least within one pixel.

The problems I found:

  1. some calls (for circle and square) to QPainter::drawXXX() functions had two points passed in - these should have been upper left location and size; this is the main reason that the fudge factors had to be employed.
  2. calls to QPainter::drawXXX() functions had float calculations, but the functions took integers - this causes whole pixel differences (left and up) due to truncation plus any other differences that occur elsewhere. This is why the symbols were clipped on the left and top.
  3. the QImage may have an even number of pixels on a side, which makes it difficult to center.

What my patch does in imageMarker() and hardMarker():

  1. makes the QImage have an odd number of pixels for width and height, so the center of the image can be placed properly. Also, the image width and height are odd for SVG rendering.
  2. allows for the pen width, including Qt cosmetic pen (width=0, actually one pixel) when sizing QImage
  3. uses floating point calculations, objects, and calls to the draw functions - QPointF, QPolygonF, QRectF, and such, leaving the conversion to integer pixel locations to the Qt draw functions.
  4. the QImage size is passed to hardMarker() for centering the figure when drawing it. The hardMarker() function has an additional parameter. It is a private function, so the API is not affected.
  5. provides proper rounding of float values to integer when centering the figure
  6. pictureMarker() isn't currently used, I believe, so it is modified only so function calls are correct. Perhaps this function should be removed?
  7. includes M_PI and DEG2RAD macros for some figure calculations
  8. removes the iostream include as this interferes with the data stream operators used to send data into QPolygonF

Once I had it working I created three additional symbols (equilateral triangle, pentagon, regular star) using mathematical models, which were drawn centered as expected.

Now, symbols like the crosses are drawn on the map canvas with the point at which the lines cross at the location in question (within one pixel).

As submitted, filled figures are drawn at the size specified and then the outline is added - half inside, half outside the figure - as Qt's notion of outline. I provided some alternate code (the #if 0 block in hardMarker ) to keep the overall symbol size at the specified size.

The patch is against r9611.

I am using Windows XP and Qt 4.4.0; also have tested on Linux / Qt 4.3.3

by smizuno, 15 years ago

Attachment: patch_for_1262.txt added

comment:8 by homann, 15 years ago

Resolution: fixed
Status: reopenedclosed

Excellent! Many thanks!

Applied in r9636.

comment:9 by (none), 15 years ago

Milestone: Version 1.0.0

Milestone Version 1.0.0 deleted

Note: See TracTickets for help on using tickets.