grimsa / polysplit

An implementation of polygon splitting algorithm (unfinished)
MIT License
10 stars 6 forks source link

Area calculation trapezoid #8

Open dennemark opened 6 years ago

dennemark commented 6 years ago

Hi, I have adapted your script to the Rhino3d/Grasshopper environment: https://decodingspaces-toolbox.org/grasshopper-snippets-for-urban-design-and-analysis/

I stumbled over an issue with your algorithm, when performing the minimum cut in a trapezoid. You find the cutting line by linearly interpolating the position on the angled trapezoid edges according to the needed area:

double fraction = areaToCutAway / trapezoidArea; Coordinate pointOfCutOnEdgeA = trapezoidEdgeOnEdgeA.pointAlong(fraction);

As far as I understood, you choose the angled trapezoid edges. But interpolation does not work for them. It is a bit more complicated as seen in this video: https://www.youtube.com/watch?v=GoP6wIR8-DU

I chose to "refractorise" the fraction value according to the video. This is a bit of pseudo code for those who really need to dig into it. Hope it helps.

double distance = distanceOfEdge;
      double wholeDistance = distanceOfEdge+shortestDistanceToIntersectionPointWithOppositeEdge;
      Vector dir = directionOfEdge;
      dir.Unitize();
      double remainingDistance = wholeDistance - distance;
      Vector rotateVec = dir * remainingDistance;
      rotateVec.Rotate(Math.Acos(remainingDistance / wholeDistance), Vector.ZAxis);
    //in the video the first two circles intersect and their intersection point is projected onto the extended edge
    // this can be simply done via Vector dot product
      double projectedDistance = Math.Abs(Vector.DotProduct(rotateVec, dir));
    //afterwards we find calculate the distance of our fraction
     double fractionDistance= fraction * (wholeDistance - projectedDistance);
    // in the video the point of the fraction is projected back onto the big circle. we can use trigonometry for this to create the sides of a triangle
      double adjacentSide = wholeDistance - (fracturedDistance);
      double oppositeSide = Math.Sqrt(Math.Pow(wholeDistance / 2.0, 2) - Math.Pow((wholeDistance / 2.0 - adjacentSide ), 2));
      double hypothenuse = Math.Sqrt(Math.Pow(adjacentSide, 2) + Math.Pow((oppositeSide ), 2));
     //with these values we can calculate the new fraction
     double newFraction = (wholeDistance - hypothenuse) / distance;

    }

Best, Martin