/[gzz]/gzz/gfx/libcoords/Coords.cxx
ViewVC logotype

Diff of /gzz/gfx/libcoords/Coords.cxx

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.56 by tjl, Fri Dec 13 14:49:38 2002 UTC revision 1.57 by tjl, Thu Dec 19 09:12:39 2002 UTC
# Line 472  namespace Coords { Line 472  namespace Coords {
472          }          }
473      };      };
474    
475    
476        /** Project a point through another point to a circle.
477         * @param pt the point to project
478         * @param p the projection center
479         * @param ctr The center of the circle
480         * @param rad The radius of the circle
481         * @return The projected point, or if not possible, the original pt.
482         */
483        Vec project2circle(Vec pt, Vec p, Vec ctr, float rad) {
484            Vec ao = pt - ctr;
485            Vec ap = pt - p;
486    
487            // Coefficients of the 2nd degree equation
488            float a = dot(ap, ap);
489            float b = 2*dot(ap, ao);
490            float c = dot(ao, ao) - rad * rad;
491    
492            // determinant of the equation
493            float det = b*b - 4*a*c;
494    
495            float ans = (det > 0 ? (-b + sqrt(det)) / (2*a) : 0);
496    
497            return pt + ans * ap;
498    
499        }
500    
501    
502      /** Buoy coordinates.      /** Buoy coordinates.
503       * <p>       * <p>
504       * The depth is between -1 (center) and 0 (edge)       * The depth is between -1 (center) and 0 (edge)
505       * <p>       * <p>
506       * Parameter layout:       * Parameter layout:
507       *  x_circle, y_circle, radius, x_projpoint, y_projpoint, pointdir       *  x_circle, y_circle, radius, x_projpoint, y_projpoint, shiftamount
508       *  <p>       *  <p>
      *  Pointdir = 0 -> place at center, pointdir = 1, place  
      *  normally, -1, place with projpoint = center+(center-projpoint)  
509       *  Linear interp between 0..1, 0..-1       *  Linear interp between 0..1, 0..-1
510       */       */
511      class BuoyOnCircleCoords {      class BuoyOnCircleCoords {
         bool valid;  
512      public:      public:
513          typedef AffineXYCoords BaseTransform;          typedef AffineXYCoords BaseTransform;
514          enum { NParams = 6, NDetermining = 1 };          enum { NParams = 6, NDetermining = 1 };
# Line 493  namespace Coords { Line 517  namespace Coords {
517    
518              CoordSys *anchor = *anchorp;              CoordSys *anchor = *anchorp;
519    
520              float pointdir = params[5];              Pt ctr(params[0], params[1]);
521              ZVec ctr(params[0], params[1], 0);              Pt proj(params[3], params[4]);
             ZVec proj(params[3], params[4], 0);  
522              float radius = params[2];              float radius = params[2];
523                float shiftamount = params[5];
524    
             if(pointdir < 0) {  
                 proj = ctr + (ctr - proj);  
                 pointdir = -pointdir;  
             }  
525    
526              // Get the anchor of the buoy              // Get the anchor of the buoy
527              ZPt anchorPt = anchor->transform(ZPt(0,0,0));              ZPt anchorZPt(anchor->transform(ZPt(0,0,0)));
528              // Now that we have the anchor, project              Pt anchorPt(anchorZPt);
             // from it to the circle.  
             ZVec amc = proj - ctr; amc.z = 0;  
             ZVec v = anchorPt - proj; v.z = 0;  
             // coeffs of 2nd degree eq  
             float a = v.dot(v);  
             float b = 2*v.dot(amc);  
             float c = amc.dot(amc) - radius*radius;  
   
             float rdist = (anchorPt-ctr).length() / radius;  
   
             float det = b*b - 4*a*c;  
   
             DBG(dbg_buoy) << "eq: "<<anchorPt<<" "<<amc<<" "<<v<<" "<<a<<" "<<b<<" "<<c<<"\n";  
   
             ZPt pt;  
             if(det <= 0) {  
                 pt = ZVec(0,0,0);  
                 DBG(dbg_buoy) << "No solution - zero\n";  
             }  else {  
                 float ans = (-b + sqrt(det)) / (2*a);  
                 pt = proj + ans * v;  
                 DBG(dbg_buoy) << "solution: "<<pt<<"\n";  
             }  
529    
530                // shifted point: default buoy location
531                Pt shifted = anchorPt + (ctr - proj) * shiftamount;
532    
533              ZPt tr = ctr + pointdir * (pt-ctr);              float shiftrad = (shifted - ctr).length();
534                float anchorrad = (anchorPt - ctr).length();
535                
536                Pt buoy;
537                if(shiftrad >= radius) {
538                    // if shifted point is outside circle, our work is done
539                    buoy = shifted;
540                } else {
541                    if(anchorrad >= radius)
542                        // otherwise, kludge it by placing it on the anchor.
543                        // There's a small jump here; we should do it differently.
544                        buoy = anchorPt; // XXX ???
545                    else
546                        // If both anchor and shifted point are inside circle,
547                        // project.
548                        buoy = project2circle(anchorPt, proj, ctr, radius);
549                }
550    
551              valid = 1;              float scale = 1-anchorrad / radius ;
             float scale = 1-rdist;  
552    
553              if(scale <.0001) {              if(scale <shiftamount) {
554                  valid = 0;                  scale = shiftamount;
                 scale = 1;  
555              }              }
556              DBG(dbg_buoy) << "final: "<<tr<<" "<<valid<<" "<<scale<<" "<<rdist<<"\n";              DBG(dbg_buoy) << "final: "<<buoy << " "<<" "<<scale<<" "<<"\n";
557    
558              newparams[0] = tr.x;              newparams[0] = buoy.x;
559              newparams[1] = tr.y;              newparams[1] = buoy.y;
560              newparams[2] = tr.z - scale;              newparams[2] = anchorZPt.z - scale;
561              newparams[3] = scale;              newparams[3] = scale;
562              newparams[4] = 0;              newparams[4] = 0;
563              newparams[5] = 0;              newparams[5] = 0;
564              newparams[6] = scale;              newparams[6] = scale;
565          }          }
566          virtual bool shouldBeDrawn() {          bool shouldBeDrawn() { return true; }
             return valid;  
         }  
567      };      };
568    
569      /** Rotation around 3D vector.      /** Rotation around 3D vector.

Legend:
Removed from v.1.56  
changed lines
  Added in v.1.57

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26