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); } }
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; }