Giter Site home page Giter Site logo

hello-world's People

Contributors

agviegas avatar aka-blackboots avatar arunkvijay avatar craigliesinger avatar danielsboba avatar hassanemam avatar jmcouffin avatar johltn avatar jsanchez4 avatar lukasschmid97 avatar myoualid avatar nithin-cuezap avatar ryugaryuzaki avatar seantai avatar sebastianoscarlopez avatar shalwaban avatar txtony avatar vishwajeet-hloov avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

hello-world's Issues

New bounty: Mix photogrametric, point clouds and IFC data in the viewer πŸš€

πŸ“‹ GENERAL:


βš” CHALLENGE:

Make a tutorial on multi-format converter/loader

  1. Load files, either from preloaded and converted files on server or from user device, with different formats :
  • IFC data,
  • Point clouds,
  • Photogrametric data
    Process: List preloaded files, add a switch for each file to add or retreive from viewer scene or add with user files as usual
    Expexted results: All active models are loaded in the viewer
  1. Adjust relative localisation
    Add a button to adjust the position of each model relatively one to others:
    Process: select a model in viewer, define a base point on it, then define a target point on one of other loaded models
    Expected result: Model moves to the target point

  2. demonstrate clipping plans
    Add a button to add clipping plan by selecting a model face
    Add a switch button to switch visibility of clipping vector and plans

  3. demonstrate 2D projections and exports (PDF/DXF)
    Add a button to project 2D line drawing by selecting a face or a clipping plan
    Add a button+shortcut to export PDF of 2D edge projection
    Add a button+shortcut to export DXF of 2D edge projection

Inspiration links :


πŸ‘©β€βš–οΈ REQUIREMENTS:

  • A list of requirements for this bounty to be considered successful :

    • Supported formats (to be announced at least PCD, IFC)
  • If someone completes a part of the bounty, a part of the money is given and a new bounty is created.


πŸ”₯ STARTING MATERIAL:

Links, documentation and references that you think will help to complete the task.

B#67: 3D navigation cube

β˜€ Info

πŸ“œ Notes

βš” CHALLENGE:

We need a 3D navigation cube to easily control the camera in 3D. We need an example using that cube and web-ifc-three in the following repository:


πŸ‘©β€βš–οΈ REQUIREMENTS:

B#67: 3D navigation cube

β˜€ Info

πŸ“œ Notes

βš” CHALLENGE:

We need a 3D navigation cube to easily control the camera in 3D. We need an example using that cube and web-ifc-three in the following repository:


πŸ‘©β€βš–οΈ REQUIREMENTS:

New bounty: Batch Load IFC Files πŸš€

πŸ“‹ GENERAL:


βš” CHALLENGE:

To enable more dynamic workflows in IFC and future versions of IFC we are exploring a "By Element" approach to IFC data. This means storing individual IFC files per element. To utilize this data it necessary to be able to load many files at once vs one at a time. This request is to enable the selection of one or more IFC files and have them load via a single threaded or if possible a multi-threaded process.

image

The sample data can be found here.

-https://github.com/magnetar-io/ByElementIFC_Data/tree/main/Basic%20Sample%20Architecture%202


πŸ‘©β€βš–οΈ REQUIREMENTS:

  • Extend the Existing File Loader to allow the selection and loading of one or more files simultaneously
  • Explore the possibility to multi-thread this process
  • Bonus capabilities would allow to filter selected files prior to loading by; Name, Size, Modified Date

πŸ”₯ STARTING MATERIAL:

Sample Files; -https://github.com/magnetar-io/ByElementIFC_Data/tree/main/Basic%20Sample%20Architecture%202

Nice Ambient Occlusion

πŸ“‹ GENERAL:


βš” CHALLENGE:

Autodesk Forge has a very nice ambient occlusion that gives it a cool look. You can check it out here:

As far as we know, Forge is built Three.js (around version 70), so we are convinced that it is possible to achieve that effect, especially considering all the advances Three.js has made since then.


πŸ‘©β€βš–οΈ REQUIREMENTS:

  • Similar look to Forge viewer.

  • Decent performance (don't go below 30 fps with medium-size IFC models in a laptop).


πŸ”₯ STARTING MATERIAL:

You can use the hello world repository, which has a simple example of IFC.js that you can use as starting point:

Here you have some IFC files to test:

In addition to that, there are multiple types of ambient occlusion examples published in official Three.js resources:

TypeError

Hey agviegas thankyou for creating such a great tutorial for the IFC.js-three.js beginners.

Yesterday I attempted using the hello-world tutorial to build my first ifc viewer and did so by using the hello-world html and app.js. I then downloaded the web-ifc.wasm file and bundled the projekt using webpack. After opening the site the 3d scene appears, but the scene is unable to add the ifc model. I recompiled multiple times and switched between local and external ifc files and when the ifc files are attempted to be loaded (by app.js) I always receive the error:
TypeError: Cannot read property 'rawConstructor' of undefined
at pe (bundle_3d_viewer.js:2)
at web-ifc.wasm:0x45b2d
at X (web-ifc.wasm:0x301c2)
at r.___wasm_call_ctors (bundle_3d_viewer.js:2)
at func (bundle_3d_viewer.js:2)
at _t (bundle_3d_viewer.js:2)
at pt (bundle_3d_viewer.js:2)
at s (bundle_3d_viewer.js:2)
at Ui (bundle_3d_viewer.js:2)
at t (bundle_3d_viewer.js:2)
(anonymous) @ bundle_3d_viewer.js:2
async function (async)
(anonymous) @ bundle_3d_viewer.js:2
(anonymous) @ bundle_3d_viewer.js:2
load (async)
load @ bundle_3d_viewer.js:2
load @ bundle_3d_viewer.js:2
(anonymous) @ bundle_3d_viewer.js:2

Screenshot 2021-07-06 110643

my app.js that I used for bundling and the corresponding webpack.config.js is also added below to give more context.

app.js

import {
  AmbientLight,
  AxesHelper,
  Color,
  DirectionalLight,
  GridHelper,
  PerspectiveCamera,
  Scene,
  Vector3,
  WebGLRenderer,
} from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import { IFCLoader } from "three/examples/jsm/loaders/IFCLoader";

//Creates the Three.js scene
const scene = new Scene();

//Object to store the size of the viewport
const size = {
  width: window.innerWidth,
  height: window.innerHeight,
};

//Creates the camera (point of view of the user)
const camera = new PerspectiveCamera(75, size.width / size.height);
camera.position.z = 15;
camera.position.y = 13;
camera.position.x = 8;

//Creates the lights of the scene
const lightColor = 0xffffff;

const ambientLight = new AmbientLight(lightColor, 0.5);
scene.add(ambientLight);

const directionalLight = new DirectionalLight(lightColor, 1);
directionalLight.position.set(0, 10, 0);
directionalLight.target.position.set(-5, 0, 0);
scene.add(directionalLight);
scene.add(directionalLight.target);

//Sets up the renderer, fetching the canvas of the HTML
const threeCanvas = document.getElementById("three-canvas");
const renderer = new WebGLRenderer({ canvas: threeCanvas, alpha: true });
renderer.setSize(size.width, size.height);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));

//Creates grids and axes in the scene
const grid = new GridHelper(50, 30);
scene.add(grid);

const axes = new AxesHelper();
axes.material.depthTest = false;
axes.renderOrder = 1;
scene.add(axes);

//Creates the orbit controls (to navigate the scene)
const controls = new OrbitControls(camera, threeCanvas);
controls.enableDamping = true;
controls.target.set(-2, 0, 0);

//Animation loop
const animate = () => {
  controls.update();
  renderer.render(scene, camera);
  requestAnimationFrame(animate);
};

animate();

//Adjust the viewport to the size of the browser
window.addEventListener("resize", () => {
  (size.width = window.innerWidth), (size.height = window.innerHeight);
  camera.aspect = size.width / size.height;
  camera.updateProjectionMatrix();
  renderer.setSize(size.width, size.height);
});

//Sets up the IFC loading

function loadIFC(){}
const ifcLoader = new IFCLoader();
ifcLoader.setWasmPath("../");
const url = "https://raw.githubusercontent.com/IFCjs/test-ifc-files/main/Revit/TESTED_Simple_project_01.ifc";

window.addEventListener('DOMContentLoaded', (event) => {
  ifcLoader.load(url, (geometry) => scene.add(geometry));
});

webpack.config.js

const path = require('path');
module.exports = {
    entry: "./src/public/js/app.js",
    output: {
        filename: 'bundle_3d_viewer.js',
        path: path.join(__dirname,"/src/public/dist")
    },

    devServer: {
        contentBase: path.join(__dirname,'/src/public'),
        port:9000
    }
};

Here is the viewer.html, which is essentially the same as the tutorial, but with different paths.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="../css/platform.css" />
    <title>Document</title>
  </head>
  <body>
    <input type="file" name="load" id="file-input" />
    <canvas id="three-canvas"></canvas>
    <script src="../dist/bundle_3d_viewer.js"></script>
  </body>
</html>

I suspect it is an issue with the wasm file, but it could also be the app.js itself or my bundelling technique.

Do you have an idea how I could fix it?

B#67: 3D navigation cube

β˜€ Info

πŸ“œ Notes

βš” CHALLENGE:

We need a 3D navigation cube to easily control the camera in 3D. We need an example using that cube and web-ifc-three in the following repository:


πŸ‘©β€βš–οΈ REQUIREMENTS:

HBJSON exporter

πŸ“‹ GENERAL:


βš” CHALLENGE:

One of the most powerful use cases for BIM is building energy analysis. Luckily, there are brilliant people who are already implementing this problem; we are referring to the people at Ladybug Tools.

One of their free libraries for energy analysis is Honeybee, which uses their own open HBJSON format. The goal of this task is to extract all the necessary data from an IFC and create an HBJSON file that HoneyBee can read correctly.

We are aware that many IFCs do not have the necessary information for their energy analysis, and the aim of this task is not to generate that information. We are going to provide an IFC that does have that data, so you can concentrate on simply extracting it to generate the JSON.

Quoting Mostapha Sadeghipour (Ladybug tools):
The way a simulation model should be prepared depends on the type of the simulation. A model can be built face-by-face or it can be built room-by-room. The first one is great for daylight simulation. The second one is what is needed for energy simulation. In the IFC world IFCSpaces are supposed to those rooms that should be used for energy simulation but it is not as easy. Here you have a related discussion in OSArch:

Regarding HBJSON, and quoting Mostapha again: The schema is open source and documented here: https://www.ladybug.tools/honeybee-schema/model.html#tag/model_model - Model is the object that describes the whole building.: You can think about it as a mini-IFC fo

We use OpenAPI toolkit to generate different SDKs. We use Python and C# actively. We have never used the JS one but this project might be the right place to use it. Once we generate a valid HBJSON file the rest of the process is taken care of with our translators. Most of our translators are written in Python but since we use the HBJSON file in the middle as the transition layer it doesn't really matter what language you want to use to generate the HBJSON file.


πŸ‘©β€βš–οΈ REQUIREMENTS:

  • Generate a file that HoneyBee can read.

πŸ”₯ STARTING MATERIAL:

You can use the hello world repository, which has a simple example of IFC.js that you can use as starting point:

Here you have an IFC files with the necesary information to make energy analysis:

Here you have the HBJSON specification:

Finally, here you have some HBJSON examples:

IFCjs viewer for VR/AR πŸš€

Hi,
I would like to be able to allow people to view my IFC files in VR -- with Oculus goggles for example.
Please have a look at the course at Udemy https://www.udemy.com/course/intro-webxr/
and some information for developers at:
https://developer.oculus.com/manage/organizations/create/

All I expect is:

  1. immersive navigating capabilities (the 6 degrees of freedom in VR) like in the examples of the Udemy course and
  2. to be able to 'click' on the IFCjs files with the Oculus' controllers -- in VR.
    Whatever you develop here will be par of this open source platform IFC.js -- thank you!

Please let me know if you can include some AR capabilities in the project.
Kind regards, Marcos


Checking / validating IFC properties and values

A follow-up to the conversation in the Discord Channel (user name: Arie);

At the start of a project, we define the requirements for the IFC models which parties have to create. During the project, it's very time consuming checking these models manually to see if the IFC models fits the requirements. It would be nice if this process can be more automated by automatically checking the properties of the objects in the IFC model.

For example:

  • Each object must contain a uniformat classification code;
  • Each object must contain a valid uniformat classification code in a specific format;
  • IfcWall must contain a property 'LoadBearing = true / false';

Also, we need to set custom requirements. For example;

  • IfcSlab with the material 'concrete' must contain property X with value Y.

Setting the requirements beforehand isn't the hardest part for me. But getting the right structure out of IFCjs to do the check, is the part I need help with.

Looking at the size of the IFC models (200-300mb) I think, as you suggested in the Discord Channel, JSON in combination with a NoSQL database (MongoDB) suits the best. Preprocessing the IFC models in the beginning so the querying (check the properties) is faster, fits the best for my situation I think.

For testing purposes, I have installed the local version of MongoDB.

Thanks for your help and your great product!

Problem with web-ifc node example

I tried updating and running this example. First problem is it points to an old test IFC file, IFC/7/Tungasletta10_R01.ifc, which is no longer there. I changed main.js to use the 01.ifc that is there but then get the following error:

pablo@top:~/ifcjs/hello-world/examples/web-ifc/ifc-to-json/node> node main.js
web-ifc: 0.0.34 threading: 0
TypeError: Cannot convert "undefined" to unsigned int
    at Object.toWireType (/Users/pablo/ifcjs/hello-world/node_modules/web-ifc/web-ifc-api-node.js:10184:21)
    at Object.GetLine (eval at new_ (/Users/pablo/ifcjs/hello-world/node_modules/web-ifc/web-ifc-api-node.js:9880:31), <anonymous>:8:26)
    at IfcAPI2.GetRawLineData (/Users/pablo/ifcjs/hello-world/node_modules/web-ifc/web-ifc-api-node.js:54841:28)
    at IfcAPI2.GetLine (/Users/pablo/ifcjs/hello-world/node_modules/web-ifc/web-ifc-api-node.js:54790:28)
    at saveProperties (/Users/pablo/ifcjs/hello-world/examples/web-ifc/ifc-to-json/node/main.js:42:26)
    at getAllItemsFromLines (/Users/pablo/ifcjs/hello-world/examples/web-ifc/ifc-to-json/node/main.js:33:13)
    at GetAllItems (/Users/pablo/ifcjs/hello-world/examples/web-ifc/ifc-to-json/node/main.js:26:5)
    at LoadFile (/Users/pablo/ifcjs/hello-world/examples/web-ifc/ifc-to-json/node/main.js:12:22)

Last commit to the repo:

> git log
commit 5d8f9fb7d613c13c912d288c9006b798bba7959a (HEAD -> main, origin/main, origin/HEAD)
Author: Antonio GonzΓ‘lez Viegas <[email protected]>
Date:   Wed Jun 22 00:39:02 2022 +0200

    Add psets to gltf import example

web-ifc-three/picking-properties and web-ifc-viewer/picking won't work with multiple models

When I add more than one model to the web-ifc-three/picking-properties example and when I try to select any element that doesn't belong to the first model it throws this error:

Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'type')
    at IfcAPI2.GetLine (bundle.js:75440:48)
    at WebIfcPropertyManager.getItemProperties (bundle.js:76763:27)
    at PropertyManager.getItemProperties (bundle.js:77775:30)
    at IFCManager.getItemProperties (bundle.js:79061:28)
    at pick (bundle.js:83427:33)

When doing the same with web-ifc-viewer/picking, it throws this error when the mouse is over any element:

Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'mesh')
    at ItemsMap.getGeometry (bundle.js:89496:49)
    at ItemsMap.generateGeometryIndexMap (bundle.js:89474:27)
    at SubsetCreator.createSubset (bundle.js:89606:18)
    at SubsetManager.createSubset (bundle.js:89751:31)
    at IFCManager.createSubset (bundle.js:92428:25)
    at IfcSelection.newSelection (bundle.js:92583:49)
    at IfcSelection.pick (bundle.js:92566:35)
    at async IfcSelector.prePickIfcItem (bundle.js:92667:9)

How should I fix these?

Floorplan projection

πŸ“‹ GENERAL:


βš” CHALLENGE:

The goal is to take an arbitrary 3d object in Three.js and generate the 2d projection of their occluded edges.

To understand what we want, take a look at the tables/chairs in the following image. Just focus on the chair + table, ignore the rest:

We want this to generate floor plans, so if you do it so that it projects the edges in an horizontal plane, it's more than enough.


πŸ‘©β€βš–οΈ REQUIREMENTS:

  • Generate an array of coplanar edges that represent the object from above.

  • The process shouldn't be slow. A small object (like the one provided below) should be processed in less than 1/2 seconds.


πŸ”₯ STARTING MATERIAL:

You can start with a standard three.js scene. Here you have the same chairs/tables of the images shown above:

And here you have some interesting resources that might serve you as a starting point:

If you have any questions, let us know!

B#67: 3D navigation cube

β˜€ Info

πŸ“œ Notes

βš” CHALLENGE:

We need a 3D navigation cube to easily control the camera in 3D. We need an example using that cube and web-ifc-three in the following repository:


πŸ‘©β€βš–οΈ REQUIREMENTS:

Testing the examples

Hi, i would love to try testing the examples that results in compiling the project using 'npm build'. I know this comes from my unknowledge regarding Node.js but shouldn't this output an HTML where I could test this packages? Thanks in advance.

RuntimeError in 'ifc-to-json' example

Hi,
when I start the node project 'ifc-to-json' I receive this error:
image

In the same way, if I serve the frontend project, when I try to create a json from the ifc file I can see the same error in console:
image

thanks

Nice Edges

πŸ“‹ GENERAL:


βš” CHALLENGE:

Autodesk Forge has a very nice edges that gives it a cool look. You can check it out here:

As far as we know, Forge is built Three.js (around version 70), so we are convinced that it is possible to achieve that effect, especially considering all the advances Three.js has made since then.

We have tried THREE.EdgesGeometry (https://threejs.org/docs/#api/en/geometries/EdgesGeometry), but it's not very performant in bigger models. A postproduction or shader approach is what we are looking for.


πŸ‘©β€βš–οΈ REQUIREMENTS:

  • Similar look to Forge viewer.

  • Decent performance (don't go below 30 fps with medium-size IFC models in a laptop).


πŸ”₯ STARTING MATERIAL:

You can use the hello world repository, which has a simple example of IFC.js that you can use as starting point:

Here you have some IFC files to test:

In addition to that, there are multiple related discussions in the three.js forum. For instance:

New bounty: VoxelClashes πŸš€

πŸ“‹ GENERAL:

  • Bounties page: https://bounties.ifcjs.io/
  • Required skills: (e.g. javascript, ifc.js, three.js).
  • Bounty: (the price of the bounty).

βš” CHALLENGE:

The objective is to extract data from an IFC file that can be used to create an adjacency graph, in which the vertices represent voxels. The voxels have a property clashes:[] that contains an array of the expressIDs of the building elements they intersect (clash) with.

There are two major steps in the process:

  • voxelization
  • clash detection between the voxels and the building elements. A clash is defined as building element is intersecting with the 3D space of the voxel.

The output contains, for each storey in a building, an array of voxels and the elements it clashes with. NOTE: we expect that many of the voxels clash with multiple elements.

Input

The input to the process is defined as follows

{
        // Where to get the file      
        url: 'file:///IFCSchependomlaan.ifc', 
        
        // Size of voxels in 3 dimensions, in mm
        voxelSize: [500,500,500],
                               
        // Which types to include in the clash detection 
        // If not present, include all
        // Prevails over excludes
        includes: [					   
        	'IFCWALL',						   
        	'IFCWINDOW',
        	'IFCSTAIRS',
        	'IFCDOOR'
        ],
        
        // Which types to exclude in the clash detection
        // If not present, do not exclude anything
        excludes: [                           
        	'IFCRAILING',
        	'IFCFURNISHINGELEMENT'
        ]

}

Output

The output that will allow the creation of the adjacency graph is the following

{ 
	   // meta contains the original input, and the processing time in ms
	   meta: {
	   		input: {},
	   		duration: 450
	   },
	   	   
	   // the storeys array contains , for each storey, an array of voxels
	   // with a clashes property that contains the expressIDs of the items
	   // it clashes with., and a coords:[] property in indicating the position in the voxel matrix. 
	   // Voxels that do not clash with anything do not need to be returned.

	   storeys: [
		{
			level: -1,
	 		name: 'basement',
			expressID: 120,
			voxels: [,
			 	{
			 		coords: [5,40,2],
			 		clashes: [
			 			42552,
			 			3662,
			 			267282,
			 			467383
			 		]
			 	},
			 	{
			 		coords: [5,40,3],
			 		clashes: [
			 			42552,
			 			267282
			 		]
			 	},
                                 ......
			]
                 },
		 .....
            ]
}

πŸ‘©β€βš–οΈ REQUIREMENTS:

  • A UI that allows a user to provide the input as described above (form)
  • A process that correctly voxelizes and detects clashes taking into account the input
  • Display of the generated output

πŸ”₯ STARTING MATERIAL:

Testfiles :

IFCSchependomlaan.ifc (multi storey)

Simple clash detector

πŸ“‹ GENERAL:


βš” CHALLENGE:

A very interesting use case for BIM is collision detection. There are many companies that sell solutions whose only purpose is this.

IFC.js is already able to create a simple example where it detects collision between objects of the user's choice using subsets. This should be easy thanks to Garrett Johnson's work with three-mesh-bvh:


πŸ‘©β€βš–οΈ REQUIREMENTS:

  • Create a simple clash detector that detects whether two subsets are colliding or not.

  • Get the IDs of the items that collide.

  • Filter clashes by intersection distance.


πŸ”₯ STARTING MATERIAL:

You can use the hello world repository, which has a simple example of IFC.js that you can use as starting point:

Here you have some IFC files to test:

Here you have some examples Garrett Johnson regarding collision in his three-mesh-bvh repository:

In addition to that, here you have the IFC.js subset tutorial to understand how they work:

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.