Week 6 Assignment (desc)

Younghyun Chung

 

Problem 1. Create a function called smoothPath that takes as input an array of points (Vec2d*), the number of points (int), and a smoothing parameter (float) between 0.0 and 1.0. Apply this function to a stroke that has been drawn. Optionally, try applying it to the stroke as it's being drawn.

// global variables
int       numPoints = 0;
Vec2d     pointList[1000];
Vec2d     lastPoint = Vec2d( 0,0 );

void mouseDownFunc ( int button, int state, int x, int y )
{
	mouseX = x;
	mouseY = windowH - y;	  
    
    Vec2d currentPoint = Vec2d( mouseX, mouseY ); // for W5_1

    if ( numPoints < 1000 && ( lastPoint-currentPoint ).length() > 10  )  {
         pointList[ numPoints ].x = mouseX;
         pointList[ numPoints ].y = mouseY;
         lastPoint = currentPoint;
         numPoints++;
    }
}

//an array of points (Vec2d*), the number of points (int), 
//and a smoothing parameter (float) between 0.0 and 1.0
void smoothPath ( Vec2d* Points, int numberPoints, float smoothing ) {
     smoothing /= 2; // give weight, 0-1-0 <=> 0.25-0.5-0.25
     
     //draw original path
     glColor3f ( 0,0,1 );
     glPointSize ( 3.0 );
     glBegin( GL_POINTS );
     for ( int i=0; i<numberPoints; i++ ) {
             glVertex2f ( Points[i].x, Points[i].y );
     }     
     glEnd();

     glLineWidth ( 2.0 );
     glBegin( GL_LINE_STRIP );
     for ( int i=0; i<numberPoints; i++ ) {
             glVertex2f ( Points[i].x, Points[i].y );
     }     
     glEnd();

     // draw smooth path
     glColor3f ( 1,0,0 );
     glBegin ( GL_LINE_STRIP );
     glVertex2f ( Points[0].x, Points[0].y ); // start point
     for ( int i=1; i<numberPoints-1; i++ ) {
         Vec2d smoothPoint;
         
         // smooth with using before and after points
         smoothPoint.x = Points[i-1].x * smoothing/2 + Points[i].x * (1-smoothing) +
                         Points[i+1].x * smoothing/2;
         smoothPoint.y = Points[i-1].y * smoothing/2 + Points[i].y * (1-smoothing) +
                         Points[i+1].y * smoothing/2;
         
         glVertex2f ( smoothPoint.x, smoothPoint.y );
     }
     glVertex2f ( Points[numberPoints-1].x, Points[numberPoints-1].y ); // end point
     glEnd();

}

void drawW6_1a ( void ) {
     // appling to the stroke as it is  being drawn
     smoothPath ( pointList, numPoints, 0.9 ); 
}


// stroke version
void smoothPath2 ( Vec2d* Points, int numberPoints, float smoothing ) {
     smoothing /= 2; // give weight, 0-1-0 <=> 0.25-0.5-0.25

     smoothList[0] = Points[0];
     smoothList[numPoints] = smoothList[numPoints];

     // draw smooth path
     for ( int i=1; i<numberPoints-1; i++ ) {
         Vec2d smoothPoint;
         
         // smooth with using before and after points
         smoothPoint.x = Points[i-1].x * smoothing/2 + Points[i].x * (1-smoothing) +
                         Points[i+1].x * smoothing/2;
         smoothPoint.y = Points[i-1].y * smoothing/2 + Points[i].y * (1-smoothing) +
                         Points[i+1].y * smoothing/2;

         smoothList[i] = smoothPoint;
     }

     for( int i=1;i<numPoints-1;i++ ) {
          Points[i] = smoothList[i];
     }

     float strokeWidth = 10.0;
     glColor4f ( 0.0,0.3,0.0,0.5 );       // alpha value
     glLineWidth ( 5.0 );           
     glBegin ( GL_TRIANGLE_STRIP );
     for ( int i=1; i<numPoints-1; i++ ) {
         Vec2d currentPoint = Points[i]; // center point
         
         // calculating the point of stroke
         Vec2d A = Points[i-1];        
         Vec2d B = Points[i+1];
             
         Vec2d V = B - A;
         V.normalize();
         Vec2d Vp = Vec2d( -V.y, V.x );

         Vec2d C = currentPoint + Vp*strokeWidth/2;
         Vec2d D = currentPoint - Vp*strokeWidth/2;
         
         glVertex2f( C.x, C.y );
         glVertex2f( D.x, D.y );
     }
     
     glEnd();

}


: smooth path, small smoothing parameter


: large smoothing parameter


: smoothing while stroking


video of first and second one

video of third one

video of continuous smoothing of strokes

 

Problem 2. Create a function called distortPath that distorts a shape by pushing its vertices radially away from 10 pre-set points on the screen, each of which should have a different distortion strength. Apply this function to a circle composed of 360 points. Optionally, allow the circle to be dragged about the screen.

void distortPath( Vec2d* Circle, int numCirclePoints, Vec2d* Points, 
                  int numPoints, float* distortStrength) {
     float distortX, distortY;

     // for each point, add distort effect of every distort pre-set point
     for( int i=0;i<numCirclePoints;i++ ) {
          for( int j=0;j<numPoints;j++ ) {
               
               // get distort vector ( direction, length )
               Vec2d distortVector = Circle[i] - Points[j];
               float distance = distortVector.length();
               distortVector.normalize();
               
               distortX += distortVector.x * distortStrength[j] *400 / distance / distance;
               distortY += distortVector.y * distortStrength[j] *400 / distance / distance;
          }    
          
          // change the position of original point
          Circle[i].x += distortX;
          Circle[i].y += distortY;
          
          // allow the circle to be dragged about the screen.
          if ( Circle[i].x > windowW ) Circle[i].x = windowW - 10;
          if ( Circle[i].x < 0 ) Circle[i].x = 10;
          if ( Circle[i].y > windowH ) Circle[i].y = windowH - 10;
          if ( Circle[i].y < 0 ) Circle[i].y = 10;
          
          // initialize the distortion effect
          distortX = 0;
          distortY = 0;
     }

     // draw distortion points
     glColor3f( 0,0,0 );
     glPointSize( 5.0 );
     glBegin( GL_POINTS );
     for( int i=0;i<numPoints;i++ ) {
          glVertex2f( Points[i].x, Points[i].y );
     }
     glEnd();

     // draw distorted circle
     glColor3f( 0,0,1 );
     glBegin( GL_LINE_LOOP );
     for( int i=0;i<numCirclePoints;i++ ) {
               glVertex2f( Circle[i].x, Circle[i].y );
               }
     glEnd();
}

void drawW6_2 ( void ) {

     Vec2d Circle[360];
     float angle;
     float radius = 200;
     Vec2d Center = Vec2d( windowW/2, windowH/2 );

     glBegin( GL_LINE_LOOP );
     
     for(int i=0;i<360;i++) {
             angle = 360.0 / 360 * i; // angle of each point
             Circle[i] = Vec2d( radius*cos_deg(angle)+Center.x,
                                radius*sin_deg(angle)+Center.y );
             glVertex2f( Circle[i].x, Circle[i].y );
     }        
     glEnd();     
     
     Vec2d Points[10] = { Vec2d(500,200), Vec2d(300,350), Vec2d(150,300),
                          Vec2d(200,450), Vec2d(300,500), Vec2d(400,400), 
                          Vec2d(500,550), Vec2d(650,350), Vec2d(400,200),
                          Vec2d(550,150)
                        };
     float Strength[10] = { 100, 50, 200, 300, 200, 
                            20, 150, 10, 400, 100 };

     distortPath( Circle, 360, Points, 10, Strength );

}

: distortion path


video of distortion path

 

Problem 3. Create a function that detects if a drawn stroke intersects itself. If it has, draw a finished shape that uses the intersection point as its start and end point, and is filled in solid red. Call this function continuously while drawing.

// global variables
Vec2d     intersectPoint; 

int intersect( int endPoint ) {   
     // new line
     Vec2d P0a( pointList[endPoint-1].x, pointList[endPoint-1].y );
     Vec2d P0b( pointList[endPoint].x, pointList[endPoint].y );
     Vec2d P1a, P1b;

     float X, Y;

     // check from first line through third last line
     for( int i=0;i<endPoint-2;i++ ) {
          P1a = pointList[i];
          P1b = pointList[i+1];

         // check in intersection is within line segment boundaries
         float left0 = min( P0a.x, P0b.x );
         float right0 = max( P0a.x, P0b.x );
         float left1 = min( P1a.x, P1b.x );
         float right1 = max( P1a.x, P1b.x );
         
         float M0 = ( P0b.y - P0a.y ) / ( P0b.x - P0a.x );
         float M1 = ( P1b.y - P1a.y ) / ( P1b.x - P1a.x );
         
         if ( M0 != M1 ) {
             X = ( P1a.y - P0a.y - P1a.x * M1 + P0a.x * M0 ) / ( M0 - M1 );
             Y = P0a.y + ( X - P0a.x) * M0;
             
             // if it does intersect    
             if ( X > left0 && X < right0 && X > left1 && X < right1 ) {       
                //numPoints = 0;  // for debugging
                intersectPoint = Vec2d ( X,Y );  // store the intersection
                return i; // return the intersected line
             }
         }
     }
     
     return -1; // return -1 if it does not intersect
}

void drawW6_3 ( void ) {
     //draw original path
     
     glColor3f( 0,0,1 );
     glPointSize( 3.0 );
     glBegin( GL_POINTS );
     for( int i=0;i<numPoints;i++ ) {
             glVertex2f ( pointList[i].x, pointList[i].y );
     }
     glEnd();

     glColor3f ( 0,0,1 );
     glLineWidth ( 2.0 );
     glBegin( GL_LINE_STRIP );
     for ( int i=0; i<numPoints; i++ ) 
         glVertex2f ( pointList[i].x, pointList[i].y ); 
     glEnd();
     
     int intersection; // variable for intersected point
     for ( int i=3; i<numPoints; i++ ) {
         int intersection = intersect( i );
         if( intersection > -1 ) {
             glColor3f ( 1,0,0 );
             glBegin( GL_POLYGON );

             glVertex2f ( intersectPoint.x, intersectPoint.y );
             for( int j=intersection+1;j<i;j++ )
                  glVertex2f ( pointList[j].x, pointList[j].y );

             glEnd();
         }     
     }
}




: detecting intersection


: fill whole inside part of intersection


video of the above

video of continuously processing while drawing