double dist_pt_to_line_seg(const XYZ & p0, const XYZ &  p1, const XYZ &  p2) //p1 and p2 are the two ends of the line segment, and p0 the point
{
	if (p1==p2)
		return norm(p0-p1);
	else if (p0==p1 || p0==p2) return 0;

	XYZ d12 = p2-p1;
	XYZ d01 = p1-p0;
	float v01 = dot(d01, d01);
	float v12 = dot(d12, d12);
	float d012 = dot(d12, d01);

	float t = -d012/v12;
	if (t<0 || t>1) //then no intersection within the lineseg
	{
		double d01 = dist_L2(p0, p1);
		double d02 = dist_L2(p0, p2);
		return (d01<d02)?d01:d02;
	}
	else
	{
		XYZ xpt(p1.x+d12.x*t, p1.y+d12.y*t, p1.z+d12.z*t);
		return dist_L2(xpt, p0);
	}
}
Exemple #2
0
static inline void dists_L2(const data_t1* q, length_t m, const data_t2* x,
	length_t n, data_t3* out, length_t stride=1)
{
	return mapSubseqs([m, q](const data_t2* x) {
		return dist_L2(q, x, m);
	}, m, x, n, out, stride);
}
double dist_directional_swc_1_2(V3DLONG & nseg1, V3DLONG & nseg1big, double & sum1big, const NeuronTree *p1, const NeuronTree *p2)
{
	if (!p1 || !p2) return -1;
	V3DLONG p1sz = p1->listNeuron.size(), p2sz = p2->listNeuron.size();
	if (p1sz<2 || p2sz<2) return -1;

	NeuronSWC *tp1, *tp2;
	V3DLONG i, j;
	double sum1=0;
	nseg1=0;
	nseg1big=0;
	sum1big=0;

	QHash<int, int> h1 = generate_neuron_swc_hash(p1); //generate a hash lookup table from a neuron swc graph

	for (i=0;i<p1->listNeuron.size();i++)
	{
		//first find the two ends of a line seg
		tp1 = (NeuronSWC *)(&(p1->listNeuron.at(i)));
		if (tp1->pn < 0 || tp1->pn >= p1sz)
			continue;
		tp2 = (NeuronSWC *)(&(p1->listNeuron.at(h1.value(tp1->pn)))); //use hash table
		//qDebug() << "i="<< i << " pn="<<tp1->pn - 1;

		//now produce a series of points for the line seg
		double len=dist_L2(XYZ(tp1->x,tp1->y,tp1->z), XYZ(tp2->x,tp2->y,tp2->z));
		int N = int(1+len+0.5);
		XYZ ptdiff;
		if (N<=1)
		{
			qDebug() << "detect one very short segment, len=" << len;
			ptdiff = XYZ(0,0,0);
		}
		else
		{
			double N1=1.0/(N-1);
			ptdiff = XYZ(N1,N1,N1) * XYZ(tp2->x-tp1->x, tp2->y-tp1->y, tp2->z-tp1->z);
		}
		qDebug() << "N="<<N << "len=" <<len << "xd="<<ptdiff.x << " yd=" << ptdiff.y << " zd=" << ptdiff.z << " ";
		for (j=0;j<N;j++)
		{
			XYZ curpt(tp1->x + ptdiff.x*j, tp1->y + ptdiff.y*j, tp1->z + ptdiff.z*j);
			double cur_d = dist_pt_to_swc(curpt, p2);
			sum1 += cur_d;
			nseg1++;

			if (cur_d>=2)
			{
				sum1big += cur_d;
				nseg1big++;
			}

		}
	}
	qDebug() << "end directional neuronal distance computing";

	return sum1;
}
double dist_pt_to_line(const XYZ & p0, const XYZ &  p1, const XYZ &  p2) //p1 and p2 are the two points of the straight line, and p0 the point
{
	if (p1==p2)
		return norm(p0-p1);
	else if (p0==p1 || p0==p2) return 0;

	XYZ d12 = p2-p1;
	XYZ d01 = p1-p0;
	float v01 = dot(d01, d01);
	float v12 = dot(d12, d12);
	float d012 = dot(d12, d01);

	float t = -d012/v12;

	XYZ xpt(p1.x+d12.x*t, p1.y+d12.y*t, p1.z+d12.z*t);
	return dist_L2(xpt, p0);
}
NeuronMorphoInfo neuron_morpho_features(const NeuronTree *p) //collect the morphological features of a neuron
{
	NeuronMorphoInfo m;
	if (!p) return m;

	//create some reference names so that easier to write the code
	double & total_length = m.total_length;
	V3DLONG & n_node = m.n_node;
	V3DLONG & n_segment = m.n_segment; //091009 RZC
	V3DLONG & n_branch = m.n_branch;
	V3DLONG & n_tip = m.n_tip;
	double & bbox_xmin = m.bbox_xmin, bbox_xmax=m.bbox_xmax, bbox_ymin=m.bbox_ymin, bbox_ymax=m.bbox_ymax, bbox_zmin=m.bbox_zmin, bbox_zmax=m.bbox_zmax;
	double * moments = m.moments;

	//
	NeuronSWC *tp1, *tp2;
	V3DLONG i, j;

	QHash<int, int> h = generate_neuron_swc_hash(p); //generate a hash lookup table from a neuron swc graph
	n_node = h.size();

	unsigned char *nchildren = new unsigned char [n_node]; //track the # of children each node has
	for (i=0;i<n_node;i++) nchildren[i]=0;

	total_length = 0;
	for (i=0, total_length=0.0;i<p->listNeuron.size();i++)
	{
		//first find the two ends of a line seg
		tp1 = (NeuronSWC *)(&(p->listNeuron.at(i)));
		if (tp1->pn < 0 || tp1->pn >= n_node)
			continue;
		tp2 = (NeuronSWC *)(&(p->listNeuron.at(h.value(tp1->pn)))); //use hash table

		nchildren[h.value(tp1->pn)]++; //update the parent node's children number

		//qDebug() << "i="<< i << " pn="<<tp1->pn - 1;

		//compute the length
		double len=dist_L2(XYZ(tp1->x,tp1->y,tp1->z), XYZ(tp2->x,tp2->y,tp2->z));
		total_length += len;

		//compute the bbox
		if (i==0)
		{
			bbox_xmin = bbox_xmax = tp1->x;
			bbox_ymin = bbox_ymax = tp1->y;
			bbox_zmin = bbox_zmax = tp1->z;
		}
		else
		{
			if (bbox_xmin>tp1->x) bbox_xmin = tp1->x; if (bbox_xmax<tp1->x) bbox_xmax = tp1->x;
			if (bbox_ymin>tp1->y) bbox_ymin = tp1->y; if (bbox_ymax<tp1->y) bbox_ymax = tp1->y;
			if (bbox_zmin>tp1->z) bbox_zmin = tp1->z; if (bbox_zmax<tp1->z) bbox_zmax = tp1->z;
		}

//		//now produce a series of points for the line seg
//		int N = int(1+len+0.5);
//		XYZ ptdiff;
//		if (N<=1)
//		{
//			qDebug() << "detect one very short segment, len=" << len;
//			ptdiff = XYZ(0,0,0);
//		}
//		else
//		{
//			double N1=1.0/(N-1);
//			ptdiff = XYZ(N1,N1,N1) * XYZ(tp2->x-tp1->x, tp2->y-tp1->y, tp2->z-tp1->z);
//		}
//		qDebug() << "N="<<N << "len=" <<len << "xd="<<ptdiff.x << " yd=" << ptdiff.y << " zd=" << ptdiff.z << " ";
//		for (j=0;j<N;j++)
//		{
//			XYZ curpt(tp1->x + ptdiff.x*j, tp1->y + ptdiff.y*j, tp1->z + ptdiff.z*j);
//			double cur_d = dist_pt_to_swc(curpt, p2);
//			sum1 += cur_d;
//			nseg1++;
//		}
	}

//	for (i=0, n_branch=0;i<n_node;i++) //find the n_branches
//		if (nchildren[i]>1) n_branch++;

	if (nchildren) {delete nchildren; nchildren=0;}


	//////////////////////////////////////////////////////////
	// 091009 RZC: count after splitting to simple segments
	//////////////////////////////////////////////////////////

	vector <V_NeuronSWC> seg_vec = get_neuron_segments(p);
	n_segment = seg_vec.size();
	//neuron_branch_tip_count(n_branch, n_tip, seg_vec);

	// 091212 RZC: count changed using link_map
    V_NeuronSWC v_neuron = join_V_NeuronSWC_vec(seg_vec);
    //V_NeuronSWC v_neuron = get_v_neuron_swc(p);
    neuron_branch_tip_count(n_branch, n_tip, v_neuron);

    //141006 CHB: above may cause error when there is overlapping point in the file, corrrected:
    vector<int> num_child (p->listNeuron.size(),0);
    for(int i=0; i<p->listNeuron.size(); i++){
        V3DLONG pn=p->listNeuron.at(i).pn, pid=-1;
        if(p->hashNeuron.contains(pn))
            pid=p->hashNeuron[pn];
        else
            continue;
        num_child[pid]++;
    }
    n_branch=0;
    n_tip=0;
    for(int i=0; i<num_child.size(); i++){
        if(p->listNeuron.at(i).pn<0) //skip root
            continue;
        if(num_child[i]==0) //tips
            n_tip++;
        if(num_child[i]>1) //branch points
            n_branch++;
    }

	return m;
}