#include <iostream>
#include <sstream>
#include <iomanip>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
#include <list>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <bitset>
#include <numeric>
#include <climits>
#include <cfloat>
using namespace std;

void stronglyConnectedComponents(const vector<vector<int> >& edges1, vector<vector<int> >& nodes, vector<vector<int> >& edges2)
{
    const int n = edges1.size();

    class Func{
        vector<int> num, low;
        vector<bool> isStk;
        stack<int> stk;
        int time;
    public:
        Func(int n){
            num.assign(n, 0);
            low.assign(n, 0);
            isStk.assign(n, false);
            time = 0;
        }
        void visit(const vector<vector<int> >& edges, int v, vector<vector<int> >& nodes){
            if(num[v] != 0)
                return;
            num[v] = low[v] = ++ time;
            stk.push(v);
            isStk[v] = true;
            for(unsigned i=0; i<edges[v].size(); ++i){
                int w = edges[v][i];
                visit(edges, w, nodes);
                if(isStk[w])
                    low[v] = min(low[v], low[w]);
            }
            if(low[v] == num[v]){
                nodes.push_back(vector<int>());
                for(;;){
                    int w = stk.top();
                    stk.pop();
                    isStk[w] = false;
                    nodes.back().push_back(w);
                    if(v == w)
                        break;
                }
            }
        }
    }func(n);

    for(int i=0; i<n; ++i)
        func.visit(edges1, i, nodes);
    reverse(nodes.begin(), nodes.end()); // DAGÉ·é½ßÉ½]³¹é

    const int m = nodes.size();
    vector<int> index(n); // ³ÌOtÌe¸_ÌDAGÉ¨¯é¸_
    for(int i=0; i<m; ++i){
        for(unsigned j=0; j<nodes[i].size(); ++j)
            index[nodes[i][j]] = i;
    }
    edges2.assign(m, vector<int>());
    vector<vector<bool> > check(m, vector<bool>(m, false));
    for(int i=0; i<n; ++i){
        for(unsigned j=0; j<edges1[i].size(); ++j){
            int v = index[i];
            int w = index[edges1[i][j]];
            if(v != w && !check[v][w]){
                edges2[v].push_back(w);
                check[v][w] = true;
            }
        }
    }
}

const double EPS = 1.0e-10;

class Point
{
public:
    double y, x;
    Point(){
        y = x = 0.0;
    }
    Point(double y0, double x0){
        y = y0;
        x = x0;
    }
    Point operator+(const Point& p) const{
        return Point(y + p.y, x + p.x);
    }
    Point operator-(const Point& p) const{
        return Point(y - p.y, x - p.x);
    }
    Point operator*(double a) const{
        return Point(y * a, x * a);
    }
    Point operator/(double a) const{
        return Point(y / a, x / a);
    }
    double length() const{
        return sqrt(y * y + x * x);
    }
    double dist(const Point& p) const{
        return sqrt(pow(y - p.y, 2) + pow(x - p.x, 2));
    }
    double dot(const Point& p) const{
        return y * p.y + x * p.x; // |a|*|b|*cosÆ
    }
    double cross(const Point& p) const{
        return x * p.y - y * p.x; // |a|*|b|*sinÆ
    }
};

double segmentPointDist(const Point& a1, const Point& a2, const Point& p)
{
    if((a2-a1).dot(p-a1) < 0)
        return a1.dist(p);
    else if((a1-a2).dot(p-a2) < 0)
        return a2.dist(p);
    else
        return abs((a2-a1).cross(p-a1)) / a1.dist(a2);
}

double segmentsDist(const Point& a1, const Point& a2, const Point& b1, const Point& b2)
{
    if(((a2-a1).cross(b1-a1) * (a2-a1).cross(b2-a1) < -EPS) && ((b2-b1).cross(a1-b1) * (b2-b1).cross(a2-b1) < -EPS))
        return 0.0;

    double ret = segmentPointDist(a1, a2, b1);
    ret = min(ret, segmentPointDist(a1, a2, b2));
    ret = min(ret, segmentPointDist(b1, b2, a1));
    ret = min(ret, segmentPointDist(b1, b2, a2));
    return ret;
}

bool convexContain(const vector<Point>& cp, const Point& p)
{
    int n = cp.size();
    bool ret1 = true;
    bool ret2 = true;
    for(int i=0; i<n; ++i){
        double a = (cp[(i+1)%n] - cp[i]).cross(p - cp[i]);
        if(a < -EPS)
            ret1 = false;
        if(a > EPS)
            ret2 = false;
    }
    return ret1 || ret2;
}

bool polygonsCollide(const vector<Point>& cp1, const vector<Point>& cp2)
{
    int n = cp1.size();
    int m = cp2.size();
    for(int i=0; i<n; ++i){
        for(int j=0; j<m; ++j){
            if(segmentsDist(cp1[i], cp1[(i+1)%n], cp2[j], cp2[(j+1)%m]) < 0.01 + EPS)
                return true;
        }
    }

    return convexContain(cp1, cp2[0]) || convexContain(cp2, cp1[0]);
}

int main()
{
    for(;;){
        int n, d;
        cin >> n >> d;
        if(n == 0)
            return 0;

        vector<vector<Point> > p(n, vector<Point>(3));
        for(int i=0; i<n; ++i){
            for(int j=0; j<3; ++j){
                cin >> p[i][j].x >> p[i][j].y;
            }
            if(p[i][0].dist(p[i][2]) > p[i][0].dist(p[i][1]))
                swap(p[i][1], p[i][2]);
            if(p[i][1].dist(p[i][2]) > p[i][0].dist(p[i][1]))
                swap(p[i][0], p[i][2]);
            if((p[i][1] - p[i][0]).cross(p[i][2] - p[i][0]) < 0)
                swap(p[i][0], p[i][1]);
        }

        vector<vector<int> > edges(n);
        for(int i=0; i<n; ++i){
            Point v = p[i][1] - p[i][0];
            v = v / v.length() * d;
            swap(v.y, v.x);
            v.x *= -1;

            vector<Point> p1(4);
            p1[0] = p[i][0];
            p1[1] = p[i][0] + v;
            p1[2] = p[i][1] + v;
            p1[3] = p[i][1];

            for(int j=0; j<n; ++j){
                if(j == i)
                    continue;
                if(polygonsCollide(p1, p[j]))
                    edges[i].push_back(j);
            }
        }

        vector<vector<int> > nodes, edges2;
        stronglyConnectedComponents(edges, nodes, edges2);

        int m = edges2.size();
        vector<bool> check(m, false);
        int ret = m;
        for(int i=0; i<m; ++i){
            for(unsigned j=0; j<edges2[i].size(); ++j){
                if(!check[edges2[i][j]]){
                    check[edges2[i][j]] = true;
                    -- ret;
                }
            }
        }
        cout << ret << endl;
    }
}

Measured memory_bytes: 0