QuintinZhangQQ / osmdroid

Automatically exported from code.google.com/p/osmdroid
0 stars 0 forks source link

overlay onSingleTapUp goes tits up when zoomed in #11

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. Run one of the samples with an overlay
2. Zoom in x12 (whatever)
3. Tapping on the overlay items stops working

What is the expected output? What do you see instead?

Tabbing should work ;> the x,y screen coords are very weird x > 1000 and y
becomes negative. It confuses me even more that the overlay items are
rendered correctly even though the x,y coords are off-screen?  

I have attached a screen shot where the x&y coords are rendered.

What version of the product are you using? On what operating system?

Using the latest code from SVN

Please provide any additional information below.

Original issue reported on code.google.com by carsten....@gmail.com on 22 Oct 2009 at 11:08

Attachments:

GoogleCodeExporter commented 9 years ago
In the code below the unprojected screen coords from the MotionEvent event are
compared to the coords returned from pj.toPixels(mItem.mGeoPoint, 
mCurScreenCoords);
which, as far as I can tell, are coords that are supposed to be mapped to real 
screen
coords (onDraw) via a Matrix set on the canvas when drawing.

So either the event coords need to be converted via pj.fromPixles? & 
pj.toPixels or
the matix used in ondraw should be accessible to convert (Matrix.mapPoints) the
pj.toPixels(mItem.mGeoPoint, mCurScreenCoords) result into coord that can 
compared
with the event.

In the ondraw code the canvans is also translated before the matrix is applied 
so
this may also have an impact on the coord comparison.

        public boolean onSingleTapUp(final MotionEvent event, final OpenStreetMapView
mapView) {
                final OpenStreetMapViewProjection pj = mapView.getProjection();
                final int eventX = (int)event.getX();
                final int eventY = (int)event.getY();

                final int markerWidth = this.mMarker.getIntrinsicWidth();
                final int markerHeight = this.mMarker.getIntrinsicHeight();

                /* These objects are created to avoid construct new ones every cycle. */
                final Rect curMarkerBounds = new Rect();
                final Point mCurScreenCoords = new Point();

                for(int i = 0; i < this.mItemList.size(); i++){
                        final T mItem = this.mItemList.get(i);
                        pj.toPixels(mItem.mGeoPoint, mCurScreenCoords);

                        final int left = mCurScreenCoords.x - this.mMarkerHotSpot.x;
                        final int right = left + markerWidth;
                        final int top = mCurScreenCoords.y - this.mMarkerHotSpot.y;
                        final int bottom = top + markerHeight;

                        curMarkerBounds.set(left, top, right, bottom);
                        if(curMarkerBounds.contains(eventX, eventY))
                                if(onTap(i))
                                        return true;
                }
                return super.onSingleTapUp(event, mapView);
        }

Original comment by carsten....@gmail.com on 25 Oct 2009 at 8:57

GoogleCodeExporter commented 9 years ago
Here is a solution. In the your overlay add a matrix member field and keep a 
ref to
the matrix used for the latest draw operation eg:

private Matrix lastDrawMatrix;

@Override
public void onDraw(Canvas c, OpenStreetMapView mapView) {
  super.onDraw(c, mapView);
  lastDrawMatrix = c.getMatrix();  
}

Then override:

@Override
public boolean onSingleTapUp(final MotionEvent event,
        final OpenStreetMapView mapView) {
    final OpenStreetMapViewProjection pj = mapView.getProjection();
    int eventX = (int) event.getX();
    int eventY = (int) event.getY();

    final int markerWidth = this.mMarker.getIntrinsicWidth();
    final int markerHeight = this.mMarker.getIntrinsicHeight();

    /*
     * These objects are created to avoid construct new ones every
     * cycle.
     */
    final Rect curMarkerBounds = new Rect();
    final Point mCurScreenCoords = new Point();

    for (int i = 0; i < this.mItemList.size(); i++) {
        final T mItem = this.mItemList.get(i);
        pj.toPixels(mItem.mGeoPoint, mCurScreenCoords);
        float[] xyPoint = { mCurScreenCoords.x, mCurScreenCoords.y };
        lastDrawMatrix.mapPoints(xyPoint);
        mCurScreenCoords.set((int) xyPoint[0], (int) xyPoint[1]);
        final int left = mCurScreenCoords.x - this.mMarkerHotSpot.x;
        final int right = left + markerWidth;
        // the dreaded 50 px default android translation
        // http://mobiledevelop.blogspot.com/2009/02/android-canvas translation-discussion.html
        final int top = mCurScreenCoords.y - this.mMarkerHotSpot.y - 50;
        final int bottom = top + markerHeight;

        curMarkerBounds.set(left, top, right, bottom);
        if (curMarkerBounds.contains(eventX, eventY))
            if (onTap(i))
                return true;
        }
            return super.onSingleTapUp(event, mapView);
    }

Original comment by carsten....@gmail.com on 26 Oct 2009 at 11:54

GoogleCodeExporter commented 9 years ago
The draw coordinates are now signed world-pixel-coordinates. If the zoom level 
is 5
and the tiles have a size of 256=2^8, the world size is 2^(5+8)=8192. The
getScrollX() and getScrollY() will be in the range of -4096 to 4095.
This makes it easier to use the standard view scrolling mechanism (fling etc.)

Original comment by ThyMythos@googlemail.com on 29 Oct 2009 at 9:14

GoogleCodeExporter commented 9 years ago
I spent a day on this issue.
I wrote a function and now it works! ;)

There is a little inaccuracy in the Y coordinates. If you knows how to solve it 
please post the solution in this website.

@Override
    public final boolean onSingleTapUp(MotionEvent event, MapView mapView) {
        /* onTap by Michele Riso - zeroc87@gmail.com */

        final Projection pj = mapView.getProjection();
        final int eventX = (int)event.getX();
        final int eventY = (int)event.getY();

        final int markerWidth = this.mDefaultMarker.getIntrinsicWidth();
        final int markerHeight = this.mDefaultMarker.getMinimumHeight();

        /* These objects are created to avoid construct new ones every cycle. */
        Point mCurScreenCoords = new Point();
        Point mItemScreenCoords = new Point();

        for(int i = 0; i < this.size() ; i++){
            final Item mItem = this.getItem(i);
            mItemScreenCoords = pj.toMapPixels(mItem.getPoint(), mItemScreenCoords); 
            mCurScreenCoords = pj.fromMapPixels(eventX, eventY, mCurScreenCoords);

            int diffX = Math.abs(mItemScreenCoords.x-mCurScreenCoords.x); //Abs() distance from touchevent and the marker (X)
            int diffY = Math.abs(mItemScreenCoords.y-mCurScreenCoords.y); //Abs() distance from touchevent and the marker (Y)

            if(diffX<=markerWidth && diffY<=markerHeight)   //If I touched inside the marker
                if(onTap(i))
                    return true;
        }

        super.onSingleTapUp(event, mapView);

        return true;

    }

    public boolean onTap(int index){

           // DO SOMETHING

        return true;

    }

Original comment by zero...@gmail.com on 11 Sep 2011 at 11:13