Tuesday, June 26, 2012

Some useful matrix methods...


Every time while developing iOS Applications which use matrix related calculations, I used to think how to convert index to matrix co-ordinate etc. So i thought of writing this one -  why to reinvent the wheel every-time :)

-(NSInteger) getIndexFromMatrix : (CGPoint) inPoint size:(CGSize)gridSize
{
    if( (inPoint.x >= 0 && inPoint.x < gridSize.width) && (inPoint.y >= 0 && inPoint.y < gridSize.height))
        return inPoint.x*(gridSize.width-1) + (inPoint.x+inPoint.y);
    return -1;
}

-(CGPoint) getMatrixFromIndex : (NSInteger) index size:(CGSize)gridSize
{
    return CGPointMake(index/(int)gridSize.width, index%(int)gridSize.height);
}

-(BOOL) isIndexIsDialognal:(CGPoint)index1 andIndex:(CGPoint)index2
{
    return (abs(index1.x - index2.x)==abs(index1.y - index2.y));
}

-(NSMutableArray*) adjacentIndicesForIndex:(CGPoint)inPoint matrixSize:(CGSize) matrixSize
{
    NSMutableArray *array = [NSMutableArray array];
    
    for (int dx = -1; dx <= 1; ++dx) 
        for (int dy = -1; dy <= 1; ++dy) 
            if (dx != 0 || dy != 0
            {
                CGPoint adjacentIndex = CGPointMake(inPoint.x + dx, inPoint.y + dy);
                if(![self isIndexIsDialognal:adjacentIndex andIndex:inPoint]) //Checking for diagonal elements
                {
                    NSInteger index = [self getIndexFromMatrix:adjacentIndex size:matrixSize];
                    if(index >= 0)
                        [array addObject:[NSNumber numberWithInt:index]];
                }
            }
    return array;
}

#Some Coolest thinks i have learnt while developing an application

1. Mapping between two range
   //NewValue = (((OldValue - OldMin) * (NewMax - NewMin)) / (OldMax - OldMin)) + NewMin

+(NSInteger)convertValue:(NSInteger)OldValue newRange:(NSRange)newRange oldRange:(NSRange)oldRange
{
    NSInteger NewValue = (((OldValue - oldRange.location) * (newRange.length - newRange.location)) / (oldRange.length - oldRange.location)) + newRange.location;
    return NewValue;

}

 2. To check if a point is inside a convex polygon
// wn_PnPoly(): winding number test for a point in a polygon
//      Input:   P = a point,
//               V[] = vertex points of a polygon V[n+1] with V[n]=V[0]
//      Return:  wn = the winding number (=0 only if P is outside V[])
//http://www.softsurfer.com/Archive/algorithm_0103/algorithm_0103.htm

// isLeft(): tests if a point is Left|On|Right of an infinite line.
//    Input:  three points P0, P1, and P2
//    Return: >0 for P2 left of the line through P0 and P1
//            =0 for P2 on the line
//            <0 for P2 right of the line
//    See: the January 2001 Algorithm "Area of 2D and 3D Triangles and Polygons"
inline int isLeft( point P0, point P1, point P2 )
{
    return ( (P1.mX - P0.mX) * (P2.mY - P0.mY)
            - (P2.mX - P0.mX) * (P1.mY - P0.mY) );
}

FFBool isPointInsidePolyGon( point P, point* V, int n )
{
    int    wn = 0;    // the winding number counter

  // loop through all edges of the polygon
    for (int i=0; i<n; i++) {   // edge from V[i] to V[i+1]
        if (V[i].mY <= P.mY) {         // start y <= P.y
            if (V[i+1].mY > P.mY)      // an upward crossing
                if (isLeft( V[i], V[i+1], P) > 0)  // P left of edge
                    ++wn;            // have a valid up intersect
        }
        else {                       // start y > P.y (no test needed)
            if (V[i+1].mY <= P.mY)     // a downward crossing
                if (isLeft( V[i], V[i+1], P) < 0)  // P right of edge
                    --wn;            // have a valid down intersect
        }
    }
    return wn;
}