void check_mates(const HitList& hits1_in_ref, const HitList& hits2_in_ref, vector<pair<size_t, size_t> >& happy_mates, vector<size_t>& map1_singletons, vector<size_t>& map2_singletons) { std::set<size_t> marked; // TODO: if this shows up on the profile, replace it with a linear // time algorithm. This one is 2*n*lg(n). HitList::const_iterator last_good = hits2_in_ref.begin(); for (size_t i = 0; i < hits1_in_ref.size(); ++i) { pair<HitList::const_iterator, HitList::const_iterator> range_pair; range_pair = equal_range(last_good, hits2_in_ref.end(), hits1_in_ref[i], hit_insert_id_lt); bool found_hit = false; if (range_pair.first != range_pair.second) last_good = range_pair.first; for (HitList::const_iterator f = range_pair.first; f != range_pair.second; ++f) { if (possible_cotranscript(hits1_in_ref[i], *f)) { happy_mates.push_back(make_pair(i,f - hits2_in_ref.begin())); marked.insert(f - hits2_in_ref.begin()); found_hit = true; } } if (!found_hit) map1_singletons.push_back(i); } for (size_t i = 0; i < hits2_in_ref.size(); ++i) { if (marked.find(i) == marked.end()) { map2_singletons.push_back(i); } } }
void best_insert_mappings(uint64_t refid, ReadTable& it, /*const string& name,*/ HitList& hits1_in_ref, HitList& hits2_in_ref, BestInsertAlignmentTable& best_status_for_inserts, bool prefer_shorter_pairs) { long chucked_for_shorter_pair = 0; std::set<size_t> marked; HitList::iterator last_good = hits2_in_ref.begin(); for (size_t i = 0; i < hits1_in_ref.size(); ++i) { BowtieHit& h1 = hits1_in_ref[i]; pair<HitList::iterator, HitList::iterator> range_pair; range_pair = equal_range(last_good, hits2_in_ref.end(), h1, hit_insert_id_lt); bool found_hit = false; if (range_pair.first != range_pair.second) last_good = range_pair.first; uint32_t obs_order = it.observation_order(h1.insert_id()); for (HitList::iterator f = range_pair.first; f != range_pair.second; ++f) { BowtieHit& h2 = *f; if (h1.insert_id() == h2.insert_id()) { // max mate inner distance (genomic) int min_mate_inner_dist = inner_dist_mean - inner_dist_std_dev; if (max_mate_inner_dist == -1) { max_mate_inner_dist = inner_dist_mean + inner_dist_std_dev; } InsertAlignmentGrade s(h1, h2, min_mate_inner_dist, max_mate_inner_dist); pair<InsertAlignmentGrade, vector<InsertAlignment> >& insert_best = best_status_for_inserts[obs_order]; InsertAlignmentGrade& current = insert_best.first; // Is the new status better than the current best one? if (current < s) { insert_best.second.clear(); current = s; insert_best.second.push_back(InsertAlignment(refid, &h1, &h2)); } else if (!(s < current)) { if (prefer_shorter_pairs && current.num_mapped == 2) { pair<int, int> dc = pair_distances(*(insert_best.second[0].left_alignment), *(insert_best.second[0].right_alignment)); pair<int, int> ds = pair_distances(h1,h2); if (ds.second < dc.second) { chucked_for_shorter_pair += insert_best.second.size(); insert_best.second.clear(); current = s; insert_best.second.push_back(InsertAlignment(refid, &h1, &h2)); } } else { insert_best.second.push_back(InsertAlignment(refid, &h1, &h2)); } } marked.insert(f - hits2_in_ref.begin()); found_hit = true; } } if (!found_hit) { pair<InsertAlignmentGrade, vector<InsertAlignment> >& insert_best = best_status_for_inserts[obs_order]; InsertAlignmentGrade& current = insert_best.first; InsertAlignmentGrade s(h1); if (current < s) { insert_best.second.clear(); current = s; insert_best.second.push_back(InsertAlignment(refid, &h1, NULL)); } else if (! (s < current)) { insert_best.second.push_back(InsertAlignment(refid, &h1, NULL)); } } } for (size_t i = 0; i < hits2_in_ref.size(); ++i) { BowtieHit& h2 = hits2_in_ref[i]; uint32_t obs_order = it.observation_order(h2.insert_id()); pair<InsertAlignmentGrade, vector<InsertAlignment> >& insert_best = best_status_for_inserts[obs_order]; InsertAlignmentGrade& current = insert_best.first; InsertAlignmentGrade s(h2); // Did we include h2 as part of a pairing already, or is this first time // we've seen it? If so, it's a singleton. if (marked.find(i) == marked.end()) { if (current < s) { insert_best.second.clear(); current = s; insert_best.second.push_back(InsertAlignment(refid, NULL, &h2)); } else if (! (s < current)) { insert_best.second.push_back(InsertAlignment(refid, NULL, &h2)); } } } fprintf(stderr, "Chucked %ld pairs for shorter pairing of same mates\n", chucked_for_shorter_pair); }
/** * Compute the intersection between the line segment and the capped cylinder. * * Site from is ALWAYS fluid * Site to is ALWAYS solid * * Therefore we expect exactly one intersection. Due to floating point errors, * we can't guarantee this. So, we search for intersections with some * tolerance (macro TOL) and pick the closest to fluid site (as given by the * parametic line coordinate t. We use a priority_queue to keep the hits in * order. */ Hit ComputeIntersection(CylinderData* cyl, std::vector<Iolet*>& iolets, Site& from, Site& to) { HitList hitList = HitList(); /* * The equation of the line segment is: * x(t) = a + t (b - a) t E (0, 1) */ Vector& n = cyl->Axis; double& r = cyl->Radius; Vector& c = cyl->Centre; double& h = cyl->Length; { /* * The equation determining intersection with an INFINITE cylinder of * radius r is: * [(b-a)^2 - ((b-a).n)^2] t^2 + [2 a.(b - a) - 2 (a.n)((b-a).n)] t + [a^2 - (a.n)^2 - r^2] = 0 * So first compute the coefficients and then the discriminant of the eqn */ Vector a = from.Position - c; Vector b = to.Position - c; Vector b_a = b - a; double b_aDOTn = Vector::Dot(b_a, n); double aDOTn = Vector::Dot(a, n); double A = (b_a.GetMagnitudeSquared() - b_aDOTn * b_aDOTn); double B = 2. * (Vector::Dot(a, b_a) - aDOTn * b_aDOTn); double C = a.GetMagnitudeSquared() - aDOTn * aDOTn - r * r; double discriminant = B * B - 4 * A * C; if (discriminant < 0.) { // No real solutions. } else if (discriminant == 0) { // Exactly one solution, i.e. line segment just brushes the cylinder. // This means the line must be outside the cylinder everywhere else, // so we will count this as no intersection. } else { // Two real solutions. So we have two intersections between the // infinite line and infinite cylinder. // If t outside (0,1), then the intersection isn't on the line segment // we care about. std::vector<double> ts(2); ts[0] = (-B + std::sqrt(discriminant)) / (2 * A); ts[1] = (-B - std::sqrt(discriminant)) / (2 * A); for (std::vector<double>::iterator tIt = ts.begin(); tIt != ts.end(); ++tIt) { double t = *tIt; if (t > 0. && t < 1. + TOL) { // Hit in part of line we care about. // Now check if it's on the finite cylinder. This requires that // x.n E (-h/2, h/2) double xDOTn = aDOTn + t * b_aDOTn; if (xDOTn >= -0.5 * h - TOL && xDOTn <= 0.5 * h + TOL) { // Real cylinder hit! Hit hit; hit.t = t; hit.pt = from.Position + b_a * t; hit.cellId = -1; hitList.push(hit); } } } } } /* * Now we want to look for intersections with the capping planes. */ Vector& a = from.Position; Vector& b = to.Position; Vector b_a = b - a; for (std::vector<Iolet*>::iterator iIt = iolets.begin(); iIt != iolets.end(); ++iIt) { Iolet* iolet = *iIt; /* * Plane equation is x.p = q.p (p = plane normal, q = point on plane) * Line is x = a + t(b-a) */ Vector& q = iolet->Centre; Vector& p = iolet->Normal; double t = Vector::Dot(q - a, p) / Vector::Dot(b_a, p); if (t > 0. && t < 1. + TOL) { // Intersection within the line segment. Now check within cap. Vector x = a + b_a * t; Vector x_c = x - c; double x_cDOTn = Vector::Dot(x_c, n); Vector radial = x_c - n * x_cDOTn; if (radial.GetMagnitudeSquared() < (r + TOL) * (r + TOL)) { // Within the cap Hit hit; hit.t = t; hit.pt = x; hit.cellId = iIt - iolets.begin(); hitList.push(hit); } } } // We know there SHOULD be exactly one intersection. Take the closest. if (hitList.size() == 0) throw InconsistentFluidnessError(from, to, hitList.size()); // Ensure that the hit lies on the link Hit ans = hitList.top(); if (ans.t > 1.) { ans.t = 1.; ans.pt = b; } return ans; }
/** * R T _ B R E P _ S H O T * * Intersect a ray with a brep. * If an intersection occurs, a struct seg will be acquired * and filled in. * * Returns - * 0 MISS * >0 HIT */ int rt_brep_shot(struct soltab *stp, register struct xray *rp, struct application *ap, struct seg *seghead) { //TRACE1("rt_brep_shot origin:" << ON_PRINT3(rp->r_pt) << " dir:" << ON_PRINT3(rp->r_dir)); TRACE("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"); vect_t invdir; struct brep_specific* bs = (struct brep_specific*)stp->st_specific; // check the hierarchy to see if we have a hit at a leaf node BBNode::IsectList inters; ON_Ray r = toXRay(rp); bs->bvh->intersectsHierarchy(r, &inters); if (inters.size() == 0) return 0; // MISS TRACE1("bboxes: " << inters.size()); // find all the hits (XXX very inefficient right now!) HitList all_hits; // record all hits MissList misses; // XXX - get rid of this stuff (for debugging) int s = 0; for (BBNode::IsectList::iterator i = inters.begin(); i != inters.end(); i++) { const SubsurfaceBBNode* sbv = dynamic_cast<SubsurfaceBBNode*>((*i).m_node); const ON_BrepFace* f = sbv->m_face; const ON_Surface* surf = f->SurfaceOf(); brep_hit* hit; pt2d_t uv = {sbv->m_u.Mid(),sbv->m_v.Mid()}; TRACE1("surface: " << s); int status = brep_intersect(sbv, f, surf, uv, r, all_hits); if (status == BREP_INTERSECT_FOUND) { TRACE("INTERSECTION: " << PT(all_hits.back().point) << all_hits.back().trimmed << ", " << all_hits.back().closeToEdge << ", " << all_hits.back().oob); } else { TRACE1("dammit"); misses.push_back(ip_t(all_hits.size()-1,status)); } s++; } HitList hits = all_hits; // sort the hits hits.sort(); int num = 0; for (HitList::iterator i = hits.begin(); i != hits.end(); ++i) { TRACE("hit " << num << ": " << PT(i->point) << " [" << VDOT(i->normal,rp->r_dir) << "] " << i->trimmed << ", " << i->closeToEdge << ", " << i->oob); ++num; } TRACE("---"); num = 0; for (HitList::iterator i = hits.begin(); i != hits.end(); ++i) { if ((i->trimmed && !i->closeToEdge) || i->oob || NEAR_ZERO(VDOT(i->normal,rp->r_dir),RT_DOT_TOL)) { // remove what we were removing earlier if (i->oob) { TRACE("\toob u: " << i->uv[0] << ", " << IVAL(i->sbv->m_u)); TRACE("\toob v: " << i->uv[1] << ", " << IVAL(i->sbv->m_v)); } i = hits.erase(i); if (i != hits.begin()) --i; continue; } TRACE("hit " << num << ": " << PT(i->point) << " [" << VDOT(i->normal,rp->r_dir) << "]"); ++num; } { // we should have "valid" points now, remove duplicates or grazes HitList::iterator last = hits.begin(); HitList::iterator i = hits.begin(); ++i; while (i != hits.end()) { if ((*i) == (*last)) { double lastDot = VDOT(last->normal,rp->r_dir); double iDot = VDOT(i->normal,rp->r_dir); if (sign(lastDot) != sign(iDot)) { // delete them both i = hits.erase(last); i = hits.erase(i); last = i; if (i != hits.end()) ++i; } else { // just delete the second i = hits.erase(i); } } else { last = i; ++i; } } } // remove "duplicate" points // HitList::iterator new_end = unique(hits.begin(), hits.end()); // hits.erase(new_end, hits.end()); if (hits.size() > 1 && (hits.size() % 2) != 0) { cerr << "WTF???" << endl; #if PLOTTING pcount++; if (pcount > -1) { point_t ray; point_t vscaled; VSCALE(vscaled,rp->r_dir,100); VADD2(ray,rp->r_pt,vscaled); COLOR_PLOT(200,200,200); LINE_PLOT(rp->r_pt,ray); } #endif num = 0; int lastSign = 0; MissList::iterator m = misses.begin(); for (HitList::iterator i = all_hits.begin(); i != all_hits.end(); ++i) { double dot = VDOT(i->normal,rp->r_dir); #if PLOTTING if (pcount > -1) { // set the color of point and normal if (i->trimmed && i->closeToEdge) { COLOR_PLOT(0,0,255); // blue is trimmed but close to edge } else if (i->trimmed) { COLOR_PLOT(255,255,0); // yellow trimmed } else if (i->oob) { COLOR_PLOT(255,0,0); // red is oob } else if (NEAR_ZERO(VDOT(i->normal,rp->r_dir),RT_DOT_TOL)) { COLOR_PLOT(0,255,255); // purple is grazing } else { COLOR_PLOT(0,255,0); // green is regular surface } // draw normal point_t v; VADD2(v,i->point,i->normal); LINE_PLOT(i->point,v); // draw intersection PT_PLOT(i->point); // draw bounding box BB_PLOT(i->sbv->m_node.m_min,i->sbv->m_node.m_max); fflush(plot_file()); } #endif // if ((num == 0 && dot > 0) || sign(dot) == lastSign) { // remove hits with "bad" normals // i = hits.erase(i); // --i; // TRACE("removed a hit!"); // continue; // } else { // lastSign = sign(dot); // } TRACE("hit " << num << ": " << ON_PRINT3(i->point) << " [" << dot << "]"); while ((m != misses.end()) && (m->first == num)) { TRACE("miss " << num << ": " << BREP_INTERSECT_GET_REASON(m->second)); ++m; } num++; } while (m != misses.end()) { TRACE("miss " << BREP_INTERSECT_GET_REASON(m->second)); ++m; } } bool hit = false; if (hits.size() > 0) { if (hits.size() % 2 == 0) { // take each pair as a segment for (HitList::iterator i = hits.begin(); i != hits.end(); ++i) { brep_hit& in = *i; i++; brep_hit& out = *i; register struct seg* segp; RT_GET_SEG(segp, ap->a_resource); segp->seg_stp = stp; VMOVE(segp->seg_in.hit_point, in.point); VMOVE(segp->seg_in.hit_normal, in.normal); segp->seg_in.hit_dist = DIST_PT_PT(rp->r_pt,in.point); segp->seg_in.hit_surfno = in.face.m_face_index; VSET(segp->seg_in.hit_vpriv,in.uv[0],in.uv[1],0.0); VMOVE(segp->seg_out.hit_point, out.point); VMOVE(segp->seg_out.hit_normal, out.normal); segp->seg_out.hit_dist = DIST_PT_PT(rp->r_pt,out.point); segp->seg_out.hit_surfno = out.face.m_face_index; VSET(segp->seg_out.hit_vpriv,out.uv[0],out.uv[1],0.0); BU_LIST_INSERT( &(seghead->l), &(segp->l) ); } hit = true; } else { TRACE2("screen xy: " << ap->a_x << "," << ap->a_y); } } return (hit) ? hits.size() : 0; // MISS }