Interesting/ANDROID | Posted by hyena0 2009. 8. 14. 21:32

[Android] 지도에 Path 그리기 확인


  지도에 Path 그리기 확인

  구글맵을 이용하는 운전 경로를 찾아주는 코드가

  대만의 블로거가 포스팅한 내용을 참조해서 작성해 보았습니다.

  주요한 내용은 두 지점의 위도, 경도의 Geo 정보만 있다면

  구글맵에서 KML 파일을 가져 올 수 있고, 

  KML 파일을 가져와서 Parsing 하여 경로의 정보를 가지고

  Overlay 클래스를 이용하여 지도에 겹쳐서 그린다는 내용입니다.

  예) http://maps.google.com/maps?f=d&hl=en&saddr=25.04202,121.534761&daddr=25.05202,121.554761&ie=UTF8&0&om=0&output=kml

  전체 소스는 링크된 사이트로 가시면 볼 수 있으니 붙이지 않습니다.

  다만 테스트를 해보면 나와있는 지점에 대한 Path 는 확인되나

  한국의 특정지점에 대해 입력하면 동작하지 않는 것을 알 수 있습니다.

  수정한 코드가 오류인지 확인해 보았으나 그렇지 않고,

  구글맵에서 한국지도에 대한 Path 정보를 KML파일로 제공하지 않는 것 같습니다.

  그래서 한국지도의 두지점에 대한 정보를 입력하면 KML 파일의 크기가 "0" byte 라는 것을 알 수 있습니다.

  아래의 확인결과는 안드로이드의 구글맵이 GPS 정보가 제대로 안잡히면 마운틴뷰로 설정되게 되어 있는데,

  그 근방에 대해 마커를 터치할때 마다 Path 를 표시하게 한 결과 입니다.



  소스코드는 정상이었으나, 한국 지도에는 아직 동작하지 않는 것 같네요.

  그리고 그 기준은 정확히 확인해 보진 않았지만, 장거리에서도 KML 파일이 정상적으로 동작하지 

  않는 것 같습니다. 미국 기준으로 몇개의 주를 걸치도록 지도에 입력을 해보니 마커만 표시되고

  Path는 그려지지 않네요. 






댓글을 달아 주세요


  OpenGL 로 원하는 도형 만들기

  android로 OpenGL ES 를 이용하는 예제는

  Dev site 에서 찾을 수 있습니다.

  예제는 Cube.java 와 CubeRenderer.java 입니다.

  그런데 여기서 Cube 만 다루다 보니 

  다른 도형을 어떻게 해야 할지 좀 막막하더군요.

  Web 상의 OpenGL 문서를 뒤져보고 해도 기초만 나오기 때문에

  좀처럼 이해하기 어려웠습니다.

  원하는 도형을 한번에 만들어서 Renderer 에서 그리면 좋을텐데,

  꼭지점을 이용하여 그리는 방식을 이해하기 어렵더군요.

  그간 고민한게 효과가 있었던지, 드디어 알게 되었습니다.

  일단 Cube.java 파일을 봅시다.

class Cube

{

    public Cube()

    {

        int one = 0x10000;

        int vertices[] = {

               //x,    y,    z,

                -one, -one, -one, // index #0

                one, -one, -one,  // index #1

                one,  one, -one,  // index #2

                -one,  one, -one, // index #3

                -one, -one,  one, // index #4

                one, -one,  one,  // index #5

                one,  one,  one,  // index #6

                -one,  one,  one, // index #7

        };


        int colors[] = {

              //R, G, B, A

                0,    0,    0,  one,

                one,    0,    0,  one,

                one,  one,    0,  one,

                0,  one,    0,  one,

                0,    0,  one,  one,

                one,    0,  one,  one,

                one,  one,  one,  one,

                0,  one,  one,  one,

       

        };


        byte indices[] = {

                // Triangle 로 쪼개는 인덱스 번호들

                0, 4, 5,    0, 5, 1,

                1, 5, 6,    1, 6, 2,

                2, 6, 7,    2, 7, 3,

                3, 7, 4,    3, 4, 0,

                4, 7, 6,    4, 6, 5,

                3, 0, 1,    3, 1, 2,

        

        };


        // Buffers to be passed to gl*Pointer() functions

        // must be direct, i.e., they must be placed on the

        // native heap where the garbage collector cannot

        // move them.

        //

        // Buffers with multi-byte datatypes (e.g., short, int, float)

        // must have their byte order set to native order


        ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length*4);

        vbb.order(ByteOrder.nativeOrder());

        mVertexBuffer = vbb.asIntBuffer();

        mVertexBuffer.put(vertices);

        mVertexBuffer.position(0);


        ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length*4);

        cbb.order(ByteOrder.nativeOrder());

        mColorBuffer = cbb.asIntBuffer();

        mColorBuffer.put(colors);

        mColorBuffer.position(0);


        mIndexBuffer = ByteBuffer.allocateDirect(indices.length);

        mIndexBuffer.put(indices);

        mIndexBuffer.position(0);

        

    }


    public void draw(GL10 gl)

    {

        gl.glFrontFace(gl.GL_CW);

        gl.glVertexPointer(3, gl.GL_FIXED, 0, mVertexBuffer);

        gl.glColorPointer(4, gl.GL_FIXED, 0, mColorBuffer);

        gl.glDrawElements(gl.GL_TRIANGLES, 36, gl.GL_UNSIGNED_BYTE, mIndexBuffer);

        

    }

    

    private IntBuffer   mVertexBuffer;

    private IntBuffer   mColorBuffer;

    private ByteBuffer  mIndexBuffer;

}


그리고 anddev.org 사이트에서 찾아보면 나오는 설명에서 아래의 그림처럼
꼭지점들(vertices)을 정하고, 색을 정하고, 그림을 그리기 위한 조각들을 결정합니다.

 

위의 그림처럼 꼭지점이 인덱스가 "0" 이면 (-1,-1,-1) 이고,  "1"이면 (1,-1,-1)  의 순으로 지정됩니다.
vertices[] 내의 좌표 순서가 바로 인덱스 순서라고 보면 되지요.
그리고 glDrawElements 함수로 그리기 위해 GL_TRIANGLES를 이용했는데 아래 그림처럼 삼각형으로 잘라지지요.

 

삼각형의 번호는 인덱스의 번호로 3개씩 짝을 짓고 있고 glFrontFace 함수에서 시계방향을 선택했으므로
인덱스 번호의 순서를 결정할 수 있습니다.

그러면 다른 도형의 형태를 어떻게 할 것인가? 감이 오시는지...

안오신다면 아래의 그림을 다시 한번 보면 이해가 될 것 같네요.


만약 집모양을 만든다고 하면 좌표값의 크기를 정하고, 좌표값에 맞는 인덱스를 정한 후 

도형의 면을 그릴 수 있도록 삼각형, Loop 등의 방법을 결정해 주면 됩니다.




댓글을 달아 주세요

  1.  댓글주소  수정/삭제  댓글쓰기 dualwield 2009.11.27 15:56 신고

    감사합니다. 많은 도움되었습니다^^


  Camera와 OpenGL 동시에 표시하기

  안드로이드에서 카메라와 OpenGL을 동시에 표시하는 

  것을 구현하려고 했더니 잘안되어서 검색을 좀 해봤습니다. 

  해당 이슈는 이미 Google groups 에서 논의되었었는데

  
  제목으로 검색하시면 찾을 수 있습니다.

  제가 처음 시도한 것처럼 카메라 Preview 를 먼저 보이게 하고

  투명한 배경의 OpenGL 화면을 보이게 하려고 했는데

  카메라만 보인다는 내용입니다.

  저역시 카메라만 보이는 것을 확인할 수 있었는데,

  Julius 라는 사람이 쓴 답글을 보면 순서를 거꾸로 하여

  OpenGL을 먼저하고 나중에 카메라를 더하라는 것이 있었습니다.

  그렇게 해보니 신기하게도 카메라 영상과 OpenGL 이 겹쳐져 나오더군요.

  <<디바이스 실행화면>>



  아래의 코드대로 해보시면 아시겠지만, 1.5 버전의 에뮬레이터에서

  투명한 배경이 동작하지 않는 것을 확인했습니다. 

  제가 설치한 에뮬레이터의 버전 문제일지 모르겠으나, 투명이 아니라 

  백색화면에 그래픽 객체는 나오지 않더군요. 

  또다른 구글그룹스의 내용에는 멀티 SurfaceView 를 권장하지 않는다고

  안드로이드 프레임웍 엔지니어가 답글을 달았군요.

  코드는 Cube.java 와 CubeRenderer.java 를 참조하고 있습니다.

  public class camGL extends Activity {

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);


        requestWindowFeature(Window.FEATURE_NO_TITLE);

        this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

        

        Preview mPreview = new Preview(this); 

        

        mRenderer = new CubeRenderer(true);

        

        mGLSurfaceView = new GLSurfaceView(this);

        //translucent

        mGLSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);

        mGLSurfaceView.getHolder().setFormat(PixelFormat.RGBA_8888);

        mGLSurfaceView.setRenderer(mRenderer);

        

     //OpenGL 먼저 표시하기

        setContentView(mGLSurfaceView); 

     //그 다음 카메라 표시하기

        addContentView(mPreview, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));

        

    }

    

    private GLSurfaceView mGLSurfaceView;

    private CubeRenderer mRenderer;


    @Override

    protected void onResume() {

        super.onResume();

        

    }


    @Override

    protected void onPause() {

        super.onPause();

        

    }

    

}

//////////////////////////////

// camer preview

////////////////////////////

class Preview extends SurfaceView implements SurfaceHolder.Callback { 

    SurfaceHolder mHolder

    Camera mCamera

    

    boolean mPreviewRunning = false;

    

    Preview(Context context) { 

        super(context); 

        mHolder = getHolder(); 

        mHolder.addCallback(this); 

        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 

        

    } 


    Camera.PictureCallback mPictureCallback = new Camera.PictureCallback() {

        public void onPictureTaken(byte[] data, Camera c) {

            mCamera.startPreview();

        }

    };

    

    public void surfaceCreated(SurfaceHolder holder) { 

        mCamera = Camera.open(); 

        try{

        mCamera.setPreviewDisplay(holder);

         if (false) throw new IOException(); 

        }catch (IOException e){

        //do something

        }

    } 


    public void surfaceDestroyed(SurfaceHolder holder) { 

        mCamera.stopPreview();

        mPreviewRunning = false;//// added

        mCamera = null

    } 


    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { 

     if (mPreviewRunning) {    ///added

            mCamera.stopPreview();

        }

    

        Camera.Parameters parameters = mCamera.getParameters(); 

        parameters.setPreviewSize(w, h); 

        mCamera.setParameters(parameters);

        mCamera.startPreview(); 

        //

        try{

        mCamera.setPreviewDisplay(holder);

         if (false) throw new IOException(); 

        }catch (IOException e){

        //do something

        }

        mCamera.startPreview();

        mPreviewRunning = true///added

    } 


}

댓글을 달아 주세요

  1.  댓글주소  수정/삭제  댓글쓰기 2010.03.08 19:30

    비밀댓글입니다

  2.  댓글주소  수정/삭제  댓글쓰기 2010.06.10 22:49

    비밀댓글입니다

    •  댓글주소  수정/삭제 hyena0 2010.06.11 22:58 신고

      회사에서 부서가 바뀌는 바람에 여유가 없군요. 질문 주신 내용을 시도할 여유가 없어 생각만 남깁니다. 코드상 보면 오픈지엘을 먼저 표시하고 카메라를 추가한 것이기 때문에, 순서적으로 본다면 카메라를 먼저 제거하고 오픈지엘을 닫는 것이 맞을 것 같습니다. 뷰자체의 변경이 잦다고 한다면, visibilty 설정을 바꾸어 보는 것도 방법으로 생각되네요. 현재 안드로이드 개발은 펌웨어의 적용한계, 아이폰개발 등의 여러 상황으로 잠시 멈춘 상태라 질문에 제대로 답변못드리는게 아쉽군요.

  3.  댓글주소  수정/삭제  댓글쓰기 akarae 2010.06.18 23:39 신고

    답변 감사합니다
    결국엔 구글링으로 해결했네요 ^^;
    많이 바쁘신듯한데 건강 잘 챙기시길 바랍니다

  4.  댓글주소  수정/삭제  댓글쓰기 송지혜 2010.06.20 21:19 신고

    저..이거아무리해도 안됩니다ㅜㅜ 혹시 도움을 주실수있나요?
    대학생인데요, 에뮬레이터에서 웹캠으로 영상 입력받아서 하는데,진짜 이걸로 5일째 검색 검색 코딩 하고있는데 안되요......흑...그래서일단 검정화면으로 만들고있긴한데 도움을 주실수있나요 ㅜㅜㅜ 혹시 가능하시다면
    jea8805q@naver.com으로 연락주시면 진짜감사하겠습니다!

    •  댓글주소  수정/삭제 hyena0 2010.06.21 01:08 신고

      카메라 관련된 부분은 실제 폰에서 수행해 보시길 권장합니다. 왜냐하면, 웹캠부분의 소스코드를 결국엔 수정해야 하는데 또 다시 그만큼의 수고를 해야 할 것입니다. 에뮬레이터로 할 때에는 아실지도 모르겠지만, 다음의 주소에서 내용을 참조하십시오. http://www.tomgibara.com/android/camera-source

  5.  댓글주소  수정/삭제  댓글쓰기 송지혜 2010.06.21 10:32 신고

    대학생이고, 개인프로젝트로 만드는거라다보니 폰이없네요..ㅜㅜ 저 쏘스로 불러오는건 아니고 openCV해서 웹캠 소켓으로 받아오는 소스를 이용하였습니다...

  6.  댓글주소  수정/삭제  댓글쓰기 송지혜 2010.06.21 10:33 신고

    혹시 3d 만들어서 안드로이드에 포팅하는 방법 포스팅하신다구했는데..ㅇ ㅏ직안올라와서요><
    알고싶습니다! 그.. 파이썬코드를 직접 바꿔서 쓰는 방법말고, 그림으로 obj,파일로 추가해서 하는방법이 있다고듣긴해쓴데..

    •  댓글주소  수정/삭제 hyena0 2010.06.24 23:56 신고

      3D 모델은 해당포스트에 질문해주시고, 좀 더 명확히 써주시면 답변을 해드릴수 있을것 같네요. 그림으로, obj 파일로 추가하는 방법이라는게 어떤건지요?

  7.  댓글주소  수정/삭제  댓글쓰기 baka11 2010.12.16 00:25 신고

    OpenGL로 객체를 그릴때 원하는 위치에 그릴 수 있나요? 어떤 한 점 x,y 좌표값이 있으면 그 좌표가 움직일때마다 객체도 따라 움직이길 원해서요..

    •  댓글주소  수정/삭제 hyena0 2010.12.20 01:14 신고

      네 당연히 가능합니다. 오픈지엘의 기본적인 내용을 파악하시면 더 쉽게 이해할 수 있는 부분으로 생각되는데요. 객체 자체를 이동시키는 함수는 glTranslatef(x,y,z) 이고 회전하는 함수는 glRotate(degree,x,y,z) 가 있습니다. 이동 및 회전에 대한 위치조절은 행렬의 대수관계를 알고 있다면 더 유용하겠습니다. 여기에서 선형대수학을 활용할 수 있습니다. 안드로이드로 접근하신다면 다음의 사이트를 참조하십시오. http://insanitydesign.com/wp/projects/nehe-android-ports/?sms_ss=dzone

  8.  댓글주소  수정/삭제  댓글쓰기 준호씨 2011.06.12 12:34 신고

    이거 오래 되어서 패치가 된 걸까요? 지금
    setContentView(mPreview);
    addContentView(mGLSurfaceView, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
    순서로 하니 잘 나오네요. 그런데 역으로 하나 똑바로 하나 3D가 나왔다가 안나왔다가 그러네요;;
    그나마 순서대로 하면 좀 더 잘 나오는 편이고 역순으로 하면 덜 나오는 편이고;; 아무튼 좀 더 테스트 해 봐야 겠습니다.