void LinearAlgebra::QRDecomposition(const Mat2F32 &m, Mat2F32 &Q, Mat2F32 &R){ Q = LinearAlgebra::orthogonalGramSchmidt(m); R.clear(); R.resize(m.sizeI(),m.sizeJ()); std::vector<VecF32> v_a(m.sizeI(),VecF32(m.sizeI())); for(unsigned int j =0;j<m.sizeJ();j++) v_a[j]=m.getCol(j); for(unsigned int i =0;i<m.sizeI();i++){ VecF32 e = Q.getCol(i); for(unsigned int j =i;j<m.sizeJ();j++){ R(i,j)=productInner(e,v_a[j]); } } }
// This routine tries to find the 'grain' of a block by a weighting of dot // products relative to all sides. A few notes: // 1. It tries to first run wiht a handy-cap to take only street-level roads. // It then tries again if the filter is too harsh. // 2. It does an intentionally bad job when there are a huge number of sides // since such high-count polygons aren't sane AGB candidates. // 3. It ALWAYS returns some answer, no matter how goofy the polygon. void find_major_axis(vector<block_pt>& pts, Segment2 * out_segment, Vector2 * out_major, Vector2 * out_minor, double * bounds) { double best_v = -1.0; Vector2 temp_a, temp_b; double bounds_temp[4]; if(out_major == NULL) out_major = &temp_a; if(out_minor == NULL) out_minor = &temp_b; if(bounds == NULL) bounds = bounds_temp; bool elev_ok = false; for(int tries = 0; tries < 2; ++tries) { for(int i = 0; i < pts.size(); ++i) if(elev_ok || ground_road_access_for_he(pts[i].orig)) { int j = (i + 1) % pts.size(); Vector2 v_a(pts[i].loc,pts[j].loc); v_a.normalize(); Vector2 v_b(v_a.perpendicular_ccw()); double total = 0.0; int max_k = min(pts.size(),PTS_LIM); for(int k = 0; k < max_k; ++k) { int l = (k + 1) % pts.size(); Vector2 s(pts[k].loc,pts[l].loc); total += max(fabs(v_a.dot(s)),fabs(v_b.dot(s))); } if(total >= best_v) { best_v = total; if(out_segment) *out_segment = Segment2(pts[i].loc,pts[j].loc); *out_major = v_a; *out_minor = v_b; } } if(best_v != -1) break; elev_ok = true; } { int longest = -1; double corr_len = -1; for(int i = 0; i < pts.size(); ++i) if(/*elev_ok ||*/ ground_road_access_for_he(pts[i].orig)) { int j = (i + 1) % pts.size(); Vector2 this_side(pts[i].loc,pts[j].loc); double len = this_side.normalize(); double my_corr = fltmax2(fabs(this_side.dot(*out_major)), fabs(this_side.dot(*out_minor))); if(my_corr > 0.996194698091746) { my_corr *= len; if(my_corr > corr_len) { longest = i; corr_len = my_corr; } } } if(longest >= 0) { int i = longest; int j = (longest + 1) % pts.size(); Vector2 v_a(pts[i].loc,pts[j].loc); v_a.normalize(); Vector2 v_b(v_a.perpendicular_ccw()); if(out_segment) *out_segment = Segment2(pts[i].loc,pts[j].loc); *out_major = v_a; *out_minor = v_b; } } bounds[2] = bounds[0] = out_major->dot(Vector2(pts[0].loc)); bounds[3] = bounds[1] = out_minor->dot(Vector2(pts[0].loc)); for(int n = 1; n < pts.size(); ++n) { double ca = out_major->dot(Vector2(pts[n].loc)); double cb = out_minor->dot(Vector2(pts[n].loc)); bounds[0] = min(bounds[0],ca); bounds[1] = min(bounds[1],cb); bounds[2] = max(bounds[2],ca); bounds[3] = max(bounds[3],cb); } // if(fabs(bounds[3] - bounds[1]) > fabs(bounds[2] - bounds[0])) // { // *out_major = out_major->perpendicular_ccw(); // *out_minor = out_minor->perpendicular_ccw(); // // bounds[2] = bounds[0] = out_major->dot(Vector2(pts[0].loc)); // bounds[3] = bounds[1] = out_minor->dot(Vector2(pts[0].loc)); // for(int n = 1; n < pts.size(); ++n) // { // double ca = out_major->dot(Vector2(pts[n].loc)); // double cb = out_minor->dot(Vector2(pts[n].loc)); // bounds[0] = min(bounds[0],ca); // bounds[1] = min(bounds[1],cb); // bounds[2] = max(bounds[2],ca); // bounds[3] = max(bounds[3],cb); // } // // } }