2012-01-23 30 views
3

由於前幾天Google Sky Map開放源代碼,我正在努力研究它。不幸的是,我無法將用戶的點擊動作映射到對象(行星等)。Google Sky Map open source - 如何將點擊動作映射到對象?

我覺得這個入口點是GestureInterceptor.onDown(MotionEvent e)

但是,如何將MotionEvent映射到對象?我完全迷失在這裏。

你可以在這裏找到源代碼:http://code.google.com/p/stardroid/source/browse/#svn%2Ftrunk%2Fapp

什麼是想出迄今:

AstronomerModel model = StardroidApplication.getModel(); 
Pointing pointing = model.getPointing(); 

所以我的模型,我可以得到的視線。但是,需要做的是將點擊座標轉換爲地心座標(如何?),然後找到位於這些座標處的對象(如何?)。

回答

1

好吧,這就是我所做的。

我捕獲了標籤Geocentric Positions並將它們全部存儲在ApplicationConstants類中。您可以將它們放入ProtobufAstronomicalSource.getLabels()中,除了行星,您可以在PlanetSource.initialize()上獲得。

然後,當用戶單擊時,在com.google.android.stardroid.touch.GestureInterpreter類中調用onSingleTapConfirmed方法。在此方法中,我得到的所有標籤,轉換地心志願服務崗位到屏幕上的位置,使用此代碼:

@Override 
     public boolean onSingleTapConfirmed(MotionEvent e) { 
     Log.d(TAG, "Confirmed single tap"); 

     Point screen = ApplicationConstants.getSizeOfScreen(); 
     int screenHeight = screen.y; 
     int screenWidth = screen.x; 
     float yClicked = screenHeight - e.getRawY(); //e.y is inverted, this normalizes it 
     float xClicked = e.getRawX(); 
     ArrayList<Label> labelArray = ApplicationConstants.getLabels(); 
     Log.d("LabelClicked", "label count: " + labelArray.size()); 
     ArrayList<LabelScreen> labelsOnScreen = new ArrayList<LabelScreen>(); 
     for (Label label : labelArray) { 
      //calculets current screen position of all labels, most of this code comes from LabelObjectManager.drawLabel() 
      Vector3 lookDir = ApplicationConstants.getLookDir(); 
      if (lookDir.x * label.x + lookDir.y * label.y + lookDir.z * label.z < ApplicationConstants.getmDotProductThreshold()) { 
       //return; 
      } 

      Vector3 mLabelOffset = ApplicationConstants.getmLabelOffset(); 

      // Offset the label to be underneath the given position (so a label will 
      // always appear underneath a star no matter how the phone is rotated) 
      Vector3 v = new Vector3(
       label.x - mLabelOffset.x * label.offset, 
       label.y - mLabelOffset.y * label.offset, 
       label.z - mLabelOffset.z * label.offset); 

      Vector3 screenPos = Matrix4x4.transformVector(
       ApplicationConstants.setTransformToScreenMatrix(), 
       v); 

      // We want this to align consistently with the pixels on the screen, so we 
      // snap to the nearest x/y coordinate, and add a magic offset of less than 
      // half a pixel. Without this, rounding error can cause the bottom and 
      // top of a label to be one pixel off, which results in a noticeable 
      // distortion in the text. 
      final float MAGIC_OFFSET = 0.25f; 
      screenPos.x = (int)screenPos.x + MAGIC_OFFSET; 
      screenPos.y = (int)screenPos.y + MAGIC_OFFSET; 

      //by Marcio Granzotto Rodrigues 
      if ((screenPos.x < 0.0f) | (screenPos.y < 0.0f)) { 
       //not on screen 
      }else if ((screenPos.x > screenWidth) | (screenPos.y > screenHeight)) { 
       //not on screen 
      }else if (screenPos.z < 0) { 
       //not on screen 
      }else { 
       //on screen 
       Log.d("LabelClicked", "on screen: " + label.getText() + " - " + screenPos.x + " " + screenPos.y + " " + screenPos.z); 
       LabelScreen labelScreen = new LabelScreen(label, screenPos); 
       labelsOnScreen.add(labelScreen); 
      }//end else 
     }//end for 

     Log.i("LabelClicked", "Labels on Screen: " + labelsOnScreen.size()); 
     LabelScreen theLabel = null; 
     for (LabelScreen labelScreen : labelsOnScreen) { 
      if (true) { //TODO check if label is on the clickable list 
       if (theLabel == null) { 
        //defines first label 
        theLabel = labelScreen; 
        Log.i("LabelClicked", "theLabel null -> " + theLabel.getLabel().getText()); 
       }else { 
        //check if this label is closer to the click area than theLabel 
        float theLabelRelativeX = theLabel.getScreenPos().x - xClicked; 
        float theLabelRelativeY = theLabel.getScreenPos().y - yClicked; 
        float myLabelRealativeX = labelScreen.getScreenPos().x - xClicked; 
        float myLabelRealativeY = labelScreen.getScreenPos().y - yClicked; 

        if ((Math.abs(myLabelRealativeX) < Math.abs(theLabelRelativeX)) 
          && (Math.abs(myLabelRealativeY) < Math.abs(theLabelRelativeY))) { 
         Log.i("LabelClicked", "theLabel " + theLabel.getLabel().getText() + " -> " + labelScreen.getLabel().getText()); 
         theLabel = labelScreen; 
        } 
       } 
      } 
     } 

     float theLabelRelativeX = theLabel.getScreenPos().x - xClicked; 
     float theLabelRelativeY = theLabel.getScreenPos().y - yClicked; 
     if ((theLabelRelativeX < screenWidth*0.1f) && (theLabelRelativeY < screenHeight*0.1f)) { 
      //clicked 
      if (theLabel.getLabel().getText().equals(ApplicationConstants.myContext.getString(com.google.android.stardroid.R.string.moon))) { 
       //ìf the clicked label is the moon, checks phase (in portuguese) 
       String moonPhase = ""; 
       switch (ApplicationConstants.getMoonPhase()) { 
       case ApplicationConstants.MOON_FULL: 
        moonPhase = " cheia"; 
        break; 
       case ApplicationConstants.MOON_CRESCENT: 
        moonPhase = " crescente"; 
        break; 
       case ApplicationConstants.MOON_NEW: 
        moonPhase = " nova"; 
        break; 
       case ApplicationConstants.MOON_GIBBOUS: 
        moonPhase = " minguante"; 
        break; 
       default: 
        break; 
       } 
       Toast.makeText(ApplicationConstants.myContext, theLabel.getLabel().getText() + moonPhase, Toast.LENGTH_SHORT).show(); 
       Log.i("LabelClicked", "You clicked: " + theLabel.getLabel().getText() + moonPhase); 
      }else { 
       Toast.makeText(ApplicationConstants.myContext, theLabel.getLabel().getText(), Toast.LENGTH_SHORT).show(); 
       Log.i("LabelClicked", "You clicked: " + theLabel.getLabel().getText()); 
      } 
     } 
     return false; 
     } 

我希望這有助於。

+0

請問您可以分享ApplicationContants課程 –