Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p><strong>Update 3 Alternative Idea</strong></p> <p>An alternative solution could be to calculate the percentage values based on the two end points of the gradient.<br/> In this Picture you see the original polygon <code>abcd</code>, its bounding box <code>a'b'c'd'</code> and the gradient <code>g1g2</code>. The aim is now to calculate first the two points <code>g1</code> and <code>g2</code> in absolute values and then calculate the relative values of these two.</p> <p><img src="https://i.stack.imgur.com/xnrUI.png" alt="bounding box"> </p> <p>I've derived an algorithm that does most of what I described but it fails short of calculating the intersection between the gradient and the bounding box. I have an idea on how to solve this problem but right now not the time to implement it, so I list the steps for that.<br/> The basic idea is to test if the gradient intersects with one of the lines through the corners of the bounding box (<code>a'b'</code>,<code>b'c'</code>,<code>c'd'</code>,<code>d'a'</code>) and then test if the intersection is in on the edge in question. There are now two special cases that need handling. 1. the gradient is vertical, this means its slope is infinity 2. the side in question is vertical, again this means its slope is infinity All other cases are easily solvable with basic math (two point form of a line, intersection of two lines).</p> <p><em>My algorithm</em></p> <pre><code>_ = require('underscore') function intersectGradientWithPolygon(polygon, gradient){ var sides = [ ["a", "b"], ["b", "c"], ["c", "d"], ["d", "a"] ]; var boundingBox = calculateBoundingBox(polygon); // intersect each side of the bounding box with the gradient var intersections = _.map(sides, function(side){ var intersection = intersect(boundingBox[side[0]], boundingBox[side[1]], gradient.a, gradient.b); if(intersection){ // calculate the percentages console.log(JSON.stringify(intersection)); return calcPercentage(intersection, boundingBox); } }); return intersections; } function Point(x,y){ this.x = x; this.y = y; } function calcPercentage(intersection, boundingBox){ var lengthX = (boundingBox.max.x - boundingBox.min.x), lengthY = (boundingBox.max.y - boundingBox.min.y), x = (intersection.x / lengthX) * 100, y = (intersection.y / lengthY) * 100; } function calculateBoundingBox(polygon){ var xValues = _.pluck(polygon, 'x'), yValues = _.pluck(polygon, 'y'), maxX = _.max(xValues), maxY = _.max(yValues), minX = _.min(xValues), minY = _.min(yValues); return { "a": new Point(minX, maxY), "b": new Point(maxX, maxY), "c": new Point(maxX, minY), "d": new Point(minX, minY), "max": new Point(maxX, maxY), "min": new Point(minX, minY) }; } // tests if the two lines a1, b1 and a2, b2 intersect and // returns the point of intersection if the do so function intersect(a1, b1, a2, b2){ var s = new Point( ); // TODO // This is the part that is missing // one needs to implement what I described above at this point // if (isInIntervall(s.x, a1.x, b1.x) &amp;&amp; isInIntervall(s.y, a2.y, b2.y)){ return s; } else { return false; } } // test if a point is in the intervall [a,b] function isInIntervall(point, a, b){ return (point &gt;= a) &amp;&amp; (point &lt;=b); } </code></pre> <p><strong>Update 2</strong> </p> <blockquote> <p><strong>Question:</strong> Also how should the gradient coordinates change if the polygon is moved in space as a whole and not stretched.?</p> <p><strong>Answer:</strong> You calculate the amount that you move one point of your polygon in x and y and move the points of the gradient the exact same amount.</p> </blockquote> <p>I've now changed the algorithm to be based of scaling on one side of the polygon by absolute amount of units. I've also created an image to explain what the algorithm does</p> <ol> <li>original polygon</li> <li>scaled polygon by a scale factor determined by the inputs</li> <li>move the polygon back to the original place</li> </ol> <p><img src="https://i.stack.imgur.com/qsP0X.png" alt="explain"></p> <p><strong>Updated 15.7.2012</strong> I've derived an algorithm based on the idea I proposed using transformation matrices for the transform. I hadn't time to test it but the code is running under node.js and should run in the browser if you include <a href="http://underscorejs.org" rel="nofollow noreferrer">underscore.js</a> and <a href="http://sylvester.jcoglan.com/" rel="nofollow noreferrer">sylvester</a> (matrix operations) in your document.</p> <p><strong>The Setup</strong></p> <pre><code>/* underscore for some helper methods * http:*http:*underscorejs.org */ _ = require("underscore"); /* matrix operations * http:*sylvester.jcoglan.com */ require("sylvester"); </code></pre> <p><strong>The inputs</strong></p> <pre><code>var gradient = { "a":{ "x": 165.3425, "y": 39.7002 }, "b":{ "x": -49.991, "y": 43.0337 } }; var polygon = { "a": { "x": 137.145, "y": 41.204 }, "b": { "x": 68.572, "y": 0 }, "c": { "x": 0, "y": 41.204 }, "d": { "x": 68.572, "y": 82.396 } }; // the scales are now absolute values in the same units as the coordinates var scaleAbsX = 100; var scaleAbsY = 100 * Math.tan( 62/2 * (Math.PI/180) ); // this describes the side that is scaled var side = ["a", "b"]; </code></pre> <p><strong>The Algorithm</strong></p> <pre><code>scalePolyWithGradient = function(polygon, gradient, scaleAbsX, scaleAbsY, side){ // 1. Scale by factor: derive factor from input scaling and then translate into scaling matrix // 2. Apply scale to the gradient // 3. Translate both back // create a scaling matrix based of the input scales // get the two points of the scaled side var point1 = polygon[side[0]], point2 = polygon[side[1]]; // scale these points var scaledPoint1 = { "x": point1.x + scaleAbsX, "y": point1.y + scaleAbsY }, scaledPoint2 = { "x": point2.x + scaleAbsX, "y": point2.y + scaleAbsY }; // calculate the relative scales var scaleRelX = scaledPoint1.x / point1.x, scaleRelY = scaledPoint1.y / point1.y; // create the scale matrix var scaleMatrix = $M([ [scaleRelX, 0], [0, scaleRelY] ]); // scale both the polygon and the gradient // we iterate so that the translation is done on every point var scale = function(point){ // convert the point into a matrix point = $M([[point.x], [point.y]]); // scale var newPoint = scaleMatrix.multiply(point); return { "x": newPoint.elements[0][0], "y": newPoint.elements[1][0]}; }; var newPolygon = {}, newGradient = {}; _.each(polygon, function(point, key){ newPolygon[key] = scale(point); }); _.each(gradient, function(point, key){ newGradient[key] = scale(point); }); // calculate the translation to move them to the original position // and move them back // we know that the points to move to their original position are the // ones not in the scale side var sides = _.keys(polygon), // all possible sides movePoints = _.difference(sides, side), // the points not used in the scale point = movePoints[0]; // the first of these points // we use these points to create the translation var oldPoint = polygon[point], newPoint = newPolygon[point]; var translateMatrix = $M([ [newPoint.x - oldPoint.x], [newPoint.y - oldPoint.y] ]); var translate = function(point){ // convert the point into a matrix point = $M([[point.x], [point.y]]); // translate var newPoint = point.add(translateMatrix); return { "x": newPoint.elements[0][0], "y": newPoint.elements[1][0]}; }; // apply the translation _.each(newPolygon, function(point, key){ newPolygon[key] = translate(point); }); _.each(newGradient, function(point, key){ newGradient[key] = translate(point); }); // return the new coordinates return [newPolygon, newGradient]; }; // apply the algorithm var newPolygon, newGradient = null; var result = scalePolyWithGradient(polygon, gradient, scaleAbsX, scaleAbsY, side); newPolygon = result[0]; newGradient = result[1]; </code></pre> <p><strong>The result</strong></p> <pre><code> newPolygon = { "a": { "x": 178.2885, "y":82.405 }, "b": { "x": 96.00089999999999, "y": 20.598999999999997 }, "c": { "x": 13.714500000000001, "y": 82.405 }, "d": { "x": 96.00089999999999, "y":144.19299999999998 } } newGradient = { "a": { "x": 212.12550000000005, "y":80.14930000000001 }, "b": { "x": -46.274699999999996, "y": 85.14955 } } </code></pre> <p><strong>Old Answer</strong></p> <p><a href="https://www.evernote.com/shard/s130/sh/04be966e-143a-46f7-b92a-8cf5df2f656a/fb0edaeebe3cb6a2514da63ea846c8dd/res/fba6488f-3d14-4dc4-bb18-e57cd42805e1/scaling_concept-20120714-210224.png.jpg" rel="nofollow noreferrer">The image is here</a> because I can't upload images to stackoverflow (reputation is to low) </p> <p>I abstracted the side of the polygon so we can focus on that. The left picture is before scaling. Now I've drawn the "whole" gradient to show what needs to be scaled. In order to figure out the needed coordinates one just scales the square of the gradient in the same proportion as the side of the polygon. </p> <p>I know this image is without rotation but this method can be expanded to also incorporate this.</p> <p>I can derive an algorithm for this stuff but haven't had the time to do so. So if this is what you want let me know and I will get to it tomorrow.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload