#include <algorithm>
#include <cassert>
#include <cmath>
#include <complex>
#include <iomanip>
#include <iostream>
#include <vector>

#include <cstring>

// ???, ????????????
typedef std::complex<double> Point;
typedef Point Vector;

namespace std {
	bool operator < (const Point &a, const Point &b){
		return a.real() != b.real() ? a.real() < b.real() : a.imag() < b.imag();
	}
	
	istream& operator >> (istream &is, Point &a){
		double x, y;
		is >> x >> y;
		a = Point(x, y);
		return is;
	}
	
	ostream& operator << (ostream &os, Point a){
		return os << a.real() << " " << a.imag();
	}
}

// ??´???
struct Line {
	Point p1, p2;
	Line(){}
	Line(const Point &p1, const Point &p2): p1(p1), p2(p2){}
};
typedef Line Segment;

namespace std {
	istream& operator >> (istream &is, Line &a){
		return is >> a.p1 >> a.p2;
	}
}

// ???
struct Circle {
	Point p; double r;
	Circle(){}
	Circle(const Point &p, double r): p(p), r(r){}
};

namespace std {
	istream& operator >> (istream &is, Circle &a){
		return is >> a.p >> a.r;
	}
}

// ????§???¢
typedef std::vector<Point> Polygon;

const double EPS = 1e-12;
const double INF = 1e12;
const double PI = acos(-1.0);

// ????????¨??????????????¢???
enum CCW {
	COUNTER_CLOCKWISE = 1,
	CLOCKWISE = -1,
	ONLINE_BACK = 2,
	ONLINE_FRONT = -2,
	ON_SEGMENT = 0,
};

// ?????¢????£????????????¢???
enum {
	OUT = 0,
	ON = 1,
	IN = 2,
};


// a ??? 2 ??? (a ^ 2)
double SQ(double a);

// ?????????????????????????????¢??°
bool EQ(double a, double b);
bool NEQ(double a, double b);
bool LT(double a, double b);
bool GT(double a, double b);
bool LEQ(double a, double b);
bool GEQ(double a, double b);

// ??§?????? <=> ?????°?????????
double toDeg(double t);
double toRad(double t);

// ????????? (dot(a, a))
double norm(const Vector &a);

// ??????, ??????
double dot(const Vector &a, const Vector &b);
double cross(const Vector &a, const Vector &b);

// ??´???, ??????
bool orthogonal(const Segment &s1, const Segment &s2);
bool parallel(const Segment &s1, const Segment &s2);

// ?°???±, ????°?
Point project(const Line &l, const Point &p);
Point reflect(const Line &l, const Point &p);

// ?????? (p0, p1) ??¨??? p2 ???????????¢???
int ccw(const Point &p0, const Point &p1, const Point &p2);

// ????????????
bool intersectLP(const Line &l, const Point &p);
bool intersectLL(const Line &l1, const Line &l2);
bool intersectLS(const Line &l, const Segment &s);
bool intersectSP(const Segment &s, const Point &p);
bool intersectSS(const Segment &s1, const Segment &s2);
int intersectCP(const Circle &c, const Point &p);
bool intersectCL(const Circle &c, const Line &l);
int intersectCS(const Circle &c, const Segment &s);
int intersectCC(const Circle &c1, const Circle &c2);

// ?????¢
double distanceLP(const Line &l, const Point &p);
double distanceLL(const Line &l1, const Line &l2);
double distanceLS(const Line &l, const Segment &s);
double distanceSP(const Segment &s, const Point &p);
double distanceSS(const Segment &s1, const Segment &s2);
double distanceCP(const Circle &c, const Point &p);
double distanceCL(const Circle &c, const Line &l);
double distanceCS(const Circle &c, const Segment &s);
double distanceCC(const Circle &c1, const Circle &c2);

// ??????
Point crossPointLL(const Line &l1, const Line &l2);
Point crossPointLS(const Line &l, const Segment &s);
Point crossPointSS(const Segment &s1, const Segment &s2);
std::vector<Point> crossPointCL(const Circle &c, const Line &l);
std::vector<Point> crossPointCS(const Circle &c, const Segment &s);
std::vector<Point> crossPointCC(const Circle &c1, const Circle &c2);


double SQ(double a){
	return a * a;
}

bool EQ(double a, double b){
	return std::abs(a - b) < EPS;
}

bool NEQ(double a, double b){
	return !EQ(a, b);
}

bool LT(double a, double b){
	return a - b < -EPS;
}

bool GT(double a, double b){
	return a - b > EPS;
}

bool LEQ(double a, double b){
	return !GT(a, b);
}

bool GEQ(double a, double b){
	return !LT(a, b);
}

double toDeg(double t){
	return t * 180 / PI;
}

double toRad(double t){
	return t / 180 * PI;
}

double norm(const Vector &a){
	return SQ(a.real()) + SQ(a.imag());
}

double dot(const Vector &a, const Vector &b){
	return (conj(a) * b).real();
}

double cross(const Vector &a, const Vector &b){
	return (conj(a) * b).imag();
}

// AOJ CGL_2_A
bool orthogonal(const Segment &s1, const Segment &s2){
	return EQ(dot(s1.p2 - s1.p1, s2.p2 - s2.p1), 0.0);
}

// AOJ CGL_2_A
bool parallel(const Segment &s1, const Segment &s2){
	return EQ(cross(s1.p2 - s1.p1, s2.p2 - s2.p1), 0.0);
}

// AOJ CGL_1_A
Point project(const Line &l, const Point &p){
	Vector base = l.p2 - l.p1;
	double r = dot(p - l.p1, base) / norm(base);
	return l.p1 + base * r;
}

// AOJ CGL_1_B
Point reflect(const Line &l, const Point &p){
	return p + (project(l, p) - p) * 2.0;
}

// AOJ CGL_1_C
int ccw(const Point &p0, const Point &p1, const Point &p2){
	Vector a = p1 - p0;
	Vector b = p2 - p0;
	if (GT(cross(a, b), 0.0)) return COUNTER_CLOCKWISE;
	if (LT(cross(a, b), 0.0)) return CLOCKWISE;
	if (LT(dot(a, b), 0.0)) return ONLINE_BACK;
	if (LT(norm(a), norm(b))) return ONLINE_FRONT;
	return ON_SEGMENT;
}

bool intersectLP(const Line &l, const Point &p){
	return LEQ(std::abs(cross(l.p1 - p, l.p2 - p)), 0.0);
}

bool intersectLL(const Line &l1, const Line &l2){
	return !parallel(l1, l2) || LEQ(std::abs(cross(l1.p2 - l1.p1, l2.p1 - l1.p1)), 0.0);
}

bool intersectLS(const Line &l, const Segment &s){
	return LEQ(cross(l.p2 - l.p1, s.p1 - l.p1) * cross(l.p2 - l.p1, s.p2 - l.p1), 0.0);
}

bool intersectSP(const Segment &s, const Point &p){
	return norm(s.p1 - p) + norm(s.p2 - p) - norm(s.p2 - s.p1) < EPS;
}

// CGL_2_B
bool intersectSS(const Segment &s1, const Segment &s2){
	return ccw(s1.p1, s1.p2, s2.p1) * ccw(s1.p1, s1.p2, s2.p2) <= 0 &&
		ccw(s2.p1, s2.p2, s1.p1) * ccw(s2.p1, s2.p2, s1.p2) <= 0;
}

int intersectCP(const Circle &c, const Point &p){
	double dd = norm(c.p - p);
	if (LT(dd, SQ(c.r))) return IN;
	if (EQ(dd, SQ(c.r))) return ON;
	return OUT;
}

bool intersectCL(const Circle &c, const Line &l){
	double d = distanceLP(l, c.p);
	return LEQ(d, c.r);
}

int intersectCS(const Circle &c, const Segment &s){
	double dd1 = norm(c.p - s.p1);
	double dd2 = norm(c.p - s.p2);
	if (LT(dd1, SQ(c.r)) && LT(dd2, SQ(c.r))) return IN;
	if (GT(distanceCS(c, s), 0.0)) return OUT;
	return ON;
}

// c1 ??? c2 ???????????????????????¨??? IN
// c1 ??? c2 ????????£???????????¨??? ON
// c1 ??? c2 ?????????????????¨??? OUT
int intersectCC(const Circle &c1, const Circle &c2){
	if (GT(norm(c1.p - c2.p), SQ(c1.r + c2.r))) return OUT;
	if (LT(norm(c1.p - c2.p), SQ(c2.r))) return IN;
	if (LT(norm(c1.p - c2.p), SQ(c1.r))) return OUT;
	return ON;
}

double distanceLP(const Line &l, const Point &p){
	return std::abs(cross(l.p2 - l.p1, p - l.p1)) / std::abs(l.p2 - l.p1);
}

double distanceLL(const Line &l1, const Line &l2){
	if (intersectLL(l1, l2)) return 0.0;
	return distanceLP(l1, l2.p1);
}

double distanceLS(const Line &l, const Segment &s){
	if (intersectLS(l, s)) return 0.0;
	return std::min(distanceLP(l, s.p1), distanceLP(l, s.p2));
}

double distanceSP(const Segment &s, const Point &p){
	if (dot(s.p2 - s.p1, p - s.p1) < 0.0) return std::abs(p - s.p1);
	if (dot(s.p1 - s.p2, p - s.p2) < 0.0) return std::abs(p - s.p2);
	return distanceLP(s, p);
}

// AOJ CGL_2_D
double distanceSS(const Segment &s1, const Segment &s2){
	if (intersectSS(s1, s2)) return 0.0;
	return std::min(
		std::min(
			distanceSP(s1, s2.p1),
			distanceSP(s1, s2.p2)
		),
		std::min(
			distanceSP(s2, s1.p1),
			distanceSP(s2, s1.p2)
		)
	);
}

double distanceCP(const Circle &c, const Point &p){
	return std::abs(std::abs(c.p - p) - c.r);
} 

double distanceCL(const Circle &c, const Line &l){
	if (intersectCL(c, l)) return 0.0;
	return distanceLP(l, c.p) - c.r;
}

double distanceCS(const Circle &c, const Segment &s){
	if (intersectCS(c, s)) return 0.0;
	return std::min(distanceCP(c, s.p1), distanceCP(c, s.p2));
}

double distanceCC(const Circle &c1, const Circle &c2){
	if (intersectCC(c1, c2) == ON) return 0.0;
	if (intersectCC(c1, c2) == IN){
		return c2.r - (std::abs(c1.p - c2.p) + c1.r);
	}
	if (intersectCC(c2, c1) == IN){
		return c1.r - (std::abs(c1.p - c2.p) + c2.r);
	}
	return (c1.r + c2.r) - (c1.r + c2.r);
}

Point crossPointLL(const Line &l1, const Line &l2){
	assert(intersectLL(l1, l2));
	Vector base = l2.p2 - l2.p1;
	double d1 = std::abs(cross(base, l1.p1 - l2.p1));
	double d2 = std::abs(cross(base, l1.p2 - l2.p1));
	double t = d1 / (d1 + d2);
	return l1.p1 + (l1.p2 - l1.p1) * t;
}

Point crossPointLS(const Line &l, const Segment &s){
	assert(intersectLS(l, s));
	return crossPointLL(l, s);
}

Point crossPointSS(const Segment &s1, const Segment &s2){
	assert(intersectSS(s1, s2));
	return crossPointSS(s1, s2);
}

std::vector<Point> crossPointCL(const Circle &c, const Line &l){
	if (!intersectCL(c, l)) return std::vector<Point>();
	std::vector<Point> ret;
	Vector proj = project(l, c.p);
	Vector e = (l.p2 - l.p1) / std::abs(l.p2 - l.p1);
	double base = sqrt(SQ(c.r) - norm(proj - c.p));
	ret.push_back(proj + e * base);
	ret.push_back(proj - e * base);
	return ret;
}

std::vector<Point> crossPointCS(const Circle &c, const Segment &s){
	std::vector<Point> ret = crossPointCL(c, s);
	for (int i = 0; i < ret.size(); i++){
		if (!intersectCP(c, ret[i])){
			swap(ret[i], ret.back());
			ret.pop_back();
			i--;
		}
	}
	return ret;
}

std::vector<Point> crossPointCC(const Circle &c1, const Circle &c2){
	if (!intersectCC(c1, c2)) return std::vector<Point>();
	std::vector<Point> ret;
	double d = std::abs(c1.p - c2.p);
	double a = std::acos((SQ(c1.r) + SQ(d) - SQ(c2.r)) / (2 * c1.r * d));
	double t = std::arg(c2.p - c1.p);
	ret.push_back(c1.p + std::polar(c1.r, t + a));
	ret.push_back(c1.p + std::polar(c1.r, t - a));
	return ret;
}

namespace {
enum {DIRECTED, UNDIRECTED};
const int GRAPH_TYPE = DIRECTED;

typedef int Weight;
const Weight INF = 1 << 28;

struct Edge {
	int src, dst;
	Weight weight;
	Edge() {}
	Edge(int src, int dst, Weight weight = 1): src(src), dst(dst), weight(weight) {}
	bool operator < (const Edge &t) const { return weight < t.weight; }
};

typedef std::vector<Edge> Edges;
typedef std::vector<Edges> Graph;

void addEdge(Graph &g, int src, int dst, int weight = 1)
{
	g[src].push_back(Edge(src, dst, weight));
	if (GRAPH_TYPE == UNDIRECTED) g[dst].push_back(Edge(dst, src, weight));
};

Graph transpose(const Graph &g)
{
	Graph rg(g.size());
	for (int i = 0; i < g.size(); i++){
		for (int j = 0; j < g[i].size(); j++){
			addEdge(rg, g[i][j].dst, g[i][j].src, g[i][j].weight);
		}
	}
	return rg;
}

void dfs_(const Graph &g, int v, bool *used, std::vector<int> &vs)
{
	used[v] = true;
	for (int i = 0; i < g[v].size(); i++){
		int to = g[v][i].dst;
		if (!used[to]) dfs_(g, to, used, vs);
	}
	vs.push_back(v);
}

void rdfs_(const Graph &g, int v, int k, bool *used, std::vector<int> &cmp)
{
	used[v] = true;
	cmp[v] = k;
	for (int i = 0; i < g[v].size(); i++){
		int to = g[v][i].dst;
		if (!used[to]) rdfs_(g, to, k, used, cmp);
	}
}

int scc(const Graph &g, std::vector<int> &cmp)
{
	Graph rg = transpose(g);
	std::vector<int> vs;
	bool *used = new bool[g.size()];
	cmp.resize(g.size());
	
	std::memset(used, false, g.size());
	for (int v = 0; v < g.size(); v++){
		if (!used[v]) dfs_(g, v, used, vs);
	}
	
	std::memset(used, false, g.size());
	int k = 0;
	for (int i = vs.size() - 1; i >= 0; i--){
		if (!used[vs[i]]) rdfs_(rg, vs[i], k++, used, cmp);
	}
	
	delete used;
	return k;
}
}


using namespace std;

int n;
double d;
vector<Polygon> tri;
vector<Polygon> rect;

bool contains(const Polygon &g, const Point &p)
{
	for (int i = 0; i < g.size(); i++){
		int t = ccw(g[i], g[(i + 1) % g.size()], p);
		if (t == CLOCKWISE) return false;
		if (t == ON_SEGMENT) return true;
	}
	return true;
}

bool intersect(const Polygon &g, const Polygon &h)
{
	for (int i = 0; i < g.size(); i++){
		for (int j = 0; j < h.size(); j++){
			Segment s(g[i], g[(i + 1) % g.size()]);
			Segment t(h[j], h[(j + 1) % h.size()]);
			if (LEQ(distanceSS(s, t), 0.01)) return true;
		}
	}
	
	for (int i = 0; i < g.size(); i++){
		if (contains(h, g[i])) return true;
	}
	
	for (int i = 0; i < h.size(); i++){
		if (contains(g, h[i])) return true;
	}
	
	return false;
}

int solve()
{
	rect.assign(n, Polygon(4));
	
	for (int i = 0; i < n; i++){
		for (int j = 0; j < 3; j++){
			if (EQ(norm(tri[i][j] - tri[i][(j + 1) % 3]), norm(tri[i][j] - tri[i][(j + 2) % 3]))){
				swap(tri[i][0], tri[i][j]);
			}
		}
		if (ccw(tri[i][1], tri[i][2], tri[i][0]) == CLOCKWISE){
			swap(tri[i][1], tri[i][2]);
		}
		
		Vector s = tri[i][2] - tri[i][1];
		Vector normal = s / abs(s) * Vector(0, 1) * d;
		rect[i][0] = tri[i][1];
		rect[i][1] = tri[i][2];
		rect[i][2] = tri[i][2] + normal;
		rect[i][3] = tri[i][1] + normal;
	}
	
	Graph graph(n);
	for (int i = 0; i < n; i++){
		for (int j = 0; j < n; j++){
			if (i == j) continue;
			if (intersect(rect[i], tri[j])){
				addEdge(graph, i, j);
			}
		}
	}
	
	vector<int> cmp;
	int v = scc(graph, cmp);
	int mat[100][100] = {};
	int in[100] = {};
	for (int i = 0; i < n; i++){
		for (int j = 0; j < graph[i].size(); j++){
			int src = cmp[i];
			int dst = cmp[graph[i][j].dst];
			if (src == dst) continue;
			if (mat[src][dst]++) continue;
			in[dst]++;
		}
	}
	int res = 0;
	for (int i = 0; i < v; i++){
		if (in[i] == 0) res++;
	}
	return res;
}

int main()
{
	std::cout << std::fixed << std::setprecision(12);
	
	while (cin >> n >> d, n){
		tri.assign(n, Polygon(3));
		for (int i = 0; i < n; i++){
			for (int j = 0; j < 3; j++){
				cin >> tri[i][j];
			}
		}
		cout << solve() << endl;
	}
}

Measured memory_bytes: 1356