/** * @brief Find the largest particles that meet a criteria * @param binaryImage Image to inspect * @param hitReport structure containing arry of hits - first hit is largest * @param rect area to search * @param numParticles Number of particles in array * @return 0 = error */ int GetLargestParticles(Image* binaryImage, ImageHits *hitReport, Rect rect, int numberHitsRequested) { //char funcName[]="GetLargestParticles"; HitList *hitsInArea = new HitList(); // list to contain all particles within area sorted by size int i; /* determine number of particles in thresholded image */ int numParticles = -1; int success = frcCountParticles(binaryImage, &numParticles); if ( !success ) { return success; } //DPRINTF(LOG_DEBUG, "particles requested = %i ; particles found in image = %i", numberHitsRequested, numParticles); /* if no particles found we can quit here */ if (numParticles <= 0) { return 1; } // successful, but zero particles found /* get areas of each particle and insert into list */ double particleArea; int count = 0; for (i = 0; i < numParticles; ++i) { success = imaqMeasureParticle(binaryImage, i, 0, IMAQ_MT_AREA, &particleArea); if ( !success ) { return success; } //DPRINTF (LOG_INFO, "size of particle %i = %g", i, particleArea); // see if is in the right area and large enough to be considered a possible target //TODO: Call InArea & delete TempInArea when new WPILib is released //if (InArea(binaryImage, i, rect)) { //if ( InArea(binaryImage, i, rect) && (particleArea >= FRC_MINIMUM_PIXELS_FOR_TARGET) ) { if ( TempInArea(binaryImage, i, rect) && (particleArea >= FRC_MINIMUM_PIXELS_FOR_TARGET) ) { hitsInArea->AddNode(i,particleArea); count++; } } // see what's in the list hitsInArea->debugDump(); // fill in return structure - number of hits if (numParticles < numberHitsRequested) { hitReport->numberOfHits = numParticles; } else { hitReport->numberOfHits = numberHitsRequested; } // fill in return structure - indices & areas of largest hits HitNode *hitPtr = hitsInArea->head; for (i = 0; i < hitReport->numberOfHits; ++i) { if (hitPtr == NULL) { break; } hitReport->indices[i] = hitPtr->nodeIndex; hitReport->areas[i] = hitPtr->nodeArea; //DPRINTF (LOG_INFO, "put index %i in hitReport %i", hitPtr->nodeIndex, hitReport->indices[i]); hitPtr = hitPtr->next; } // dispose of HitList delete hitsInArea; return 1; // success }
int brep_edge_check(int reason, const SubsurfaceBBNode* sbv, const ON_BrepFace* face, const ON_Surface* surf, const ON_Ray& r, HitList& hits) { // if the intersection was not found for any reason, we need to // check and see if we are close to any topological edges; we may // have hit a crack... // the proper way to do this is to only look at edges // interesecting with the subsurface bounding box... but for // now, we'll look at the edges associated with the face for the bounding box... // XXX - optimize this set<ON_BrepEdge*> edges; ON_3dPoint pt; for (int i = 0; i < face->LoopCount(); i++) { ON_BrepLoop* loop = face->Loop(i); for (int j = 0; j < loop->TrimCount(); j++) { ON_BrepTrim* trim = loop->Trim(j); ON_BrepEdge* edge = trim->Edge(); pair<set<ON_BrepEdge*>::iterator, bool> res = edges.insert(edge); // if (res.second) { // only check if its the first time we've seen this // edge const ON_Curve* curve = edge->EdgeCurveOf(); Sample s; if (curve->CloseTo(ON_3dPoint(hits.back().point), BREP_EDGE_MISS_TOLERANCE, s)) { TRACE1("CLOSE TO EDGE"); hits.back().closeToEdge = true; return BREP_INTERSECT_FOUND; } } } return BREP_INTERSECT_TRIMMED; }
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); } } }
/** * 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; }
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); }
/** * 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 }
int brep_intersect(const SubsurfaceBBNode* sbv, const ON_BrepFace* face, const ON_Surface* surf, pt2d_t uv, ON_Ray& ray, HitList& hits) { int found = BREP_INTERSECT_ROOT_ITERATION_LIMIT; fastf_t Dlast = MAX_FASTF; int diverge_iter = 0; pt2d_t Rcurr; pt2d_t new_uv; ON_3dPoint pt; ON_3dVector su; ON_3dVector sv; plane_ray pr; brep_get_plane_ray(ray, pr); for (int i = 0; i < BREP_MAX_ITERATIONS; i++) { brep_r(surf,pr,uv,pt,su,sv,Rcurr); //fastf_t d = v2mag(Rcurr); fastf_t d = DIST_PT_PT(pt,ray.m_origin); //if (d < BREP_INTERSECTION_ROOT_EPSILON) { if (NEAR_ZERO(d-Dlast,BREP_INTERSECTION_ROOT_EPSILON)) { TRACE1("R:"<<ON_PRINT2(Rcurr)); found = BREP_INTERSECT_FOUND; break; } else if (d > Dlast) { found = BREP_INTERSECT_ROOT_DIVERGED; //break; diverge_iter++; if (diverge_iter > 10) break; //return brep_edge_check(found, sbv, face, surf, ray, hits); } brep_newton_iterate(surf, pr, Rcurr, su, sv, uv, new_uv); move(uv, new_uv); Dlast = d; } if (found > 0) { fastf_t l,h; ON_3dPoint _pt; ON_3dVector _norm; surf->EvNormal(uv[0],uv[1],_pt,_norm); if (face->m_bRev) _norm.Reverse(); hits.push_back(brep_hit(*face,(const fastf_t*)ray.m_origin,(const fastf_t*)_pt,(const fastf_t*)_norm, uv)); hits.back().sbv = sbv; if (!sbv->m_u.Includes(uv[0]) || !sbv->m_v.Includes(uv[1])) { // if (!sbv->m_u.Includes(uv[0]-BREP_SAME_POINT_TOLERANCE) || // !sbv->m_v.Includes(uv[1]-BREP_SAME_POINT_TOLERANCE)) { hits.back().oob = true; return BREP_INTERSECT_OOB; } if (sbv->doTrimming() && brep_pt_trimmed(uv, *face)) { hits.back().trimmed = true; TRACE1("Should be TRIMMED!"); // if the point was trimmed, see if it is close to the edge before removing it return brep_edge_check(BREP_INTERSECT_TRIMMED, sbv, face, surf, ray, hits); //return BREP_INTERSECT_TRIMMED; } } return found; }