moagrius / TileView

TileView is a subclass of android.view.ViewGroup that asynchronously displays, pans and zooms tile-based images. Plugins are available for features like markers, hotspots, and path drawing.
MIT License
1.46k stars 335 forks source link

how can I drag map automatically where I search on map #102

Closed dygka closed 10 years ago

dygka commented 10 years ago

Hi, I found here new I am designing indoor map in android. I am using TileView. I will explain how it is work.

1) When I search 302 room,It put pin on 302 room. I put 302 room's x,y coordinate on my sqlite

2) I can drag map lift and right side

But map is very big and I show big map in picture when I write 311 room which is end of map it put pin. But I have to drag map for showing 311 room pin. _How can I do drag automatically.For example When I write 311, it should go here._

Do you give me any advice?

first picture is on my android device screen shut. I can drag left and right.

enter image description here

And this is my real map.

enter image description here

And this is code of my main

package com.qozix;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;

import com.qozix.data.ClassData;
import com.qozix.data.ClassRepository;
import com.qozix.tileview.TileView;
import com.qozix.tileview.markers.MarkerEventListener;

public class BuildingPlansTileViewActivity extends TileViewActivity {

    private final static int SEARCH_REQUEST=999;
    private String className;
    private ImageView currentMarker;
    private ClassRepository classRepository=new ClassRepository();

    @Override
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        // multiple references
        TileView tileView = getTileView();

        // size of original image at 100% scale
        tileView.setSize(1500, 1000);

        // detail levels
        tileView.addDetailLevel(1.000f, "tiles/harita2/%col%_%row%.jpg",
                "samples/harita.jpg");
        // tileView.addDetailLevel( 0.500f, "tiles/plans/500/%col%_%row%.jpg",
        // "samples/plans.JPG");
        // tileView.addDetailLevel( 0.250f, "tiles/plans/250/%col%_%row%.jpg",
        // "samples/plans.JPG");
        // tileView.addDetailLevel( 0.125f, "tiles/plans/125/%col%_%row%.jpg",
        // "samples/plans.JPG");

        // let's use 0-1 positioning...
        tileView.defineRelativeBounds(0, 0, 896, 507);

        // center markers along both axes
        tileView.setMarkerAnchorPoints(-0.5f, -0.5f);

        // add a marker listener
        tileView.addMarkerEventListener(markerEventListener);

        // scale it down to manageable size
        tileView.setScale(0.5);

        // center the frame
        frameTo(0.5, 0.5);

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // TODO Auto-generated method stub
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.actionmenu, menu);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        switch (item.getItemId()) {
        case R.id.searchItem:

            Toast.makeText(BuildingPlansTileViewActivity.this,
                    "Arama yapiliyor", Toast.LENGTH_SHORT).show();
            showSearchDialog();
            return true;

        default:
            return super.onOptionsItemSelected(item);
        }
    }
    private void showSearchDialog(){
        Intent intent=new Intent(BuildingPlansTileViewActivity.this,SearchActivity.class);
         startActivityForResult(intent,SEARCH_REQUEST);

    }
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode ==SEARCH_REQUEST && resultCode == RESULT_OK) {
             String classQuery=data.getStringExtra("classQuery");       
             Log.i("KadirHas", "Sonuc Sinif sorgusu "+classQuery);
             ClassData classData=classRepository.findData(classQuery);
             if(classData!=null){
                 addPin(classData.getClassX(), classData.getClassY());
             }else{
                 Toast.makeText(BuildingPlansTileViewActivity.this,
                    "Sinif bulunamadi '"+classQuery+"'", Toast.LENGTH_SHORT).show();
             }
        }
    }

    private void addPin(double x, double y) {
        if(currentMarker!=null){
            getTileView().removeMarker(currentMarker);
        }
        currentMarker = new ImageView(this);
        currentMarker.setImageResource(R.drawable.push_pin);
        getTileView().addMarker(currentMarker, x, y);
    }

    private MarkerEventListener markerEventListener = new MarkerEventListener() {
        @Override
        public void onMarkerTap(View v, int x, int y) {
            Toast.makeText(getApplicationContext(), "You tapped a pin",
                    Toast.LENGTH_LONG).show();
        }
    };
}
moagrius commented 10 years ago

I'm not 100% sure I'm understanding what you want to do, but there are a number of positioning methods, including

There are more, but these are the ones you probably want to limit yourself to.

These are all described in the javadocs.

Post back if that doesn't answer your question.

dygka commented 10 years ago

I have search button. I am searching number(301.302.. etc) which are rooms name. for example when I write on Google map some place, it zoom on it ,or automatically drag it where I search.I want to do same think. When I search room,It put pin on it. But I have to scroll myself. I hope I can explain it. could you give me example algorithm. for example *311 is x=40 y=50 if I used this method , is it go automatically on pins 311 ?

moagrius commented 10 years ago

I'm still not sure I know what you want, and I'm not sure how I could provide an algorithm for unknown quantities. I have no idea how your map or coordinate system is laid out. It doesn't look like your rooms are the same size, so I don't know how we'd be able to tell where that was in the coordinate space?

Generally speaking, since you have the map outside of tileview, you can tell the x and y of each room from the base image (for example, you could see it in photoshop). You can also tell (again, without TileView) the percentages. I'd suggest you use those as your coordinate system.

There's no way anyone could tell what x and y your room 311 without trying to read the pixels of the map and OCR the digits, which isn't realistic.

I'm a little confused as to why there's a problem, since it's your map, and you have access to all the information, position, etc - why don't you find the pixel location of 311 (like in photoshop), then record that in some data structure (a database, or just an in-memory collection), and when they search for 311, use TileView.moveTo to those same coordinates?

demirkolderya commented 10 years ago

we are designing same project. We do have all coordinates ( these are pixel and we keep them in Sqlite with x, y coordinates) for our classroom. For example Google map when you search some place , marker and map view goes that place. (For example i am in Turkey and i search some place in England and when location is found . marker and map view moves from Turkey to England automatically) Is that possible in TileView too? Thank you.

moagrius commented 10 years ago

I think I understand.

The TileView uses raw pixels by default.

So do not call defineRelativeBounds at all...

OR call defineRelativeBounds with 0, 0, actual width of image, actual height of image

If you have already set it for some reason, unset it with undefineRelativeBounds

Assuming that the TileView does not have a custom coordinate space (that relative bounds were never set, or they were unset), all positioning methods will use raw pixels of the original image, regardless of scale.

So if room 311 was at x=40, and y=50, you could say

tileView.moveTo(40, 50);

That would scroll the tile view instantly, so the top left corner of room 311 would be at the top left corner of the viewport.

If you'd rather have it centered to the coordinate, use the alternate signature:

tileView.moveToAndCenter(40, 50);

If you want it to scroll to that position (with animation, instead of immediately moving), use slideTo...

tileView.slideTo(40, 50);

And centered...

tileView.slideToAndCenter(40, 50);

Alternatively, if you have a reference to a marker already at the place you want to scroll, you can use moveToMarker, the last argument of which is true for animation, false (or omitted) for immediate repositioning.

Is that about what you were looking for?

demirkolderya commented 10 years ago

Thank you so much for reply:) We did use defineRelativeBounds.. so i guess this method keep our map immovable. After we change that we can use whole method you suggested.. should we create method for that?and use like this: tileView.moveTo(getClassX(), getClassY());

moagrius commented 10 years ago

The defineRelativeBounds allows you to use a custom coordinate space (like latitude and longitude, or percentage, or columns and rows, etc).

Here's some more info: https://github.com/moagrius/TileView/wiki/Positioning

If you don't need it, then definitely don't use it.

You're free to create your own methods, or even extend the base class, for example...

public class ClassRoomMapView extends TileView {
  public void moveToClass(ClassRoomInstance classRoom){
    // query your database against the passed in classRoom and get coordinates...
   moveTo(x, y);
  }
}

Whatever works for you - feel free.

demirkolderya commented 10 years ago

private void moveTo(double x ,double y) { getTileView().moveTo(x, y); } i did something like that and i guess its working.

thank you again:)

by the way do you suggest anyweb site other than ImageMagick to crop our map.?

moagrius commented 10 years ago

in my experience, the program imagemagick is the most efficient and flexible; here's some info: https://github.com/moagrius/TileView/wiki/Creating-Tiles

most websites that let you upload a photo are A) way too limited in terms of file size, and B) don't let you select a tile size, but rather a number of columns (which could lead to wierd sized tiles).

photoshop is limited to the number of tiles it'll product.

i'm sure there's other ways to generate tiles, but IME imagemagick has been the most reliable and efficient.

unrelated, it looks like you're using the TileViewDemo project as a base. That's fine, but make sure to get the latest jar release from here, and delete the old lib that comes with the Demo project.

demirkolderya commented 10 years ago

yes. its really perfect project for indoor mapping (we did lots of searching including OpenStreetMap) , TileView is the best :) thanks for advice we will use latest jar.. One more thing about creating tiles : Lets say our map 1000_1000 and we have two 300_300 classroom and one 500_350 saloon. and we want to create 200200 tiles , it will crop our map into tile with same size but room has different sizes. is that important by using ; tileView.addDetailLevel(0,125f, "tiles/mapTile/%col%%row%.jpg", "samples/map.jpg"); this code?

moagrius commented 10 years ago

The default tile size is 256x256. To use a custom tile size, you need to use the appropriate signature: http://moagrius.github.io/TileView/com/qozix/tileview/TileView.html#addDetailLevel(float, java.lang.String, java.lang.String, int, int)

tileView.addDetailLevel(0,125f, "tiles/mapTile/%col%_%row%.jpg", "samples/map.jpg", 200, 200);

demirkolderya commented 10 years ago

thank you so much for your help. if we stuck with a issue, can i ask them again?

moagrius commented 10 years ago

Of course.