AniGeometryUtils.cpp 6.31 KB
//
//  AniGeometryUtils.cpp
//  SteveMaggieCpp
//
//  Created by Katarzyna Kalinowska-Górska on 20.05.2017.
//
//

#include <stdio.h>
#include "AniGeometryUtils.h"

//TODO: use original scale doesn't seem to work
cocos2d::Rect AniGeometryUtils::getBoundingBoxToWorld(cocos2d::Node* node, bool ignoreTransformations)
{
    auto tempScale = node->getScaleX() != node->getScaleY() ? node->getScaleX() : node->getScale();
    auto tempRotation = node->getRotation();
    
    if(ignoreTransformations){
        node->setScale(1);
        node->setRotation(0);
    }
    
    auto bb = node->getBoundingBox();
    bb.origin = cocos2d::Point(0,0);
    if(ignoreTransformations){
        node->setScale(tempScale);
        node->setRotation(tempRotation);
    }
    auto bbToWorld = cocos2d::RectApplyTransform(bb, node->getNodeToWorldTransform());
    
//    if(ignoreTransformations){
//        node->setScale(tempScale);
//        node->setRotation(tempRotation);
//    }
    
    return bbToWorld;
}

void AniGeometryUtils::flipChildX(cocos2d::Node* flippedParent, cocos2d::Node* child){
    auto childDFromCenter = flippedParent->getBoundingBox().size.width/2 - child->getPositionX();
    child->setPositionX(flippedParent->getBoundingBox().size.width/2 + childDFromCenter);
}

cocos2d::Rect AniGeometryUtils::flippedXRect(cocos2d::Node* flippedParent, cocos2d::Rect rect){
    auto rectMidDFromCenter = flippedParent->getBoundingBox().size.width/2 - rect.getMidX();
    auto anchorPointcorrection = /*rectMidDFromCenter > 0 ? rect.size.width/2 :*/ -rect.size.width/2;
    auto newRect = rect;
    newRect.origin.x = flippedParent->getBoundingBox().size.width/2 + rectMidDFromCenter + anchorPointcorrection;
    return newRect;
}

cocos2d::Point AniGeometryUtils::flippedXPoint(cocos2d::Node* flippedParent, cocos2d::Point point){
    auto dxFromCenter = flippedParent->getBoundingBox().size.width/2 - point.x;
    return cocos2d::Point(flippedParent->getBoundingBox().size.width/2 + dxFromCenter, point.y);
}

cocos2d::Rect AniGeometryUtils::getBoundingBoxToWorldForSubrect(cocos2d::Node* node, cocos2d::Rect subrect){
    auto subrectToWorld = AniGeometryUtils::getBoundingBoxToWorld(node);
    subrectToWorld.origin.y += subrect.origin.y;
    subrectToWorld.size.height = subrect.size.height;
    subrectToWorld.origin.x += subrect.origin.x;
    subrectToWorld.size.width = subrect.size.width;
    return subrectToWorld;
}

cocos2d::Rect AniGeometryUtils::getRectIntersection(cocos2d::Rect rect1, cocos2d::Rect rect2)
{
    auto intersection = cocos2d::Rect(MAX(rect1.origin.x, rect2.origin.x), MAX(rect1.origin.y, rect2.origin.y), 0, 0);
    intersection.size.width = MIN(rect1.origin.x + rect1.size.width, rect2.origin.x + rect2.size.width) - intersection.origin.x;
    intersection.size.height = MIN(rect1.origin.y + rect1.size.height, rect2.origin.y + rect2.size.height) - intersection.origin.y;
    return intersection;
}

bool AniGeometryUtils::segmentIntersectsRect(cocos2d::Rect rect, cocos2d::Point lineP1, cocos2d::Point lineP2)
{
    if(rect.containsPoint(lineP1) || rect.containsPoint(lineP2)){
        return true;
    }
    
    auto rectX2 = rect.origin.x + rect.size.width;
    auto rectY2 = rect.origin.y + rect.size.height;
    
    if((lineP1.x > rectX2 && lineP2.x > rectX2) || (lineP1.x < rect.origin.x && lineP2.x < rect.origin.x) || (lineP1.y > rectY2 && lineP2.y > rectY2) || (lineP1.y < rect.origin.y && lineP2.y < rect.origin.y)){
        return false;
    }
    
    if(lineP1.y == lineP2.y){
        return true;
    }
    
    if(lineP1.x == lineP2.x){
        return true;
    }
    
    auto lineA = (lineP1.y - lineP2.y)/(lineP1.x - lineP2.x);
    auto lineB = lineP1.y - lineP1.x * lineA;
    
    auto yr1 = rect.origin.x*lineA + lineB;
    auto yr2 = (rect.origin.x+rect.size.width)*lineA + lineB;
    auto xr1 = (rect.origin.y - lineB)/lineA;
    auto xr2 = (rect.origin.y+rect.size.height - lineB)/lineA;
    
    return (yr1 >= rect.origin.y && yr1 <= rectY2) || (yr2 >= rect.origin.y && yr2 <= rectY2) || (xr1 >= rect.origin.x && xr1 <= rectX2) || (xr2 >= rect.origin.x && xr2 <= rectX2);
}

cocos2d::Point AniGeometryUtils::addPoints(std::vector<cocos2d::Point> points)
{
    float sumX = 0, sumY = 0;
    for(int i = 0; i < points.size(); ++i){
        sumX += points[i].x;
        sumY += points[i].y;
    }
    
    return cocos2d::Point(sumX, sumY);
}

void AniGeometryUtils::getLineABCFromPoints(cocos2d::Point pointA, cocos2d::Point pointB, float (&line)[3])
{
    auto A = pointA.y - pointB.y;
    auto B = pointB.x - pointA.x;
    auto C = pointA.x * pointB.y - pointB.x * pointA.y;
    
    line[0] = A;
    line[1] = B;
    line[2] = C;
}

bool AniGeometryUtils::segmentCrossesLine(cocos2d::Point sPointA, cocos2d::Point sPointB, float lineA, float lineB, float lineC)
{
    auto valueA = lineA * sPointA.x + lineB * sPointA.y + lineC;
    auto valueB = lineA * sPointB.x + lineB * sPointB.y + lineC;
    
    if(valueA * valueB <= 0){
        return true;
    }
    
    return false;
}

float AniGeometryUtils::calculateIntersectionPercentage(cocos2d::Rect rect1, cocos2d::Rect rect2, int percentageOfWhichRect)
{
    if(rect1.size.width == 0 || rect1.size.height == 0 || rect2.size.width == 0 || rect2.size.height == 0){
        return 0;
    }
    
    if(!rect1.intersectsRect(rect2)){
        return 0;
    }
    
    auto intersection = AniGeometryUtils::getRectIntersection(rect1, rect2);
    
    auto r = percentageOfWhichRect == 0 ? rect1 : rect2;
    return intersection.size.width * intersection.size.height / (r.size.width * r.size.height);
}


/*
    // relatively to line y = 0
    lineAngle : function(lineP1, lineP2){
    
        if(lineP1.x == lineP2.x){
            return 0;
        } else if(lineP1.y == lineP2.y){
            return Math.PI/2;
        }
        
        // build a triangle, with third point equal to (x1, y2), and get the arc sin of (p3,p2)/(p1,p2)
        let point3 = new cc.p(lineP1.x, lineP2.y);
        let angle = Math.asin(cc.pDistance(lineP2, point3)/cc.pDistance(lineP1, lineP2));
        
        // add a multiple of PI/2, depending on the quarter
        if(lineP2.y < lineP1.y){
            if(lineP2.x > lineP1.x){
                angle = Math.PI - angle;
            } else {
                angle = Math.PI + angle;
            }
        } else if(lineP2.x < lineP1.x){
            angle = Math.PI*2 - angle;
        }

        return angle;
    }

};
*/