26 bool ctxVectorMapErrorOccurred =
false;
30 static const bool debug =
false;
31 static const bool debugBitmap =
false;
32 static const bool debugVector =
false;
34 char vectorFile[4096];
35 char renderFile[4096];
38 mapName = string(name);
40 snprintf(vectorFile, 4095,
"%s/%s/%s_vector.txt",mapsFolder.c_str(),name,name);
41 snprintf(renderFile, 4095,
"%s/%s/%s_render.dat",mapsFolder.c_str(),name,name);
42 if(debug) printf(
"Loading map: %s\n",name);
45 if(debug) printf(
"Loading vector map from %s\n",vectorFile);
46 pFile = fopen (vectorFile,
"r");
49 snprintf(buf, 1023,
"Unable to load vector file %s!",vectorFile);
54 minX = minY = FLT_MAX;
55 maxX = maxY = -FLT_MAX;
57 while(fscanf(pFile,
"%f,%f,%f,%f",&x1,&y1,&x2,&y2)==4){
58 if(debugVector) printf(
"Line%d: <%f %f> <%f %f>\n",(
int)lines.size(),x1,y1,x2,y2);
70 lines.push_back(
line2f(p0,p1));
71 lines.at(lines.size()-1).calcValues();
73 if(debug) printf(
"%d lines loaded into vector map\n",(
int)lines.size());
74 if(debug) printf(
"Extents: %.3f,%.3f : %.3f,%.3f\n",
minX, minY, maxX, maxY);
78 preRenderExists =
false;
80 pFile = fopen(renderFile,
"r");
83 snprintf(buf, 1023,
"Unable to load pre-render file %s!",renderFile);
89 error = fread(&
visListWidth,
sizeof(
unsigned int),1,pFile)!=1;
90 error = error || (fread(&visListHeight,
sizeof(
unsigned int),1,pFile)!=1);
96 visibilityList[i].resize(visListHeight);
100 error = fread(&x,
sizeof(
int),1,pFile)!=1;
101 error = error || (fread(&y,
sizeof(
int),1,pFile)!=1);
102 error = error || (fread(&size,
sizeof(
int),1,pFile)!=1);
104 if(x<0 || y<0 || x>
visListWidth-1 || y>visListHeight-1){
106 snprintf(msg, 4095,
"Invalid loc (%d,%d) in pre-render file",x,y);
107 TerminalWarning(msg);
110 visibilityList[x][y].resize(size);
112 error = error || (fread(visibilityList[x][y].data(),
sizeof(
int),size,pFile) != size);
114 if(!error && debug && ((y+1)*100)%visListHeight==0){
115 int progress = (y+1)*100/visListHeight;
116 printf(
"\rReading pre-render file... %3d%% ",progress);
124 snprintf(buf, 1023,
"\nUnable to parse pre-render file %s",renderFile);
125 TerminalWarning(buf);
126 preRenderExists =
false;
128 if(debug) printf(
"\nRead %d locations into visibility list\n",cnt);
129 preRenderExists =
true;
134 if(debug) printf(
"Done loading map\n\n");
139 VectorMap::VectorMap(
const char* name,
const char* _mapsFolder,
bool usePreRender)
141 mapsFolder=string(_mapsFolder);
146 VectorMap::~VectorMap()
154 return &visibilityList[xInd][yInd];
159 static const bool UsePreRender =
true;
160 float intervals = numRays - 1.0;
161 float a0 = angle - 0.5*intervals*da;
162 float a1 = angle + 0.5*intervals*da;
163 vector<float> rayCast;
165 vector< int >* visibilityList;
167 for(
float a=a0; a<a1; a += da){
168 float ray = maxRange;
169 if(preRenderExists && UsePreRender){
171 for(
unsigned int i=0; i<visibilityList->size(); i++){
172 int lineIndex = visibilityList->at(i);
173 float curRay = maxRange;
174 if(lines[lineIndex].intersects((
vector2f)loc,(
float)a)){
175 line2f &l = lines[lineIndex];
181 float sinTheta = l.Dir().cross(heading.
norm());
182 curRay = fabs(l.Perp().dot(loc-l.P0())/sinTheta);
188 TerminalWarning(
"Ray Cast Fail!");
189 printf(
"line: %.3f,%.3f : %.3f,%.3f loc:%.3f,%.3f a:%.1f\u00b0 curRay:%f\n",V2COMP(lines[lineIndex].P0()),V2COMP(lines[lineIndex].P1()),V2COMP(loc),DEG(a),curRay);
197 ray = min(ray, curRay);
208 for(
unsigned int i=0; i<sceneLines.size(); i++){
209 if(lines[sceneLines[i]].intersects(loc,a)){
210 ray = min(ray, lines[sceneLines[i]].distFromLine1((
vector2f)loc,(
float)a,
false));
215 rayCast.push_back(ray);
224 loc1 = loc + minRange*dir;
225 loc2 = loc + maxRange*dir;
229 for(
unsigned int i=0; i<visibilityList.size(); i++){
230 int lineIndex = visibilityList[i];
231 if(!lines[lineIndex].intersects(loc1,loc2,
false,
false,
true))
234 vector2f p2 = lines[lineIndex].intersection(loc1,loc2,
false,
false);
235 if( (p2-loc).sqlength()<(p-loc).sqlength()){
237 bestLine = lineIndex;
246 static const bool UsePreRender =
true;
248 vector<int> correspondences;
249 correspondences.clear();
250 vector<int> locVisibilityList;
251 if(UsePreRender && preRenderExists)
256 if(analytical && lines!=NULL){
258 vector<LineSegment> segments = sortLineSegments(loc,*lines);
259 float rotMat1[4] = {cos(angle), -sin(angle), sin(angle), cos(angle)};
261 correspondences.resize(pointCloud.size());
262 for(
int i=0; i<pointCloud.size(); i++){
264 p.set(p.x*rotMat1[0] + p.y*rotMat1[1], p.x*rotMat1[2] + p.y*rotMat1[3]);
265 int correspondence = -1;
267 for(
int j=0; j<segments.size() && correspondence<0; j++){
268 if(segments[j].v0.cross(p)>=0.0f && segments[j].v1.cross(p)<=0.0f)
269 correspondence = segments[j].index;
271 correspondences[i] = correspondence;
274 for(
int i=0; i<pointCloud.size(); i++){
275 float curAngle = angle_mod(pointCloud[i].angle() + angle);
276 correspondences.push_back(
getLineCorrespondence(loc,curAngle,minRange, maxRange, locVisibilityList));
279 return correspondences;
285 vector<int> correspondences;
286 correspondences.clear();
287 vector<int> locVisibilityList;
292 for(
float a=a0; a<a1; a += da){
295 return correspondences;
298 vector< VectorMap::LineSegment > VectorMap::sortLineSegments(
vector2f& loc, vector< line2f >& lines)
300 static const float eps = RAD(0.001);
301 vector< VectorMap::LineSegment > segments;
303 for(
unsigned int i=0; i<lines.size(); i++){
304 float a0 = angle_pos((lines[i].P0()-loc).angle());
305 float a1 = angle_pos((lines[i].P1()-loc).angle());
306 if((lines[i].P0()-loc).cross(lines[i].P1()-loc)<0.0)
308 LineSegment curSegment;
311 curSegment.index = i;
312 curSegment.v0.heading(a0);
313 curSegment.v1.heading(a1);
315 if(segments.size()<1){
316 segments.push_back(curSegment);
322 segments.insert(segments.begin(), curSegment);
327 for(; j<segments.size()-1 && !found; j++){
328 if( segments[j].a1<=a0+eps && segments[j+1].a0>=a1-eps )
332 if(found && j<segments.size())
333 segments.insert(segments.begin()+j,curSegment);
335 segments.push_back(curSegment);
338 if(segments.size()>0){
339 if(segments[0].a0>segments[0].a1){
340 LineSegment curSegment;
341 curSegment.a0 = segments[0].a0;
342 curSegment.a1 = M_2PI;
343 curSegment.index = segments[0].index;
344 segments[0].a0 = 0.0;
345 segments.push_back(curSegment);
355 float intervals = numRays - 1.0;
356 float a0 = angle - 0.5*intervals*da;
357 float a1 = angle + 0.5*intervals*da;
359 if(analytical && (lines!=NULL)){
363 vector< VectorMap::LineSegment > segments = sortLineSegments(loc,*lines);
364 vector<int> correspondences;
365 correspondences.clear();
366 for(
unsigned int i=0; i<numRays; i++){
367 correspondences.push_back(-1);
369 int maxScanRays = floor((
float)M_2PI/da);
371 for(
unsigned int i=0; i<segments.size(); i++){
372 float aStart = segments[i].a0;
373 float aEnd = segments[i].a1;
376 int index = ceil( (
float) (aStart - a0)/da );
379 for(
float a = aStart; a<aEnd; a+=da, index++){
380 int j = index%maxScanRays;
382 correspondences[j] = segments[i].index;
387 return correspondences;
394 static const float eps = 1e-6;
395 vector<int> linesList, sceneLines;
396 vector<line2f> tmpList;
400 for(
unsigned int i=0; i<lines.size(); i++){
401 if(lines[i].closestDistFromLine(loc,
true)<maxRange)
402 linesList.push_back(i);
404 for(
unsigned int i=0; i<linesList.size(); i++){
405 line2f curLine = lines[linesList[i]];
407 for(
unsigned int j=0;j<linesList.size() && curLine.Length()>=eps; j++){
410 if(lines[linesList[j]].Length()<eps)
414 if( curLine.Length()>eps ){
415 sceneLines.push_back(linesList[i]);
421 inline float cross(
const Eigen::Vector3f &v1,
const Eigen::Vector3f &v2)
423 return v1.cross(v2).z();
426 static const float eps = 1e-5;
428 inline bool lineIntersectsLine(
const Eigen::Vector3f &l1_p0,
const Eigen::Vector3f &l1_p1,
const Eigen::Vector3f &l1_dir,
429 const Eigen::Vector3f &l2_p0,
const Eigen::Vector3f &l2_p1,
const Eigen::Vector3f &l2_dir)
431 return cross(l1_dir,l2_p0-l1_p0)*cross(l1_dir,l2_p1-l1_p0)<eps && cross(l2_dir,l1_p0-l2_p0)*cross(l2_dir,l1_p1-l2_p0)<eps;
434 inline bool lineIntersectsRay(
const Eigen::Vector3f &l1_p0,
const Eigen::Vector3f &l1_p1,
435 const Eigen::Vector3f &r_p0,
const Eigen::Vector3f &r_dir)
437 return cross(l1_p0-r_p0,r_dir)*cross(l1_p1-r_p0,r_dir)<eps;
440 inline vector2f tovector2f(
const Eigen::Vector3f &v)
445 inline Eigen::Vector3f lineIntersectionLine(
const Eigen::Vector3f &l1_p0,
const Eigen::Vector3f &l1_p1,
const Eigen::Vector3f &l1_dir,
446 const Eigen::Vector3f &l2_p0,
const Eigen::Vector3f &l2_p1,
const Eigen::Vector3f &l2_dir)
448 float den = cross(l2_dir, l1_dir);
449 float ua = cross(l1_p0-l2_p0, l1_dir)/den;
450 return l2_p0 + ua*l2_dir;
453 inline Eigen::Vector3f lineIntersectionLine(
const Eigen::Vector3f &l1_p0,
const Eigen::Vector3f &l1_p1,
454 const Eigen::Vector3f &l2_p0,
const Eigen::Vector3f &l2_p1)
456 Eigen::Vector3f l1_dir(l1_p1-l1_p0), l2_dir(l2_p1-l2_p0);
457 float den = cross(l2_dir, l1_dir);
458 float ua = cross(l1_p0-l2_p0, l1_dir)/den;
459 return l2_p0 + ua*l2_dir;
462 void VectorMap::trimOcclusion2(
vector2f& loc_g,
line2f& line1,
line2f& line2, vector< line2f >& sceneLines)
464 using namespace Eigen;
466 static const float eps = 1e-4;
467 static const float sqeps = 1e-8;
468 if(line1.Length()<eps || line2.Length()<eps)
471 Vector3f loc(V2COMP(loc_g),0);
472 Vector3f l1_p0(V2COMP(line1.P0()),0);
473 Vector3f l1_p1(V2COMP(line1.P1()),0);
474 Vector3f l1_dir(l1_p1-l1_p0);
475 Vector3f l1_r0(l1_p0-loc);
476 Vector3f l1_r1(l1_p1-loc);
477 Vector3f l2_p0(V2COMP(line2.P0()),0);
478 Vector3f l2_p1(V2COMP(line2.P1()),0);
479 Vector3f l2_dir(l2_p1-l2_p0);
480 Vector3f l2_r0(l2_p0-loc);
481 Vector3f l2_r1(l2_p1-loc);
489 if( cross(l1_r0,l1_r1)<0.0 ){
493 if( cross(l2_r0,l2_r1)<0.0 ){
498 if( (cross(l1_r0, l2_r0)>=0.0 && cross(l1_r1, l2_r0)>=0.0) || (cross(l2_r1, l1_r0)>=0.0 && cross(l2_r1, l2_r1)>=0.0) )
500 bool intersects, rayOcclusion1, rayOcclusion2;
508 intersects = lineIntersectsLine(l1_p0,l1_p1,l1_dir, l2_p0,l2_p1,l2_dir);
509 rayOcclusion1 = lineIntersectsRay(l2_p0,l2_p1, loc,l1_r0);
510 rayOcclusion2 = lineIntersectsRay(l2_p0,l2_p1, loc,l1_r1);
516 mid = lineIntersectionLine(l1_p0,l1_p1,l1_dir, l2_p0,l2_p1,l2_dir);
517 if( cross((l1_p0-mid), l2_p0-mid) > 0.0){
519 line2 =
line2f(tovector2f(mid),l2_p1_g);
522 if(lineIntersectsRay(mid,l2_p0, loc, l1_r0)){
524 p = lineIntersectionLine(mid, l2_p0, loc,l1_p0);
525 if((l2_p0-p).squaredNorm()>sqeps)
526 sceneLines.push_back(
line2f(l2_p0_g, tovector2f(p)));
530 line2 =
line2f(l2_p0_g,tovector2f(mid));
533 if(lineIntersectsRay(mid,l2_p1, loc, l1_r1)){
535 p = lineIntersectionLine(mid, l2_p0, loc,l1_p1);
536 if((l2_p1-p).squaredNorm()>sqeps)
537 sceneLines.push_back(
line2f(l2_p1_g, tovector2f(p)));
543 bool occlusion0 = rayOcclusion1 && !line2.
intersects(
line2f(loc_g,l1_p0_g),
false,
false,
false);
544 bool occlusion1 = rayOcclusion2 && !line2.
intersects(
line2f(loc_g,l1_p1_g),
false,
false,
false);
545 if(completeOcclusion){
547 line2 =
line2f(0.0,0.0,0.0,0.0);
548 }
else if(occlusion0 && occlusion1){
551 mid = lineIntersectionLine(l2_p0,l2_p1,l2_dir,loc,l1_p0,l1_r0);
553 line2f newLine2(l2_p0_g,tovector2f(mid));
555 mid = lineIntersectionLine(l2_p0,l2_p1,l2_dir,loc,l1_p1,l1_r1);
558 if((mid-l2_p1).squaredNorm()>sqeps)
559 sceneLines.push_back(
line2f(tovector2f(mid),l2_p1_g));
560 }
else if(occlusion0){
563 mid = lineIntersectionLine(l2_p0,l2_p1,l2_dir,loc,l1_p0,l1_r0);
564 line2 =
line2f(l2_p0_g,tovector2f(mid));
565 }
else if(occlusion1){
568 mid = lineIntersectionLine(l2_p0,l2_p1,l2_dir,loc,l1_p1,l1_r1);
569 line2 =
line2f(tovector2f(mid),l2_p1_g);
577 static const float eps = 1e-4;
578 static const float sqeps = 1e-8;
579 if(line1.Length()<eps || line2.Length()<eps)
592 if( l1_r0.
cross(l1_r1)<0.0 ){
596 if( l2_r0.
cross(l2_r1)<0.0 ){
601 if( (l1_r0.
cross(l2_r0)>=0.0 && l1_r1.
cross(l2_r0)>=0.0) || (l2_r1.
cross(l1_r0)>=0.0 && l2_r1.
cross(l2_r1)>=0.0) )
603 bool intersects, rayOcclusion1, rayOcclusion2;
607 intersects = line2.
intersects(line1,
false,
false,
false);
608 rayOcclusion1 = line2.
intersects(loc,l1_r0,
false);
609 rayOcclusion2 = line2.
intersects(loc,l1_r1,
false);
615 if( (l1_p0-mid).cross(l2_p0-mid) > 0.0){
617 line2 =
line2f(mid,l2_p1);
621 if((l2_p0-p).sqlength()>sqeps)
622 sceneLines.push_back(
line2f(l2_p0, p));
626 line2 =
line2f(l2_p0,mid);
630 if((l2_p1-p).sqlength()>sqeps)
631 sceneLines.push_back(
line2f(l2_p1, p));
637 bool occlusion0 = rayOcclusion1 && !line2.
intersects(
line2f(loc,l1_p0),
false,
false,
false);
638 bool occlusion1 = rayOcclusion2 && !line2.
intersects(
line2f(loc,l1_p1),
false,
false,
false);
639 if(completeOcclusion){
641 line2 =
line2f(0.0,0.0,0.0,0.0);
642 }
else if(occlusion0 && occlusion1){
647 line2f newLine2(l2_p0,mid);
651 if((mid-l2_p1).sqlength()>sqeps)
652 sceneLines.push_back(
line2f(mid,l2_p1));
653 }
else if(occlusion0){
656 line2 =
line2f(l2_p0,mid);
657 }
else if(occlusion1){
660 line2 =
line2f(mid,l2_p1);
668 static const float eps = 0.001;
669 static const float MinRange = 0.03;
670 static const float MaxRange = 5.0;
671 static const unsigned int MaxLines = 200;
676 bool obtuseView = rightMargin.
cross(leftMargin)<=0.0;
678 vector<line2f> scene, sceneCleaned;
679 vector<line2f> linesList;
680 vector<int>* locVisibilityList;
683 sceneCleaned.clear();
689 locVisibilityList =
new vector<int>;
692 for(
unsigned int i=0; i<locVisibilityList->size(); i++){
693 linesList.push_back(lines[locVisibilityList->at(i)]);
696 for(i=0; i<linesList.size() && i<MaxLines; i++){
697 line2f curLine = linesList[i];
699 for(j=0;j<scene.size() && curLine.Length()>=eps; j++){
700 if(scene[j].Length()<eps)
705 if( curLine.Length()>eps ){
706 for(j=0; j<scene.size(); j++){
707 if(scene[j].Length()<eps)
712 scene.push_back(curLine);
716 if(linesList.size()>=MaxLines){
718 sprintf(buf,
"Runaway Analytic Scene Render at %.30f,%.30f, %.3f : %.3f\u00b0",V2COMP(loc),DEG(a0),DEG(a1));
719 TerminalWarning(buf);
721 for(i=0; i<scene.size(); i++){
722 if(scene[i].Length()>eps)
723 sceneCleaned.push_back(scene[i]);
vector< int > getRayToLineCorrespondences(vector2f loc, float angle, float a0, float a1, const std::vector< vector2f > pointCloud, float minRange, float maxRange, bool analytical=false, vector< line2f > *lines=0)
Get lines (for each ray) which intersect first the rays starting at angles a0 to a1, at increments of da.
C++ Interfaces: VectorMap, LineSection.
unsigned int visListWidth
size of the visibilityList array
vector< int > * getVisibilityList(float x, float y)
Get Visibility list for specified location.
int getLineCorrespondence(vector2f loc, float angle, float minRange, float maxRange, const std::vector< int > &visibilityList)
Get line which intersects first the given ray first.
vector< line2f > sceneRender(vector2f loc, float a0=0.0, float a1=M_2PI)
Perform an analytical scene render. i.e. Generate a list of lines visible from loc, and the start and end angles subtended by them.
GVector::vector2d< num > intersection(Line2d< num > l1, bool extendL0, bool extendL1)
Return the point of intersection of two lines.
void trimOcclusion(vector2f &loc, line2f &line1, line2f &line2, vector< line2f > &sceneLines)
Checks if any part of line2 is occluded by line1 when seen from loc, and if so, line2 is trimmed acco...
num cross(const vector2d< num > p) const MustUseResult
return z component of 3D cross product on 2D vectors. right handed.
vector2d< num > norm() const MustUseResult
return a unit length vector in the same direction
bool intersects(Line2d< num > l1, bool extendL0, bool extendL1, bool touch)
Return true if the line l1 intersects this line. If touch==true then touching counts as intersection...
bool loadMap(const char *name, bool usePreRender)
Load map by name.
double visListResolution
number of meters per cell in visibilityList array
void heading(num angle)
make a unit vector at given angle
vector< int > getSceneLines(vector2f loc, float maxRange)
Get a set of lines which are visible from loc.
vector< float > getRayCast(vector2f loc, float angle, float da, int numRays, float minRange, float maxRange)
Get ray cast from vector map at given location and angle, as specified by center angle, angle increment (da), and numRays to scan.