6

मेरे एंड्रॉइड ऐप में मैं उस बिंदु के बीच की दूरी जानना चाहता हूं जहां उपयोगकर्ता क्लिक करता है और एक विशिष्ट वेक्टर ड्राउबल समूह।क्या एक बिंदु और वेक्टर ड्रॉबल समूह के बीच की दूरी को मापने का एक सीधा तरीका है?

मैं VectorDrawable में blue की तरह एक समूह के लिए दूरी हैं:

<vector android:height="24dp" android:viewportHeight="1052.3622" 
    android:viewportWidth="744.0945" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> 
    <path android:fillColor="#ff0000" 
     android:name="blue" 
     android:pathData="M182.9,349.5m-74.7,0a74.7,74.7 0,1 1,149.3 0a74.7,74.7 0,1 1,-149.3 0" 
     android:strokeAlpha="1" android:strokeColor="#000000" android:strokeWidth="4.23501825"/> 
    <path android:fillColor="#00ff00" 
     android:name="red" 
     android:pathData="M474.3,392.4a84.3,102.9 0,1 0,168.6 0a84.3,102.9 0,1 0,-168.6 0z" 
     android:strokeAlpha="1" android:strokeColor="#000000" android:strokeWidth="5"/>> 
</vector> 

वहाँ एंड्रॉयड में इस दूरी की गणना करने के लिए एक सरल तरीका है?

+4

इस पर निर्भर करता है कि आपका कोड "सीधा" कैसे हो सकता है। – petey

उत्तर

2

मैं हल करने के लिए इस मुद्दे को मौजूद है यकीन है कि आसान तरीका नहीं कर रहा हूँ, लेकिन यह इस तरह किया जा सकता है:

पार्स वेक्टर एक्सएमएल ताकि आप क्रम में उन सभी चर है। पार्सिंग यहाँ शामिल नहीं है, मान लीजिए कि आप डेटा संरचना है कि हम बाद में साथ काम करेंगे निम्नलिखित है मान लें:

private static class VectorData { 
    private int width = 24; 
    private int height = 24; 
    private double viewportHeight = 1052.3622; 
    private double viewportWidth = 744.0945; 
    private String path = "M182.9,349.5m-74.7,0a74.7,74.7 0,1 1,149.3 0a74.7,74.7 0,1 1,-149.3 0"; 

    private double scaleVectorX(Context context) { 
     return dpToPx(context, width)/viewportWidth; 
    } 

    private double scaleVectorY(Context context) { 
     return dpToPx(context, height)/viewportHeight; 
    } 

    private static float dpToPx(Context context, float dp) { 
     return dp * context.getResources().getDisplayMetrics().density; 
    } 
} 

जैसा कि आप देख सभी क्षेत्रों सादगी के लिए hardcoded कर रहे हैं।

अगला चरण वेक्टर पथ यह android.graphics.Path को बदलने डेटा पार्स करने के लिए है:

android.graphics.Path path = android.util.PathParser.createPathFromPathData(vectorData.path); 

android.util.PathParser शामिल नहीं है, लेकिन आप स्रोत यहाँ पा सकते हैं: https://android.googlesource.com/platform/frameworks/base/+/17e64ffd852f8fe23b8e2e2ff1b62ee742af17a6/core/java/android/util/PathParser.java। यह सुनिश्चित नहीं है कि प्रतिलिपि बनाना और इसका उपयोग करना कितना कानूनी है।

पथ होने के बाद हमें एन अंक (निर्देशांक) ढूंढने की आवश्यकता होगी। अधिक अंक - अधिक सटीक परिणाम होगा और धीमी प्रसंस्करण:

final Collection<Point> points = getPoints(path, iv.getX(), iv.getY(), vectorData); 

private static class Point { 
    private float x; 
    private float y; 

    Point(float x, float y) { 
     this.x = x; 
     this.y = y; 
    } 

    @Override 
    public String toString() { 
     return "Point{" + 
       "x=" + x + 
       ", y=" + y + 
       '}'; 
    } 
} 

private Collection<Point> getPoints(Path path, float viewX, float viewY, VectorData vectorData) { 
    Collection<Point> points = new ArrayList<>(); 
    PathMeasure pm = new PathMeasure(path, false); 
    float length = pm.getLength(); 
    float distance = 0f; 
    int size = N; 
    float speed = length/size; 
    int counter = 0; 
    float[] aCoordinates = new float[2]; 

    while ((distance < length) && (counter < size)) { 
     // get point from the path 
     pm.getPosTan(distance, aCoordinates, null); 
     float pathX = aCoordinates[0]; 
     float pathY = aCoordinates[1]; 

     float x = (float) (vectorData.scaleVectorX(this) * pathX) + viewX; 
     float y = (float) (vectorData.scaleVectorY(this) * pathY) + viewY; 

     points.add(new Point(x, y)); 
     counter++; 
     distance = distance + speed; 
    } 

    return points; 
} 

पथ - हमारे रास्ता है कि हम पहले मिल है, iv - (उदाहरण के लिए, imageView) वेक्टर कंटेनर है, हम आदेश अंक निर्देशांक समायोजित करने के लिए इसकी आवश्यकता है । वेक्टरडाटा - संरचना है जिसे हमने अपने वेक्टर को पार्स करने से पहले प्राप्त किया था।

अब हम इस मामले में जहां पथ बंद कर दिया है संभाल करने के लिए क्षेत्र परिभाषित करने की जरूरत है और हम 0 दूरी के रूप में पथ के अंदर क्लिक करें का इलाज करना चाहते हैं:

final Region region = new Region(); 
RectF rectF = new RectF(); 
path.computeBounds(rectF, true); 
region.setPath(path, new Region((int) rectF.left, (int) rectF.top, (int) rectF.right, (int) rectF.bottom)); 

आदेश निम्न विधि मिनट की दूरी की गणना करने के लिए इस्तेमाल किया जाना चाहिए:

private int getMinDistance(float eventX, float eventY, Collection<Point> pathPoints, Region pathRegion, VectorData vectorData) { 
    int minDistance = Integer.MAX_VALUE; 

    boolean contains = pathRegion.contains((int) (eventX/vectorData.scaleVectorX(this)), (int) (eventY/vectorData.scaleVectorY(this))); 

    if (contains) { 
     minDistance = 0; 
    } else { 
     for (Point point : pathPoints) { 
      int distance = getDistanceBetweenPoints((int) eventX, (int) eventY, (int) point.x, (int) point.y); 
      if (distance < minDistance) { 
       minDistance = distance; 
      } 
     } 
    } 
    return minDistance; 
} 

private int getDistanceBetweenPoints(int x, int y, int x1, int y1) { 
    return (int) Math.sqrt((x1 - x) * (x1 - x) + (y1 - y) * (y1 - y)); 
} 
0

पहले बिंदु के cordinates मिल जहां के द्वारा प्रयोग किया छूता:

@Override 
public boolean onTouch(View v, MotionEvent event) { 
    float x1 = event.getX(); 
    float y1 = event.getY(); 
    return true; 
} 

के बाद से आप जानते हैं कि जहां drawable परदे पर दिखाई देगा, आप अपने drawable की स्थिति cordinates (x2, y2) के लिए कुछ मान निर्दिष्ट कर सकता है।

या view.getLocationOnScreen(int\[\]) तरह के साथ अपने drawable की imageView का उपयोग करें:

int[] posiXY = new int[2]; 
yourDrawablesImageView.getLocationOnScreen(posiXY); 
int x2 = posiXY[0]; 
int y2 = posiXY[1]; 
तो

अगर आप बस दूरी फार्मूला लागू:

float distance=sqrt((x2−x1)*(x2−x1)+(y2−y1)*(y2−y1)); 

आप आवश्यक दूरी मिल जाएगा।

+0

मुझे लगता है कि यह वास्तव में एक सरल और सीधा तरीका होना चाहिए – anotherGatsby

+0

मुझे कैसे पता चलेगा कि वेक्टर ड्रावेबल के समूह स्क्रीन पर दिखाई देंगे?मैं उन निर्देशांकों का उपयोग कैसे करूं? मैं समूह की दूरी की पूरी देखभाल नहीं करता हूं, पूरे वेक्टर ड्रायबल के लिए। – Christian

+0

क्या आप वेक्टर ड्रावेबल प्रदर्शित करने के लिए ImageView का उपयोग नहीं कर रहे हैं? यदि ऐसा है तो मैंने जवाब में थोड़ा सा कोड जोड़ा है। – anotherGatsby

संबंधित मुद्दे