How to add fontawasome icon as a layer in geotools using javafx (Desktop App)? - javafx

I have been using java 17 and I'm unable to add icons into the map as a layer. please help me.
void drawTarget(double x, double y) {
SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder();
builder.setName("MyFeatureType");
builder.setCRS( DefaultGeographicCRS.WGS84 ); // set crs
builder.add("location", LineString.class); // add geometry
// build the type
SimpleFeatureType TYPE = builder.buildFeatureType();
// create features using the type defined
SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(TYPE);
// GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory();
// Coordinate[] coords =
// new Coordinate[] {new Coordinate(79,25.00), new Coordinate(x, y)};
// line = geometryFactory.createLineString(coords);
// ln = new javafx.scene.shape.Line();
FontAwesomeIcon faico = new FontAwesomeIcon();
faico.setIconName("FIGHTER_JET");
faico.setX(76);
faico.setY(25);
faico.setVisible(true);
// TranslateTransition trans = new TranslateTransition();
// trans.setNode(faico);
featureBuilder.add(faico);
SimpleFeature feature = featureBuilder.buildFeature("FeaturePoint");
DefaultFeatureCollection featureCollection = new DefaultFeatureCollection("external", TYPE);
featureCollection.add(feature); // Add feature 1, 2, 3, etc
Style style5 = SLD.createLineStyle(Color.YELLOW, 2f);
Layer layer5 = new FeatureLayer(featureCollection, style5);
map.addLayer(layer5);
// mapFrame.getMapPane().repaint();
}
I want to add a font-awesome icon to the map

Currently, your code is attempting to use an Icon as a Geometry in your feature. I'm guessing that's what isn't working since you don't say.
If you want to use an Icon to display the location of a Feature then you will need two things.
A valid geometry in your feature, probably a point (since an Icon is normally a point)
A valid Style to be used by the Renderer to draw your feature(s) on the map. Currently, you are asking for the line in your feature to be drawn using a yellow line (style5 = SLD.createLineStyle(Color.YELLOW, 2f);)
I can't really help with step 1, since I don't know where your fighter jet currently is.
For step 2 I suggest you look at the SLD resources to give you some clues of how the styling system works before going on the manual to see how GeoTools implements that.
Since you are trying to add an Icon I suggest you'd need something like:
List<GraphicalSymbol> symbols = new ArrayList<>();
symbols.add(sf.externalGraphic(svg, "svg", null)); // svg preferred
symbols.add(sf.externalGraphic(png, "png", null)); // png preferred
symbols.add(sf.mark(ff.literal("circle"), fill, stroke)); // simple circle backup plan
Expression opacity = null; // use default
Expression size = ff.literal(10);
Expression rotation = null; // use default
AnchorPoint anchor = null; // use default
Displacement displacement = null; // use default
// define a point symbolizer of a small circle
Graphic city = sf.graphic(symbols, opacity, size, rotation, anchor, displacement);
PointSymbolizer pointSymbolizer =
sf.pointSymbolizer("point", ff.property("the_geom"), null, null, city);
rule1.symbolizers().add(pointSymbolizer);
featureTypeStyle.rules().add(rule1);
But that assumes that you can convert your FontAwesomeIcon into a static representation that the renderer can draw (png, svg). If it doesn't work like that (I don't use JavaFX) then you may need to add a new MarkFactory to handle them.

Related

How can I merge geometries in A-Frame without losing material information?

I have a large set of block objects using a custom geometry, that I am hoping to merge into a smaller number of larger geometries, as I believe this will reduce rendering costs.
I have been following guidance here: https://aframe.io/docs/1.2.0/introduction/best-practices.html#performance which has led me to the geometry-merger component here:
https://github.com/supermedium/superframe/tree/master/components/geometry-merger/
The A-Frame docs say:
"You can use geometry-merger and then make use a three.js material with vertex colors enabled. three.js geometries keep data such as color, uvs per vertex."
The geometry-merger component also says:
"Useful if using vertex or face coloring as individual geometries' colors can still be manipulated individually since this component keeps a faceIndex and vertexIndex."
However I have a couple of problems.
If I set vertexColors on my material (as suggested by the A-Frame docs), then this ruins the appearance of my blocks.
Whether or not I set vertexColors on my material, all material information seems to be lost when the geometries are merged, and everything just ends up white.
See this glitch for a demonstration of both problems.
https://tundra-mercurial-garden.glitch.me/
My suspicion is that the A-Frame geometry-merger component just won't do what I need here, and I need to implement something myself using the underlying three.js functions.
Is that right, or is there a way that I could make this work using geometry-merger?
For the vertexColors to work, you need to have your vertices coloured :)
More specifically - the BufferGeometry expects an array of rgb values for each vertex - which will be used as color for the material.
In this bit of code:
var geometry = new THREE.BoxGeometry();
var mat = new THREE.MeshStandardMaterial({color: 0xffffff, vertexColors: THREE.FaceColors});
var mesh = new THREE.Mesh(geometry, mat);
The mesh will be be black unless the geometry contains information about the vertex colors:
// create a color attribute in the geometry
geometry.setAttribute('color', new THREE.BufferAttribute(new Float32Array(vertices_count), 3));
// grab the array
const colors = this.geometry.attributes.color.array;
// fill the array with rgb values
const faceColor = new THREE.Color(color_hex);
for (var i = 0; i < vertices_count / 3; i += 3) {
colors[i + 0] = faceColor.r; // lol +0
colors[i + 1] = faceColor.g;
colors[i + 2] = faceColor.b;
}
// tell the geometry to update the color attribute
geometry.attributes.color.needsUpdate = true;
I can't make the buffer-geometry-merger component work for some reason, but It's core seems to be valid:
AFRAME.registerComponent("merger", {
init: function() {
// replace with an event where all child entities are ready
setTimeout(this.mergeChildren.bind(this), 500);
},
mergeChildren: function() {
const geometries = [];
// traverse the child and store all geometries.
this.el.object3D.traverse(node => {
if (node.type === "Mesh") {
const geometry = node.geometry.clone();
geometry.applyMatrix4(node.parent.matrix);
geometries.push(geometry)
// dispose the merged meshes
node.parent.remove(node);
node.geometry.dispose();
node.material.dispose();
}
});
// create a mesh from the "merged" geometry
const mergedGeo = THREE.BufferGeometryUtils.mergeBufferGeometries(geometries);
const mergedMaterial = new THREE.MeshStandardMaterial({color: 0xffffff, roughness: 0.3, vertexColors: THREE.FaceColors});
const mergedMesh = new THREE.Mesh(mergedGeo, mergedMaterial);
this.el.object3D.add(mergedMesh)
}
})
You can check it out in this glitch. There is also an example on using the vertex colors here (source).
I agree it sounds like you need to consider other solutions. Here are two different instances of instancing with A-Frame:
https://github.com/takahirox/aframe-instancing
https://github.com/EX3D/aframe-InstancedMesh
Neither are perfect or even fully finished, but can hopefully get you started as a guide.
Although my original question was about geometry merging, I now believe that Instanced Meshes were a better solution in this case.
Based on this suggestion I implemented this new A-Frame Component:
https://github.com/diarmidmackenzie/instanced-mesh
This glitch shows the scene from the original glitch being rendered with just 19 calls using this component. That compares pretty well with > 200 calls that would have been required if every object were rendered individually.
https://dull-stump-psychology.glitch.me/
A key limitation is that I was not able to use a single mesh for all the different block colors, but had to use one mesh per color (7 meshes total).
InstancedMesh can support different colored elements, but each element must have a single color, whereas the elements in this scene had 2 colors each (black frame + face color).

Use videoTexture as opacityTexture

How do I use video (mp4) as alpha map in babylonJS?
In three.js applying a video as texture is as simple as assigning the video texture to alphaMap (instead of the diffuse map).
Here's the expected result in three.js - Demo.
I attempted to do the same in babylonJS to no avail. Here's what I have so far babylonJs demo
var mat = new BABYLON.StandardMaterial("mat", scene);
var videoTexture = new BABYLON.VideoTexture("video", ["textures/babylonjs.mp4", "textures/babylonjs.webm"], scene, true, true);
mat.opacityTexture = videoTexture;
Any ideas are welcome.
Thanks
You can use videoTexture.getAlphaFromRGB = true; to use all three channels combined for the alpha. By default it only uses the red channel, which does not have enough variance in the source video for it to show.
The complete example:
var mat = new BABYLON.StandardMaterial("mat", scene);
var videoTexture = new BABYLON.VideoTexture("video", ["textures/babylonjs.mp4", "textures/babylonjs.webm"], scene, true, true);
videoTexture.getAlphaFromRGB = true;
mat.opacityTexture = videoTexture;

How can I generate a mask on a solid or create a custom (complex) drawing on that solid to Adobe After Effects only via scripting

I'm making an After Effects script that generates simple shapes & animations for kids, and I'm trying to avoid importing vector shapes from Illustrator to After Effects to animate them. And that is working perfectly with simple shapes such as squares and circles.
Is there any solution for generating complex shapes inside the Extendscript Toolkit, a pure code with no imports or locating some .txt file, just by setting the vertices, position and color of the shape and applies it to a new solid as a mask by running the script inside of After Effects?
If I wanted to do it manually, I will add a new solid, copy the first path from Illustrator, and back to after effects to paste it on that solid,then I'll add another solid, back to illustrator, copy another path, back to after effect, paste it on solid 2, and I'll repeat the process till the final result appears.
I want to end this switching between software 1 and 2 and save the drawing as an array of [vertices], [in-tangents], and [out-tangents] and call it whenever I want!
Running the script
The Result
I've done it like this, it can be used for import any kind of footage
var path = "File Path";
var input = new ImportOptinputns(File(path));
if (input.canImportAs(ImportAsType.FOOTAGE));
input.importAs = ImportAsType.FOOTAGE;
Or if you want to import an image sequence you can do it like this
// or if your footage is an image sequence
input.sequence = true;
input.forceAlphabetical = true;
imageSequence = app.project.importFile(input);
imageSequence.name = 'My automatically imported foorage";
theComp = app.project.activeItem; //import in to currently selected composition
theComp.layers.add(imageSequence);
I know how to create simple vector objects via script but I'm not sure if its work for you as you want it.
An example of two group rectangle
var shapeLayer = newComp.layers.addShape(); // adding shape layer
shapeLayer.name = "bannerLayer"; // name the shape layer
var shapeGroup1 = shapeLayer.property("Contents").addProperty("ADBE Vector Group"); / creating a group1
shapeGroup1.name = "Banner"; //name the group1
myRect= shapeGroup1.property("Contents").addProperty("ADBE Vector Shape - Rect"); // adding rectangle to the group1
Another example of a more complex shape, a triangle add to an existing shape layer, you can use this code as a base and create more complex shapes.
var shapeLayer = newComp.layers.addShape(); // adding shape layer
shapeLayer.name = "bannerLayer"; // name the shape layer
var shapeGroup1 = shapeLayer.property("Contents").addProperty("ADBE Vector Group"); // creating a group1
shapeGroup1.name = "Banner"; //name the group1
myRect = shapeGroup1.property("Contents").addProperty("ADBE Vector Shape - Rect"); // adding rectangle to the group1
// construct a Shape object that forms a triangle
var myTriShape = new Shape();
myTriShape.vertices = [[-50,50], [50,50], [0,100]];
myTriShape.closed = true;
// add a Path group to our existing shape layer
myTriGroup = shapeLayer.property("Contents").addProperty("ADBE Vector Group"); // adding rectangle to the group1
myTriGroup.name = "Triangle";
myTri = myTriGroup.property("Contents").addProperty("ADBE Vector Shape - Group");
// set the Path property in the group to our triangle shape
myTri.property("Path").setValue(myTriShape);
you can find more information on this page. I googled it myself.
Check this link https://forums.creativecow.net/docs/forums/post.php?forumid=2&postid=1119306&univpostid=1119306&pview=t

three js mirror not reflecting all meshes

Objective:
To simulate a reflective floor(like this) in three js.
Idea:
Make the floor translucent by setting opacity to 0.5.
Place a Mirror below it to reflect the meshes above it.
Expected Output:
To be able to see reflections of the house via the floor mirror.
Obtained Output:
Doesn't reflect the meshes which is part of the house.
Instead, reflects only the skybox and that too only in certain angles.
Screenshots:
Mirror reflecting skybox fully - http://prntscr.com/6yn52y
Mirror reflecting skybox partially - http://prntscr.com/6yn5f7
Mirror not reflecting anything - http://prntscr.com/6yn5qy
Questions:
Why aren't the other meshes of the house reflected through the mirror?
Why is the mirror not reflecting in certain orientations of the camera?
Code Attached:
.......
.......
function getReflectiveFloorMesh(floorMesh) {
var WIDTH = window.innerWidth;
var HEIGHT = window.innerHeight;
floorMirror = new THREE.Mirror( renderer, firstPerson.camera,
{ clipBias: 0.003,
textureWidth: WIDTH,
textureHeight: HEIGHT,
color: 0x889999 } );
var mirrorMesh = floorMesh.clone();
mirrorMesh.position.y -= 10; // Placing the mirror just below the actual translucent floor; Fixme: To be tuned
mirrorMesh.material = floorMirror.material;
mirrorMesh.material.side = THREE.BackSide; // Fixme: Normals were flipped. How to decide on normals?
mirrorMesh.material.needsUpdate = true;
mirrorMesh.add(floorMirror);
return mirrorMesh;
}
function getSkybox() {
var urlPrefix = "/img/skybox/sunset/";
var urls = [urlPrefix + "px.png", urlPrefix + "nx.png",
urlPrefix + "py.png", urlPrefix + "ny.png",
urlPrefix + "pz.png", urlPrefix + "nz.png"];
var textureCube = THREE.ImageUtils.loadTextureCube(urls);
// init the cube shadder
var shader = THREE.ShaderLib["cube"];
shader.uniforms["tCube"].value = textureCube;
var material = new THREE.ShaderMaterial({
fragmentShader: shader.fragmentShader,
vertexShader: shader.vertexShader,
uniforms: shader.uniforms,
side: THREE.BackSide
});
// build the skybox Mesh
var skyboxMesh = new THREE.Mesh(new THREE.CubeGeometry(10000, 10000, 10000, 1, 1, 1, null, true), material);
return skyboxMesh;
}
function setupScene(model, floor) {
scene.add(model); // Adding the house which contains translucent floor
scene.add(getSkybox()); // Adding Skybox
scene.add(getReflectiveFloorMesh(floor)); // Adds mirror just below floor
scope.animate();
}
....
....
this.animate = function () {
// Render the mirrors
if(floorMirror)
floorMirror.render();
renderer.render(scene, firstPerson.camera);
};
You have to attach the mirror to the mesh before doing any transformation.
So the code would be:
floorMirror = new THREE.Mirror( ... );
var mirrorMesh = floorMesh.clone();
mirrorMesh.add(floorMirror); // attach first!
mirrorMesh.position.y -= 10;
...
But another problem here is that you are cloning mirrorMesh from floorMesh, which has already been (probably) transformed.
At creation, a mirror object has the same default transform matrix as a regular Mesh with plane geometry (which is by default 'vertical').
When you attach the mirror to a floor (or any horizontal mesh), the matrix doesn't match with the mesh one and that's why you don't see the reflections, or only from a certain angle.
So, always attach a mirror to a non-transformed plane mesh, before you apply your transformations (translations or rotations).
Idea:
"Make the floor translucent by setting opacity to 0.5.
Place a Mirror below it to reflect the meshes above it".
I suggest another way, make floor as solid add mirror on top and change the alpha of the mirror instead, I think you have issues with the translucent floor restricting the mirror projection through the alpha..
If you move the mirror over from under the translucent floor or into an empty scene with just a cube or sphere geometry attached basic material does it reflect as expected?
You may need 2 mirrors, one for the room assuming you want polished floor boards and one for outside general reflection

Mystery coordinate offset on getCharBoundaries

I've ran into a weird problem with getCharBoundaries, I could not figure out what coordinate space the coordinates returned from the function was in. What ever I tried I could not get it to match up with what I expected.
So I made a new project and and added simple code to highlight the last charater in a textfield, and all of a sudden it worked fine. I then tried to copy over the TextField that had been causing me problems, into the new project. And now the same weird offset appeared 50px on the x axis. Everything else was spot on.
So after some headscracthing comparing the two TextFields, I simply can not see a difference in their properties or transformation.
So I was hoping that someone might now what property might affect the coordinates returned by getCharBoundaries.
I am using Flash CS4.
I've just had exactly the same problem and thought I'd help out by offering what my findings are. With a help from this thread, I tried to find everything that wasn't 'default' about the textfield I was using. I found that when I had switched my TextFormatAlign (or 'align' in the IDE) and TextFieldAutoSize properties to 'LEFT' as opposed to 'CENTER', it solved the problem.
A little late in the game perhaps, but worth knowing for anyone running into the same problem. This was the only thread I could find that raised the right flag...
Well the getCharBoundaries returns the boundaries in the textfield coordinate system. Where the origin is topleft corner of the textfield.
getCharBoundaries does not take into consideration the scrolling. you need to check if there are scrollbars on its parent (textarea) and if so relocate. One quick way of doing it is using localtoglobal and globaltolocal. Use the first to translate from the textfield coordinate system to the application coordinate system and then use the second to translate from the app coordinate system to the coordinate system of the parent of the textfield which is the textarea. I'm fine tuning a my method to get char boundaries i will publish it today on my blog
http://flexbuzz.blogspot.com/
Works For Me(tm) (Flex Builder AS3 project):
[Embed(systemFont="Segoe UI", fontWeight="bold", fontName="emb",
mimeType="application/x-font")]
private var EmbeddedFont:Class;
public function ScratchAs3()
{
stage.scaleMode = 'noScale';
stage.align = 'tl';
var m:Matrix = new Matrix(.8, .1, -.1, 1.1, 26, 78);
var t:TextField = new TextField();
t.autoSize = 'left';
t.wordWrap = false;
t.embedFonts = true;
t.defaultTextFormat = new TextFormat("emb", 100, 0, true);
t.transform.matrix = m;
t.text = "TEST STRING.";
addChild(t);
var r:Rectangle = t.getCharBoundaries(8);
var tl:Point = m.transformPoint(r.topLeft);
var tr:Point = m.transformPoint(new Point(r.right, r.top));
var bl:Point = m.transformPoint(new Point(r.left, r.bottom));
var br:Point = m.transformPoint(r.bottomRight);
graphics.beginFill(0xFF, .6);
graphics.moveTo(tl.x, tl.y);
graphics.lineTo(tr.x, tr.y);
graphics.lineTo(br.x, br.y);
graphics.lineTo(bl.x, bl.y);
graphics.lineTo(tl.x, tl.y);
}
To literally answer your question, it returns the coordinates in the TextField's coordinate system, not it's parent, and it is affected by DisplayObject.transform.matrix, which is the backing for the .x, .y, .scaleX, .scaleY, .width, .height, and .rotation properties.
What ever it was the solution was simple to add a new TextField, never found out what property screwed everything up.
The first answer is correct in most cases. However if your field is parented to another movie clip it may still return the wrong y coordinate. try this code:
//if this doesn't work:
myTextFormat = new TextFormat();
myTextFormat.align = TextFormatAlign.LEFT;
myFieldsParent.myField.autoSize = TextFieldAutoSize.LEFT;
myFieldsParent.myField.setTextFormat( myTextFormat);
//try this:
var x = myFieldsParent.myField.getCharBoundaries(o).x;
var y = myFieldsParent.myField.getCharBoundaries(o).y;
var myPoint:Point = new Point(myField.getCharBoundaries(o).x,myField.getCharBoundaries(o).y);
var pt:Point = new Point(myFieldsParent.myField.getCharBoundaries(o).x, myFieldsParent.myField.getCharBoundaries(o).y);
pt = myFieldsParent.myField.localToGlobal(pt);
//pt is the variable containing the coordinates of the char in the stage's coordinate space. You may still need to offset it with a fixed value but it should be constant.
I didn't test this code as I have adapted this example from code that is embedded into my project so I apologize if I'm missing something...

Resources