/**
 * Sample solution to Subway Planning
 * Author: Stein Norheim
 *
 * My first Java program ever!!!
 *
 * Geometry and Dynamic Programming.
 *
 * To get rid of floating point truncation problems, this
 * solution only uses integers, except for the initial
 * sorting on angles.
 */

import java.util.*;
import java.io.*;

class CPointComparator implements Comparator {
    public int compare(Object a, Object b) {
        double angleA = ((CPoint)a).angle;
        double angleB = ((CPoint)b).angle;
        if (angleA>angleB) return 1;
        if (angleA<angleB) return -1;
        return 0;
    }
}

class CPoint {
    public int x;
    public int y;
    public int d;
    public double angle;
    
    CPoint (int X,int Y, int D) {
        x = X;
        y = Y;
        d = D;
        angle = Math.atan2(y,x);
    }

    boolean needsSubway() {
        return r2()>d*d;
    }

    int r2 () {
        return (x*x+y*y);
    }
    
    boolean overlaps(CPoint o) {
        if (!needsSubway() && !o.needsSubway())
            return true;
        
        int templeft = x*o.x+y*o.y+d*d;
        if (templeft<0) return false;
        int leftside = templeft*templeft;
        int rightside = (r2()-d*d)*(o.r2()-d*d);
        return leftside >= rightside;
    }

};

class DynTable {
    int[] a;
    int[] solution;
    CPoint[] p;
    boolean[][] overlaps;
    int n;
    
    DynTable (int dimension) {
        n = 0;
        a = new int [dimension];
        solution = new int[dimension];
        p = new CPoint[dimension];
        overlaps = new boolean[dimension][dimension];
    }
    
    void addPoint(CPoint newPoint) {
        p[n]=newPoint;
        n++;
    }
    
    void resetA() {
        for (int i=0; i<n; i++)
            a[i]=-1;
    }

    void makeoverlaps() {
        for (int i=0; i<n; i++) {
            boolean stilloverlapping=true;
            overlaps[i][i]=true;
            for (int j=(i+n-1)%n; j!=i; j=(j+n-1)%n) {
                if (stilloverlapping) {
                    stilloverlapping = p[j].overlaps(p[i]);
                }
                overlaps[j][i]=stilloverlapping;
            }
        }

    }

    boolean canShareLines(int first, int last) {
        int i = first;
        for (i=first; i!=last; i=(i+1)%n) {
            if (!(p[last].overlaps(p[i])))
                return false;
        }
        return true;
    }
    
    int getNeededLines(int starter, int current) {
        if (a[current]>=0) return a[current];

        int i=current;
        int best;
        int lastincluded;
        if ((i+1)%n==starter) {
            best = 1;
            lastincluded = current;

        } else {
            lastincluded = i;
            i=(i+1)%n;
            best =1+getNeededLines(starter,i); // worst case!
           
            int candidate;
            while ((i!=starter) && (overlaps[current][i])) {
                if ((i+1)%n==starter) {
                    best=1;
                    lastincluded = i;
                    break;
                } else {
                    candidate = 1 + getNeededLines(starter,(i+1)%n);
                    if (candidate<best) {
                        best=candidate;
                        lastincluded=i;
                    }
                    i=(i+1)%n;
                }
            }
        }

        a[current]=best;
        solution[current]=(lastincluded+1) % n;
        return best;
    }

    int minSubways() {
        if (n==0) return 0;
        
        int bestsofar=-1;
        
        Arrays.sort(p,0,n, new CPointComparator());
        makeoverlaps();
        for (int i=0; i<n; i++) {
            resetA();
            int neededlines = getNeededLines(i,i);
            if (neededlines<bestsofar || bestsofar==-1) {
                bestsofar=neededlines;
            }
        }
        return bestsofar;
    }
}

class Subway {
   
    static BufferedReader stdin = 
	new BufferedReader(new InputStreamReader(System.in));

    static StreamTokenizer tokens;
    
    static PrintWriter stdout = 
	new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));

    static int getInt() throws IOException
    {
	tokens.nextToken();
	return Integer.parseInt(tokens.sval);
    }

    public static void main(String[] as)  throws IOException
    {
        init();
        int N = getInt();

        for (int i=0; i<N; i++)
            solve();

        stdout.close();
    }

    
    static void solve() throws IOException
    {
        int n = getInt();
        int d = getInt();


        DynTable t = new DynTable(n);

        for (int i=0; i<n; i++) {
            CPoint pointCandidate = new CPoint(getInt(),getInt(),d);
            if (pointCandidate.needsSubway())
                t.addPoint(pointCandidate);
        }
        
        System.out.println(t.minSubways());
    }
    
    
    static void init() 
    {
        tokens = new StreamTokenizer(stdin);
        tokens.resetSyntax();
        tokens.whitespaceChars(0,32);
        tokens.wordChars(33,255);
    }
    

}

	    
