#include<iostream>
#include<map>
#include<complex>
#include<queue>
#include<vector>
#include<algorithm>
#include<cassert>
#include<set>
#include<cassert>
using namespace std;
#define REP(i,b,n) for(int i=b;i<n;i++)
#define rep(i,n)   REP(i,0,n)
#define ALL(c)   (c).begin(),(c).end()
#define pb push_back
#define mp make_pair

const int N = 100;

//graph part
vector<int> edge[N];
bool vis[N];

int ord;
vector<int> inedge[N];
vector<int> redge[N];
int component[N];
struct PO{
  int order,num;
};
PO postorder[N];

bool cmp(const PO a,const PO b){
  return a.order > b.order;
}

void sccdfs(int now){
  vis[now]=1;
  rep(i,(int)inedge[now].size()){
    int next=inedge[now][i];
    if (!vis[next])sccdfs(next);
  }
  postorder[now].order=ord++;
  postorder[now].num=now;
}

void sccbfs(int ini,int comp){
  queue<int> Q;
  Q.push(ini);
  vis[ini]=true;
  component[ini]=comp;
  while(!Q.empty()){
    int now=Q.front();Q.pop();
    component[now]=comp;
    rep(i,(int)redge[now].size()){
      int next=redge[now][i];
      if (!vis[next])Q.push(next),vis[next]=true;
    }
  }
}

int scc(int n,map<int,int> &M){
  ord=0;
  rep(i,n)vis[i]=false;
  rep(i,n){
    if (!vis[i])sccdfs(i);
  }
  int cnt=0;
  rep(i,n)vis[i]=false;
  sort(postorder,postorder+n,cmp);
  rep(i,n){
    int now = postorder[i].num;
    if (vis[now])continue;
    sccbfs(now,cnt);
    cnt++;
  }
  rep(i,n)M[i]=component[i];
  return cnt;
}

void tsort(int now,vector<int> &a){
  if (vis[now])return;
  vis[now]=true;
  rep(i,(int)edge[now].size())tsort(edge[now][i],a);
  a.pb(now);
}

void dfs(int now){
  if (vis[now])return;
  vis[now]=true;
  rep(i,(int)edge[now].size())dfs(edge[now][i]);
}

int solve(int n){
  map<int,int> M;
  int tmpn=scc(n,M);
  rep(i,n){
    int me=M[i];
    rep(j,(int)inedge[i].size()){
      int you=M[inedge[i][j]];
      edge[me].pb(you);
    }
  }
  n=tmpn;
  vector<int> in;
  rep(i,n)vis[i]=false;
  rep(i,n){
    if (!vis[i])tsort(i,in);
  }
  reverse(ALL(in));
  int cnt=0;
  rep(i,n)vis[i]=false;
  rep(i,(int)in.size()){
    if (!vis[in[i]])dfs(in[i]),cnt++;
  }
  return cnt;
}

//geometry part
typedef complex<double> P;
const double eps = 1e-1;

double cross(P a,P b){
  return ( a.real()*b.imag() - a.imag()*b.real());
}

vector<P> getpolygon(vector<P> a,double d){
  int in[3]={0,1,2};
  vector<P> ret;
  do{
    if (fabs(abs(a[in[2]]-a[in[1]])-abs(a[in[2]]-a[in[0]])) < eps){
      P mid =(a[in[0]]+a[in[1]])/2.;
      P tmp=a[in[2]]-mid;
      tmp/=abs(tmp);
      tmp*=d;
      ret.pb(a[in[0]]);
      ret.pb(a[in[1]]);
      ret.pb(a[in[1]]+tmp);
      ret.pb(a[in[0]]+tmp);
      //if (     cross(a[in[0]]-a[in[1]],a[in[2]]-a[in[1]]) >=0)
      //	assert(cross(a[in[0]]-a[in[1]],mid-a[in[1]])>=0);
      //      else assert(cross(a[in[0]]-a[in[1]],mid-a[in[1]])<=0);
      return ret;
    }
  }while(next_permutation(in,in+3));
  //assert(false);
  return ret;
}

double dot(P a,P b){
  return a.real()*b.real()+a.imag()*b.imag();
}

double distance_ls_p(P a,P b,P c){
  if (dot(b-a,c-a) < eps)return abs(c-a);
  if (dot(a-b,c-b) < eps)return abs(c-b);
  return abs( cross(b-a,c-a))/abs(b-a);
}

bool isp(P a,P b,P c){
  return ( abs(a-c)+abs(b-c) < abs(a-b)+eps);
}

bool is_in(vector<P> in,P a){
  int cnt =0;
  int n = in.size();
  rep(i,n){
    P cur = in[i]-a,next=in[(i+1)%n]-a;
    if (cur.imag() > next.imag())swap(cur,next);
    if (cur.imag()<0 && 0<=next.imag() &&
        cross(next,cur)>=0)cnt++;
    if (isp(in[i],in[(i+1)%n],a))return true;
  }
  if (cnt %2 == 1)return true;
  else return false;
}

bool is_intersected_ls(P a1,P a2,P b1,P b2){
  if ( isp(a1,a2,b1))return true;
  if ( isp(a1,a2,b2))return true;
  if ( isp(b1,b2,a1))return true;
  if ( isp(b1,b2,a2))return true;
  if (( cross(a2-a1,b1-a1) * cross(a2-a1,b2-a1)<-eps ) && //-EPS
      ( cross(b2-b1,a1-b1)*cross(b2-b1,a2-b1)  <-eps))return true;
  else return false;
}

#define DSS distance_ls_p
double distance_ss_p(P a,P b,P c,P d){
  return min(  min( DSS(a,b,c),DSS(a,b,d)),min(DSS(c,d,a),DSS(c,d,b)));
}

bool is_intersected_polygon(vector<P> a,vector<P> b){
  int n = a.size();
  int m = b.size();
  rep(i,n){
    rep(j,m){
      if (is_intersected_ls(a[i],a[(i+1)%n],b[j],b[(j+1)%m]))
        return true;
    }
  }
  rep(i,(int)b.size()){
    if (is_in(a,b[i]))return true;
  }
  return false;
}

void makegraph(int n,vector<P> *sq,vector<P> *tri,double d){
  rep(i,n){
    rep(j,n){
      if (i == j)continue;
      if (is_intersected_polygon(sq[i],tri[j])){
        inedge[i].pb(j);
        redge[j].pb(i);
      }else {
	rep(k,tri[j].size()){
	  if (is_in(tri[i],tri[j][k])&&
	      (distance_ss_p(sq[i][0],sq[i][1],tri[j][0],tri[j][1])<d+eps ||
	       distance_ss_p(sq[i][0],sq[i][1],tri[j][1],tri[j][2])<d+eps||
	       distance_ss_p(sq[i][0],sq[i][1],tri[j][2],tri[j][0])<d+eps)
	      ){
	    assert(false);
	    inedge[i].pb(j);
	    redge[j].pb(i);
	    break;
	  }
	}
      }
    }
  }
}

main(){
  int n;
  double d;
  while(cin>>n>>d && n){
    rep(i,n){
      edge[i].clear();
      inedge[i].clear();
      redge[i].clear();
    }
    vector<P> in[n];
    vector<P> sq[n];
    rep(i,n){
      rep(j,3){
        P tmp;cin>>tmp.real()>>tmp.imag();in[i].pb(tmp);
      }
      sq[i]=getpolygon(in[i],d);
    }
    makegraph(n,sq,in,d);


    //rep(i,n){rep(j,sq[i].size())cout<< sq[i][j];cout << endl;}

    cout << solve(n) << endl;
  }
  return false;
}

Measured memory_bytes: 1024