diff --git a/src/util/calculateFreehandStatistics.js b/src/util/calculateFreehandStatistics.js index 0435b966c..5d58042e7 100644 --- a/src/util/calculateFreehandStatistics.js +++ b/src/util/calculateFreehandStatistics.js @@ -1,45 +1,38 @@ import pointInFreehandROI from './pointInFreehandROI.js'; -export default function (sp, boundingBox, dataHandles) { +const statisticsObj = { + count: 0, + mean: 0.0, + variance: 0.0, + stdDev: 0.0 +}; +export default function (sp, boundingBox, dataHandles) { let sum = 0; let sumSquared = 0; - let count = 0; let index = 0; for (let y = boundingBox.top; y < boundingBox.top + boundingBox.height; y++) { for (let x = boundingBox.left; x < boundingBox.left + boundingBox.width; x++) { - const point = { + if (pointInFreehandROI(dataHandles, { x, y - }; - - if (pointInFreehandROI(dataHandles, point)) { + })) { sum += sp[index]; sumSquared += sp[index] * sp[index]; - count++; + statisticsObj.count++; } - index++; } } - if (count === 0) { - return { - count, - mean: 0.0, - variance: 0.0, - stdDev: 0.0 - }; + if (statisticsObj.count === 0) { + return statisticsObj; } - const mean = sum / count; - const variance = sumSquared / count - mean * mean; + statisticsObj.mean = sum / statisticsObj.count; + statisticsObj.variance = sumSquared / statisticsObj.count - statisticsObj.mean * statisticsObj.mean; + statisticsObj.stdDev = Math.sqrt(statisticsObj.variance); - return { - count, - mean, - variance, - stdDev: Math.sqrt(variance) - }; + return statisticsObj; } diff --git a/src/util/freeHandIntersect.js b/src/util/freeHandIntersect.js index fe0ade3e0..2ce13356e 100644 --- a/src/util/freeHandIntersect.js +++ b/src/util/freeHandIntersect.js @@ -2,109 +2,64 @@ // Credit and details: geeksforgeeks.org/check-if-two-given-line-segments-intersect/ function freeHandIntersect (newHandle, dataHandles) { - // Here (p1,p2) is the new line proposed by the user. - const k = dataHandles.length - 1; - const p1 = { - x: dataHandles[k].x, - y: dataHandles[k].y - }; - const q1 = { - x: newHandle.x, - y: newHandle.y - }; - - if (doesInteresctOtherLines(dataHandles, p1, q1, k)) { - - return true; - } + // Check if the proposed line will intersect any existent line + const lastHandleId = dataHandles.length - 1; + const lastNode = getCoords(dataHandles[lastHandleId]); + const newNode = getCoords(newHandle); - return false; + return doesIntersectOtherLines(dataHandles, lastNode, newNode, [lastHandleId]); } function freeHandIntersectEnd (dataHandles) { - // Check if line (dataHandles.length -1, 0) intersects with other lines. - const k = dataHandles.length - 1; - const l = 0; - const p1 = { - x: dataHandles[k].x, - y: dataHandles[k].y - }; - const q1 = { - x: dataHandles[l].x, - y: dataHandles[l].y - }; + // Check if the last line will overlap another line. + const lastHandleId = dataHandles.length - 1; + const lastNode = getCoords(dataHandles[lastHandleId]); + const firstNode = getCoords(dataHandles[0]); - if (doesInteresctOtherLines(dataHandles, p1, q1, k, l)) { - - return true; - } - - return false; + return doesIntersectOtherLines(dataHandles, lastNode, firstNode, [lastHandleId, 0]); } -function freeHandIntersectModify (dataHandles, k) { - // Check if line (k, k-1) intersects with other lines - // Where k is the id of the handle being modified. - let l = k - 1; - - // If k is first node, previous node === final node - if (k === 0) { - l = dataHandles.length - 1; - } +function freeHandIntersectModify (dataHandles, modifiedHandleId) { + // Check if the modifiedHandle's previous and next lines will intersect any other line in the polygon + const modifiedNode = getCoords(dataHandles[modifiedHandleId]); - const p1 = { - x: dataHandles[k].x, - y: dataHandles[k].y - }; + // Previous neightbor handle + let neighborHandleId = modifiedHandleId - 1; - const q1 = { - x: dataHandles[l].x, - y: dataHandles[l].y - }; + if (modifiedHandleId === 0) { + neighborHandleId = dataHandles.length - 1; + } - if (doesInteresctOtherLines(dataHandles, p1, q1, k, l)) { + let neighborNode = getCoords(dataHandles[neighborHandleId]); + if (doesIntersectOtherLines(dataHandles, modifiedNode, neighborNode, [modifiedHandleId, neighborHandleId])) { return true; } - // Check if line (k, k+1) intersects with other lines - l = k + 1; - // If k is last node, l === first node - if (k === dataHandles.length - 1) { - l = 0; + // Next neightbor handle + if (modifiedHandleId === dataHandles.length - 1) { + neighborHandleId = 0; + } else { + neighborHandleId = modifiedHandleId + 1; } - q1.x = dataHandles[l].x; - q1.y = dataHandles[l].y; - - if (doesInteresctOtherLines(dataHandles, p1, q1, k, l)) { - - return true; - } + neighborNode = getCoords(dataHandles[neighborHandleId]); - return false; + return doesIntersectOtherLines(dataHandles, modifiedNode, neighborNode, [modifiedHandleId, neighborHandleId]); } - -function doesInteresctOtherLines (dataHandles, p1, q1, k, l) { +function doesIntersectOtherLines (dataHandles, p1, q1, ignoredHandleIds) { let j = dataHandles.length - 1; for (let i = 0; i < dataHandles.length; i++) { - // Ignore lines with node common to subject line - if (i === k || j === k || i === l || j === l) { + if (ignoredHandleIds.indexOf(i) !== -1 || ignoredHandleIds.indexOf(j) !== -1) { j = i; continue; } - const p2 = { - x: dataHandles[j].x, - y: dataHandles[j].y - }; - const q2 = { - x: dataHandles[i].x, - y: dataHandles[i].y - }; + const p2 = getCoords(dataHandles[j]); + const q2 = getCoords(dataHandles[i]); if (doesIntersect(p1, q1, p2, q2)) { return true; @@ -120,6 +75,7 @@ function doesInteresctOtherLines (dataHandles, p1, q1, k, l) { function doesIntersect (p1, q1, p2, q2) { // Check orientation of points in order to determine // If (p1,q1) and (p2,q2) intersect + let result = false; const orient = [ orientation(p1, q1, p2), @@ -130,32 +86,28 @@ function doesIntersect (p1, q1, p2, q2) { // General Case if (orient[0] !== orient[1] && orient[2] !== orient[3]) { - return true; } // Special Cases if (orient[0] === 0 && onSegment(p1, p2, q1)) { // If p1, q1 and p2 are colinear and p2 lies on segment p1q1 - - return true; - } - - if (orient[1] === 0 && onSegment(p1, q2, q1)) { // If p1, q1 and p2 are colinear and q2 lies on segment p1q1 - - return true; + result = true; + } else if (orient[1] === 0 && onSegment(p1, q2, q1)) { // If p1, q1 and p2 are colinear and q2 lies on segment p1q1 + result = true; + } else if (orient[2] === 0 && onSegment(p2, p1, q2)) { // If p2, q2 and p1 are colinear and p1 lies on segment p2q2 + result = true; + } else if (orient[3] === 0 && onSegment(p2, q1, q2)) { // If p2, q2 and q1 are colinear and q1 lies on segment p2q2 + result = true; } - if (orient[2] === 0 && onSegment(p2, p1, q2)) { // If p2, q2 and p1 are colinear and p1 lies on segment p2q2 - - return true; - } - - if (orient[3] === 0 && onSegment(p2, q1, q2)) { // If p2, q2 and q1 are colinear and q1 lies on segment p2q2 - - return true; - } + return result; +} - return false; +function getCoords (dataHandle) { + return { + x: dataHandle.x, + y: dataHandle.y + }; } function orientation (p, q, r) { diff --git a/src/util/pointInFreehandROI.js b/src/util/pointInFreehandROI.js index 40d28e91b..a2fc67a0d 100644 --- a/src/util/pointInFreehandROI.js +++ b/src/util/pointInFreehandROI.js @@ -1,7 +1,3 @@ -// JPETTS - Calculates if "point" is inside the polygon defined by dataHandles by -// Counting the number of times a ray originating from "point" crosses the -// Edges of the polygon. Odd === inside, Even === outside. - function isEnclosedY (yp, y1, y2) { if ((y1 < yp && yp < y2) || (y2 < yp && yp < y1)) { return true; @@ -44,6 +40,10 @@ function lineSegmentAtPoint (point, lp1, lp2) { } export default function (dataHandles, location) { + // JPETTS - Calculates if "point" is inside the polygon defined by dataHandles by + // Counting the number of times a ray originating from "point" crosses the + // Edges of the polygon. Odd === inside, Even === outside. + // The bool "inROI" flips every time ray originating from location and // Pointing to the right crosses a linesegment. let inROI = false;