Calculating the surface area of a two-dimensional flat shape within a three-dimensional space using Javascript and Math

Is it possible to calculate the surface area of a 2D polygon with any shape, using a set of 3D vertices? For instance, what would be the surface area of the given figure?

var polygon = new Polygon([new Point(0,0,0), new Point(5,8,2), new Point(11,15,7)])
polygon.areaIfPolygonIs3D()
--> some expected result, regardless of the number of vertices in the polygon... 

Remember that polygons have only one surface. They are flat shapes that can be triangular, trapezoidal, irregular, and positioned at various angles in 3D space – almost like pieces of paper oriented in different ways.

I've attempted to flatten the polygon by rotating it, then applied a basic formula for calculating the area of an irregular 2D polygon which currently works in my code (formula: ). However, I faced challenges in aligning all vertices so the polygon lies flat (with all "z" values as 0) leading me to explore other options. If someone can assist in resolving this issue or offer guidance after spending a day relearning high school geometry concepts, it would be highly appreciated!

I have access to Points and Edges (created using point.to(point)), where Edges possess 'theta' (edge.theta()) and 'phi' (edge.phi()).

If anyone could provide insight on how to proceed here, following extensive effort to refresh my memory on geometry principles, it would be immensely helpful!

var locatorRho = function(x,y,z) {
  return Math.sqrt(x*x + y*y + z*z);
}

var locatorTheta = function(x,y) {
  return Math.atan2(y,x);
};

var locatorPhi = function(x,y,z) {
  return z == 0 ? Math.PI_2 : Math.acos(z/locatorRho(x, y, z));
}

// rotates a point based on another point ('locator'), along with their 2D angle ('theta') and 3D angle ('phi')
Point.prototype.rotateBy = function(locator, theta, phi) {
  phi = (phi == undefined ? 0 : phi);
  var relativeX = this.x() - locator.x();
  var relativeY = this.y() - locator.y();
  var relativeZ = this.z() - locator.z();
  var distance = locatorRho(relativeX, relativeY, relativeZ);
  var newTheta = locatorTheta(relativeX, relativeY) + theta;
  var newPhi = locatorPhi(relativeX, relativeY, relativeZ) + phi;
  this._x = locatorX(distance, newTheta, newPhi) + locator.x();
  this._y = locatorY(distance, newTheta, newPhi) + locator.y();
  this._z = locatorZ(distance, newPhi) + locator.z();
}

Polygon.prototype.signedArea = function() {
  var vertices = this.vertices();
  var area = 0;
  for(var i=0, j=1, length=vertices.length; i<length; ++i, j=(i+1)%length) {
    area += vertices[i].x()*vertices[j].y() - vertices[j].x()*vertices[i].y();
  }
  return 0.5*area
}

Polygon.prototype.areaIfPolygonIs2D = function() {
  return Math.abs(rotatedFlatCopy.signedArea())
}

Polygon.prototype.areaIfPolygonIs3D = function() {
    ... assistance needed here, feeling stuck ...
}

var vertices = [some number of Points, e.g., new Point(x,y,z)]
var polygon = new Polygon(vertices)
var polygon.areaIfPolygonIs3D()
--> desired outcome  

Answer №1

In the case where your polygon plane is not aligned parallel to the Z axis, one method to calculate the area projection involves using X and Y coordinates exclusively. First, you determine the projection area with this known approach and then divide the result by the cosine of the angle between the Z axis and the normal vector N to that particular plane.

 Area = Sum[x1*y2-x2*y1 +...]    ////shoelace formula
 True_Area =  Area / Cos(Angle between N and Z axis)) = 
              Area / DotProduct((N.x,N.y,N.z), (0,0,1)) = 
              Area / N.z 
               ////   if N is normalized (unit)

Answer №2

Applying the shoelace formula thrice, calculate the area using the coordinate points (X, Y), (Y, Z), and (Z, X). The total area can be determined by computing √Axy²+Ayz²+Azx² (assuming the polygon lies on a single plane).

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Decoding JSONP $http.jsonp() response within Angular.js

I am currently utilizing Angular's $http.jsonp() method to make a request, and it is returning JSON data encapsulated within a function: var url = "http://public-api.wordpress.com/rest/v1/sites/wtmpeachtest.wordpress.com/posts?callback=jsonp_callback ...

"Troubleshooting issue: Popup in react-leaflet fails to display upon clicking

Currently, I have integrated react-leaflet into my ReactJS application to dynamically create markers with popups. However, when implementing the code as shown below, the popup box fails to display and an error message appears in the web developer console. ...

Manipulating object children in React components

Currently, I am working on a simple web page to display information from a specific data structure. In my attempt to retrieve the object's children within the Component CountryInfo, I think I might be misusing the data property. However, I haven&apos ...

The error message "TypeError: Cannot set property 'href' of undefined" occurred at angular.js line 12520 when trying to set $window.location.href

Has anyone tried using a directive function to redirect when clicking with ng-click? Here is the HTML code: <a ng-click="navbarlinksCtrl.clickedfr()" ng-class="{active: clickedfr()}">FR</a><br> <a ng-click="navbarlinksCtrl.clickeden( ...

Search as you type and populate multiple HTML form fields simultaneously

Up until now, I have been copy-pasting my way through this project! I possess a customer database and an HTML form for data entry. Upon clicking submit, it generates a fillable PDF on the server. While typing a name, results are displayed, and upon selec ...

Reverse capture group combined with forward capture group

Does the title not just sum it up? I'm attempting to gather groups and merge them together. Here's the text in question: GPX 10.802.123/3843­ 1 -­ IDENTIFIER 48 And this is what I desire as output: IDENTIFIER 10.802.123/3843-48 So, just ...

What is the best way to eliminate elements from an array that do not match a certain

I am having trouble removing all elements that contain @b.com from an array. Even when I remove the !, the result is stil an empty array. This makes me think that I might be making a mistake somewhere. Could someone please help me understand where I' ...

Deciphering JavaScript script within a Node.js module

// =============================================================================== // Auth // =============================================================================== const admin = require('firebase-admin'); //what happens if i move th ...

Maximizing the potential of input with jQuery

Having trouble retrieving the value from an input and passing it through a script to sign up a user. The alert I have in place to test it is not showing any value. Here is the code I tried: <form id ="form-signin" class="form-sign ...

Update the sorting icon in the data grid using Material-UI

I'm looking for a way to replace the current icon in the Material UI data grid with a different one. Below is the code I'm using to implement the data grid component: https://i.sstatic.net/griFN.png import { DataGrid, DataGridProps, GridColDef,G ...

Steps for inserting new text in front of an element's existing text

Is there a way to insert text before the original content of an element? I know how to add text after using createTextNode, as shown in this example: $("#button").click(function() { $( ".text" ).append( document.createTextNode( " Hello" ) ); }); < ...

Numerous asynchronous requests running simultaneously

After successfully querying a database using js/ajax for a single drop-down, I am now looking to enhance my solution by adding multiple identical drop-downs. The goal is to retrieve the same information when an option is selected without allowing duplicate ...

When creating a form group within another form group, ensure that formGroup is passed a FormGroup instance

I have created a form for adding users, which includes fields to input their birthdate. this.userFG = this.formBuilder.group({ name: [""], family: [""], birthDate: this.formBuilder.group({ day: [""], month: [""], year: [""] }) }); Wh ...

Displaying and updating an array of values in the table's cells

I have been struggling with a simple discount calculation feature where the price should update when a user enters a value. No matter how many times I try, the array values are always printed in the first row line. The issue seems to be related to printing ...

I'm curious if there is a method in Vue.js that allows for creating a separator while utilizing v-for, much like the way `Array.join()` or FreeMarker's `<#sep>` functions operate

My goal is to create a list of <span> elements separated by commas using vue.js and v-for. Is there an easy way to achieve this in vue.js? In JavaScript, I would typically use users.join(", "). In FreeMarker templates, you can do some very interes ...

Load suggestions from Material UI AutoComplete dynamically based on user input

I am facing a challenge with an Autocomplete component that needs to handle a large data list, up to 6000 elements, and display suggestions based on user input. Due to the sheer number of options, when a user types on a slower computer, there is a noticeab ...

Automatically reload main page in Javascript upon closing child window (popup)

I am working with 3 php files: view.php, edit.php, and edit2.php. In view.php, I display the content of my database tables. edit.php is used to edit a specific row using textboxes, while edit2.php is responsible for updating changes in the database. Once ...

Measuring values from table data using jQuery

Facing an issue with a jQuery script that involves creating a simple counting loop for each tr. My table structure is as shown below, and I am attempting to select the second td, multiply it by two, add it to the third td, and display the result in the fou ...

If a different link is selected, remove the class from the ID, and vice versa

I've been working on solving a jQuery issue that involves manipulating classes in a parent container with two divs and links. The goal is to add a class to change the background when a link is clicked in one div, and remove it if the other link is cli ...

a callback may seem like it's not a function, but in reality, it is

This question might seem simple, but I'm struggling to grasp the concept of callbacks, especially in NodeJS. My issue arises when trying to retrieve data from MySQL, something that is usually straightforward in most programming languages: In my rout ...