Depth Stencil and Shadow resource empty - directx-10

After Spending about 3 days trying to get shadow mapping to work I'm having some trouble getting the shadow mapped passed in to the shaders.
First I initialize the depth stencil and the resource view, then i draw ( I believe ) to the depth stencil. The problem that I am finding is that the depth stencil never has any data associated with it.
Pix shows no data in the resource view or the depth stencil, I am unable to save an image of the depth stencil to a file (I am from the non shadow depth stencil ). I am able to call DrawSceneShadow() and render it to the rendertarget and get what I want.
Any help is appreciated thank you.
Initialize
// Create depth stencil texture
D3D10_TEXTURE2D_DESC descDepth;
descDepth.Width = width;
descDepth.Height = height;
descDepth.MipLevels = 1;
descDepth.ArraySize = 1;
descDepth.Format = DXGI_FORMAT_R32_TYPELESS;
descDepth.SampleDesc.Count = 1;
descDepth.SampleDesc.Quality = 0;
descDepth.Usage = D3D10_USAGE_DEFAULT;
descDepth.BindFlags = D3D10_BIND_DEPTH_STENCIL;
descDepth.CPUAccessFlags = 0;
descDepth.MiscFlags = 0;
hr = g_pd3dDevice->CreateTexture2D( &descDepth, NULL, &g_pDepthStencil );
// Create the depth stencil view
D3D10_DEPTH_STENCIL_VIEW_DESC descDSV;
descDSV.Format = DXGI_FORMAT_D32_FLOAT;
descDSV.ViewDimension = D3D10_DSV_DIMENSION_TEXTURE2D;
descDSV.Texture2D.MipSlice = 0;
hr = g_pd3dDevice->CreateDepthStencilView( g_pDepthStencil, &descDSV, &g_pDepthStencilView );
/////////////////////////////
//Shadow Mapping
//create shadow map texture desc
descDepth.Width = width;
descDepth.Height = height;
descDepth.Format = DXGI_FORMAT_R32_TYPELESS;
descDepth.BindFlags = D3D10_BIND_DEPTH_STENCIL | D3D10_BIND_SHADER_RESOURCE;
//create shader resource view desc
D3D10_SHADER_RESOURCE_VIEW_DESC srvDesc;
srvDesc.Format = DXGI_FORMAT_R32_FLOAT;
srvDesc.ViewDimension = D3D10_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2D.MipLevels = descDepth.MipLevels;
srvDesc.Texture2D.MostDetailedMip = 0;
Render Scene
//Create shadow map
//***************************************************************************
//set render targets
//set render targets and viewport
g_pd3dDevice->OMSetRenderTargets(0, 0, pShadowMapDepthView);
g_pd3dDevice->ClearDepthStencilView( pShadowMapDepthView, D3D10_CLEAR_DEPTH, 1.0f, 0 );
moveCam( lightPos.x, lightPos.y, lightPos.z );
DrawSceneShadow();
//Render final scene
//***************************************************************************
//set render targets
g_pd3dDevice->OMSetRenderTargets(1, &g_pRenderTargetView, g_pDepthStencilView);
g_pd3dDevice->RSSetViewports(1, &vp);
g_pd3dDevice->ClearRenderTargetView( g_pRenderTargetView, D3DXCOLOR(0.6f,0.6f,0.6f,0) );
g_pd3dDevice->ClearDepthStencilView( g_pDepthStencilView, D3D10_CLEAR_DEPTH, 1.0f, 0 );
//bind shadow map texture
g_pEffect->GetVariableByName("shadowMap")->AsShaderResource()->SetResource( pShadowMapSRView );
ScreenGrab();
resetCam();
lightMatrix();
DrawScene();
//unbind shadow map as SRV and call apply on scene rendering technique
g_pEffect->GetVariableByName("shadowMap")->AsShaderResource()->SetResource( 0 );
g_pRenderShadowMapTechnique->GetPassByIndex(0)->Apply( 0 );

Related

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

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.

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;

Get latitude and longitude that is 5 metres away of a latitude and longitude [duplicate]

Bit stuck on this one. I am retrieving a list of geo coords via JSON and popping them onto a google map. All is working well except in the instance when I have two or more markers on the exact same spot. The API only displays 1 marker - the top one. This is fair enough I suppose but would like to find a way to display them all somehow.
I've searched google and found a few solutions but they mostly seem to be for V2 of the API or just not that great. Ideally I'd like a solution where you click some sort of group marker and that then shows the markers clustered around the spot they are all in.
Anybody had this problem or similar and would care to share a solution?
Take a look at OverlappingMarkerSpiderfier.
There's a demo page, but they don't show markers which are exactly on the same spot, only some which are very close together.
But a real life example with markers on the exact same spot can be seen on http://www.ejw.de/ejw-vor-ort/ (scroll down for the map and click on a few markers to see the spider-effect).
That seems to be the perfect solution for your problem.
Offsetting the markers isn't a real solution if they're located in the same building. What you might want to do is modify the markerclusterer.js like so:
Add a prototype click method in the MarkerClusterer class, like so - we will override this later in the map initialize() function:
MarkerClusterer.prototype.onClick = function() {
return true;
};
In the ClusterIcon class, add the following code AFTER the clusterclick trigger:
// Trigger the clusterclick event.
google.maps.event.trigger(markerClusterer, 'clusterclick', this.cluster_);
var zoom = this.map_.getZoom();
var maxZoom = markerClusterer.getMaxZoom();
// if we have reached the maxZoom and there is more than 1 marker in this cluster
// use our onClick method to popup a list of options
if (zoom >= maxZoom && this.cluster_.markers_.length > 1) {
return markerClusterer.onClickZoom(this);
}
Then, in your initialize() function where you initialize the map and declare your MarkerClusterer object:
markerCluster = new MarkerClusterer(map, markers);
// onClickZoom OVERRIDE
markerCluster.onClickZoom = function() { return multiChoice(markerCluster); }
Where multiChoice() is YOUR (yet to be written) function to popup an InfoWindow with a list of options to select from. Note that the markerClusterer object is passed to your function, because you will need this to determine how many markers there are in that cluster. For example:
function multiChoice(mc) {
var cluster = mc.clusters_;
// if more than 1 point shares the same lat/long
// the size of the cluster array will be 1 AND
// the number of markers in the cluster will be > 1
// REMEMBER: maxZoom was already reached and we can't zoom in anymore
if (cluster.length == 1 && cluster[0].markers_.length > 1)
{
var markers = cluster[0].markers_;
for (var i=0; i < markers.length; i++)
{
// you'll probably want to generate your list of options here...
}
return false;
}
return true;
}
I used this alongside jQuery and it does the job:
var map;
var markers = [];
var infoWindow;
function initialize() {
var center = new google.maps.LatLng(-29.6833300, 152.9333300);
var mapOptions = {
zoom: 5,
center: center,
panControl: false,
zoomControl: false,
mapTypeControl: false,
scaleControl: false,
streetViewControl: false,
overviewMapControl: false,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
$.getJSON('jsonbackend.php', function(data) {
infoWindow = new google.maps.InfoWindow();
$.each(data, function(key, val) {
if(val['LATITUDE']!='' && val['LONGITUDE']!='')
{
// Set the coordonates of the new point
var latLng = new google.maps.LatLng(val['LATITUDE'],val['LONGITUDE']);
//Check Markers array for duplicate position and offset a little
if(markers.length != 0) {
for (i=0; i < markers.length; i++) {
var existingMarker = markers[i];
var pos = existingMarker.getPosition();
if (latLng.equals(pos)) {
var a = 360.0 / markers.length;
var newLat = pos.lat() + -.00004 * Math.cos((+a*i) / 180 * Math.PI); //x
var newLng = pos.lng() + -.00004 * Math.sin((+a*i) / 180 * Math.PI); //Y
var latLng = new google.maps.LatLng(newLat,newLng);
}
}
}
// Initialize the new marker
var marker = new google.maps.Marker({map: map, position: latLng, title: val['TITLE']});
// The HTML that is shown in the window of each item (when the icon it's clicked)
var html = "<div id='iwcontent'><h3>"+val['TITLE']+"</h3>"+
"<strong>Address: </strong>"+val['ADDRESS']+", "+val['SUBURB']+", "+val['STATE']+", "+val['POSTCODE']+"<br>"+
"</div>";
// Binds the infoWindow to the point
bindInfoWindow(marker, map, infoWindow, html);
// Add the marker to the array
markers.push(marker);
}
});
// Make a cluster with the markers from the array
var markerCluster = new MarkerClusterer(map, markers, { zoomOnClick: true, maxZoom: 15, gridSize: 20 });
});
}
function markerOpen(markerid) {
map.setZoom(22);
map.panTo(markers[markerid].getPosition());
google.maps.event.trigger(markers[markerid],'click');
switchView('map');
}
google.maps.event.addDomListener(window, 'load', initialize);
Expanding on Chaoley's answer, I implemented a function that, given a list of locations (objects with lng and lat properties) whose coordinates are exactly the same, moves them away from their original location a little bit (modifying objects in place). They then form a nice circle around the center point.
I found that, for my latitude (52deg North), 0.0003 degrees of circle radius work best, and that you have to make up for the difference between latitude and longitude degrees when converted to kilometres. You can find approximate conversions for your latitude here.
var correctLocList = function (loclist) {
var lng_radius = 0.0003, // degrees of longitude separation
lat_to_lng = 111.23 / 71.7, // lat to long proportion in Warsaw
angle = 0.5, // starting angle, in radians
loclen = loclist.length,
step = 2 * Math.PI / loclen,
i,
loc,
lat_radius = lng_radius / lat_to_lng;
for (i = 0; i < loclen; ++i) {
loc = loclist[i];
loc.lng = loc.lng + (Math.cos(angle) * lng_radius);
loc.lat = loc.lat + (Math.sin(angle) * lat_radius);
angle += step;
}
};
#Ignatius most excellent answer, updated to work with v2.0.7 of MarkerClustererPlus.
Add a prototype click method in the MarkerClusterer class, like so - we will override this later in the map initialize() function:
// BEGIN MODIFICATION (around line 715)
MarkerClusterer.prototype.onClick = function() {
return true;
};
// END MODIFICATION
In the ClusterIcon class, add the following code AFTER the click/clusterclick trigger:
// EXISTING CODE (around line 143)
google.maps.event.trigger(mc, "click", cClusterIcon.cluster_);
google.maps.event.trigger(mc, "clusterclick", cClusterIcon.cluster_); // deprecated name
// BEGIN MODIFICATION
var zoom = mc.getMap().getZoom();
// Trying to pull this dynamically made the more zoomed in clusters not render
// when then kind of made this useless. -NNC # BNB
// var maxZoom = mc.getMaxZoom();
var maxZoom = 15;
// if we have reached the maxZoom and there is more than 1 marker in this cluster
// use our onClick method to popup a list of options
if (zoom >= maxZoom && cClusterIcon.cluster_.markers_.length > 1) {
return mc.onClick(cClusterIcon);
}
// END MODIFICATION
Then, in your initialize() function where you initialize the map and declare your MarkerClusterer object:
markerCluster = new MarkerClusterer(map, markers);
// onClick OVERRIDE
markerCluster.onClick = function(clickedClusterIcon) {
return multiChoice(clickedClusterIcon.cluster_);
}
Where multiChoice() is YOUR (yet to be written) function to popup an InfoWindow with a list of options to select from. Note that the markerClusterer object is passed to your function, because you will need this to determine how many markers there are in that cluster. For example:
function multiChoice(clickedCluster) {
if (clickedCluster.getMarkers().length > 1)
{
// var markers = clickedCluster.getMarkers();
// do something creative!
return false;
}
return true;
};
This is more of a stopgap 'quick and dirty' solution similar to the one Matthew Fox suggests, this time using JavaScript.
In JavaScript you can just offset the lat and long of all of your locations by adding a small random offset to both e.g.
myLocation[i].Latitude+ = (Math.random() / 25000)
(I found that dividing by 25000 gives enough separation but doesn't move the marker significantly from the exact location e.g. a specific address)
This makes a reasonably good job of offsetting them from one another, but only after you've zoomed in closely. When zoomed out, it still won't be clear that there are multiple options for the location.
The answers above are more elegant, but I found a quick and dirty way that actually works really really incredibly well. You can see it in action at www.buildinglit.com
All I did was add a random offset to the latitude and longditude to my genxml.php page so it returns slightly different results each time with offset each time the map is created with markers. This sounds like a hack, but in reality you only need the markers to move a slight nudge in a random direction for them to be clickable on the map if they are overlapping. It actually works really well, I would say better than the spider method because who wants to deal with that complexity and have them spring everywhere. You just want to be able to select the marker. Nudging it randomly works perfect.
Here is an example of the while statement iteration node creation in my php_genxml.php
while ($row = #mysql_fetch_assoc($result)){ $offset = rand(0,1000)/10000000;
$offset2 = rand(0, 1000)/10000000;
$node = $dom->createElement("marker");
$newnode = $parnode->appendChild($node);
$newnode->setAttribute("name", $row['name']);
$newnode->setAttribute("address", $row['address']);
$newnode->setAttribute("lat", $row['lat'] + $offset);
$newnode->setAttribute("lng", $row['lng'] + $offset2);
$newnode->setAttribute("distance", $row['distance']);
$newnode->setAttribute("type", $row['type']);
$newnode->setAttribute("date", $row['date']);
$newnode->setAttribute("service", $row['service']);
$newnode->setAttribute("cost", $row['cost']);
$newnode->setAttribute("company", $company);
Notice under lat and long there is the +offset. from the 2 variables above. I had to divide random by 0,1000 by 10000000 in order to get a decimal that was randomly small enough to just barely move the markers around. Feel free to tinker with that variable to get one that is more precise for your needs.
I like simple solutions so here's mine.
Instead of modifying the lib, which would make it harder to mantain. you can simply watch the event like this
google.maps.event.addListener(mc, "clusterclick", onClusterClick);
then you can manage it on
function onClusterClick(cluster){
var ms = cluster.getMarkers();
i, ie, used bootstrap to show a panel with a list. which i find much more confortable and usable than spiderfying on "crowded" places. (if you are using a clusterer chances are you will end up with collisions once you spiderfy).
you can check the zoom there too.
btw. i just found leaflet and it seems to work much better, the cluster AND spiderfy works very fluidly http://leaflet.github.io/Leaflet.markercluster/example/marker-clustering-realworld.10000.html
and it's open-source.
For situations where there are multiple services in the same building you could offset the markers just a little, (say by .001 degree), in a radius from the actual point. This should also produce a nice visual effect.
Check out Marker Clusterer for V3 - this library clusters nearby points into a group marker. The map zooms in when the clusters are clicked. I'd imagine when zoomed right in you'd still have the same problem with markers on the same spot though.
Updated to work with MarkerClustererPlus.
google.maps.event.trigger(mc, "click", cClusterIcon.cluster_);
google.maps.event.trigger(mc, "clusterclick", cClusterIcon.cluster_); // deprecated name
// BEGIN MODIFICATION
var zoom = mc.getMap().getZoom();
// Trying to pull this dynamically made the more zoomed in clusters not render
// when then kind of made this useless. -NNC # BNB
// var maxZoom = mc.getMaxZoom();
var maxZoom = 15;
// if we have reached the maxZoom and there is more than 1 marker in this cluster
// use our onClick method to popup a list of options
if (zoom >= maxZoom && cClusterIcon.cluster_.markers_.length > 1) {
var markers = cClusterIcon.cluster_.markers_;
var a = 360.0 / markers.length;
for (var i=0; i < markers.length; i++)
{
var pos = markers[i].getPosition();
var newLat = pos.lat() + -.00004 * Math.cos((+a*i) / 180 * Math.PI); // x
var newLng = pos.lng() + -.00004 * Math.sin((+a*i) / 180 * Math.PI); // Y
var finalLatLng = new google.maps.LatLng(newLat,newLng);
markers[i].setPosition(finalLatLng);
markers[i].setMap(cClusterIcon.cluster_.map_);
}
cClusterIcon.hide();
return ;
}
// END MODIFICATION
I used markerclustererplus, and for me this works:
//Code
google.maps.event.addListener(cMarkerClusterer, "clusterclick", function (c) {
var markers = c.getMarkers();
//Check Markers array for duplicate position and offset a little
if (markers .length > 1) {
//Check if all markers are in the same position (with 4 significant digits)
if (markers .every((val, index, arr) => (val.getPosition().lat().toFixed(4) == arr[0].getPosition().lat().toFixed(4)) && (val.getPosition().lng().toFixed(4) == arr[0].getPosition().lng().toFixed(4)))) { /
//Don't modify first element
for (i = 1; i < markers.length; i++) {
var existingMarker = markers[i];
var pos = existingMarker.getPosition();
var quot = 360.0 / markers.length;
var newLat = pos.lat() + -.00008 * Math.cos(+quot * i); //+ -.00008 * Math.cos((+quot * i) / 180 * Math.PI); //x
var newLng = pos.lng() + -.00008 * Math.sin(+quot * i); //+ -.0008 * Math.sin((+quot * i) / 180 * Math.PI); //Y
existingMarker.setPosition(new google.maps.LatLng(newLat, newLng));
}
let cZoom = map.getZoom();
map.setZoom(cZoom-1);
map.setZoom(cZoom+1);
}
}
});
Check this: https://github.com/plank/MarkerClusterer
This is the MarkerCluster modified to have a infoWindow in a cluster marker, when you have several markers in the same position.
You can see how it works here: http://culturedays.ca/en/2013-activities
Giving offset will make the markers faraway when the user zoom in to max. So i found a way to achieve that. this may not be a proper way but it worked very well.
// This code is in swift
for loop markers
{
//create marker
let mapMarker = GMSMarker()
mapMarker.groundAnchor = CGPosition(0.5, 0.5)
mapMarker.position = //set the CLLocation
//instead of setting marker.icon set the iconView
let image:UIIMage = UIIMage:init(named:"filename")
let imageView:UIImageView = UIImageView.init(frame:rect(0,0, ((image.width/2 * markerIndex) + image.width), image.height))
imageView.contentMode = .Right
imageView.image = image
mapMarker.iconView = imageView
mapMarker.map = mapView
}
set the zIndex of the marker so that you will see the marker icon which you want to see on top, otherwise it will animate the markers like auto swapping. when the user tap the marker handle the zIndex to bring the marker on top using zIndex Swap.
How to get away with it..
[Swift]
var clusterArray = [String]()
var pinOffSet : Double = 0
var pinLat = yourLat
var pinLong = yourLong
var location = pinLat + pinLong
A new marker is about to be created? check clusterArray and manipulate it's offset
if(!clusterArray.contains(location)){
clusterArray.append(location)
} else {
pinOffSet += 1
let offWithIt = 0.00025 // reasonable offset with zoomLvl(14-16)
switch pinOffSet {
case 1 : pinLong = pinLong + offWithIt ; pinLat = pinLat + offWithIt
case 2 : pinLong = pinLong + offWithIt ; pinLat = pinLat - offWithIt
case 3 : pinLong = pinLong - offWithIt ; pinLat = pinLat - offWithIt
case 4 : pinLong = pinLong - offWithIt ; pinLat = pinLat + offWithIt
default : print(1)
}
}
result
Adding to Matthew Fox's sneaky genius answer, I have added a small random offset to each lat and lng when setting the marker object. For example:
new LatLng(getLat()+getMarkerOffset(), getLng()+getMarkerOffset()),
private static double getMarkerOffset(){
//add tiny random offset to keep markers from dropping on top of themselves
double offset =Math.random()/4000;
boolean isEven = ((int)(offset *400000)) %2 ==0;
if (isEven) return offset;
else return -offset;
}
I used this http://leaflet.github.io/Leaflet.markercluster/ and perfectly works for me. added full solution.
<html lang="en">
<head>
<script src="https://code.jquery.com/jquery-3.2.1.js" integrity="sha256-DZAnKJ/6XZ9si04Hgrsxu/8s717jcIzLy3oi35EouyE=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.0.3/leaflet.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/leaflet.markercluster/1.0.4/leaflet.markercluster.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.0.3/leaflet.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.markercluster/1.0.4/MarkerCluster.Default.css" />
</head>
<body>
<div id="map"></div>
<script>
var addressData = [
{id: 9, name: "Ankita", title: "Manager", latitude: "33.1128019", longitude: "-96.6958939"},
{id: 1, name: "Aarti", title: "CEO", latitude: "33.1128019", longitude: "-96.6958939"},
{id: 2, name: "Payal", title: "Employee", latitude: "33.0460488", longitude: "-96.9983386"}];
var addressPoints = [];
for (i = 0; i < addressData.length; i++) {
var marker = {
latitude: addressData[i].latitude,
longitude: addressData[i].longitude,
coverage: addressData[i]
};
addressPoints.push(marker);
}
var map = L.map('map').setView(["32.9602172", "-96.7036844"], 5);
var basemap = L.tileLayer('http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png', {attribution: '© OpenStreetMap © CartoDB', subdomains: 'abcd'});
basemap.addTo(map);
var markers = L.markerClusterGroup();
for (var i = 0; i < addressPoints.length; i++) {
// var icon1 = "app/common_assest/images/pin/redPin.png"; // set ehere you own marker pin whatever you want to set
var currentMarker = addressPoints[i];
console.log(currentMarker);
var contentString = '<div class="mapinfoWindowContent">' +
'<div class="mapInfoTitle">Name: ' + currentMarker.coverage.name + '</div>' +
'<div class="mapInfoSubText">Licence: ' + currentMarker.coverage.title + '</div>' +
'</div>';
// var myIcon = L.icon({// set ehere you own marker pin whatever you want to set
// iconUrl: icon1,
// iconRetinaUrl: icon1,
// });
var marker = L.marker(new L.LatLng(currentMarker['latitude'], currentMarker['longitude']), {
title: currentMarker.coverage.name
});
marker.bindPopup(contentString);
markers.addLayer(marker);
}
markers.addTo(map);
</script>
</body>
Hope fully it will help to you easily.
The solution I've used is pretty simple. Just use #googlemaps/markerclusterer library in combination with the Maps JavaScript API.
Than you will need just one line after the map is filled out with your markers:
new MarkerClusterer({ map, markers });
All information can be found here
https://developers.google.com/maps/documentation/javascript/marker-clustering
I'm using Android's Map Cluster. These are the libs I'm using:
implementation 'com.google.android.gms:play-services-places:16.0.0' 
implementation 'com.google.android.gms:play-services-maps:16.0.0'
implementation 'com.google.android.gms:play-services-location:16.0.0'
implementation 'com.google.maps.android:android-maps-utils:2.0.1'
The problem I was running into is that the Cluster Markers don't separate if two items have the exact same Latitude and Longitudinal points. My fix is to scan through my array of items and if two positions match, I move their positions slightly. Here's my code:
Field Variables:
private ArrayList<Tool> esTools;
When you're done initializing the ArrayList of Tools. From your parsing method, call this:
loopThroughToolsListAndFixOnesThatHaveSameGeoPoint_FixStackingIssue();
Where the magic happens:
private void loopThroughToolsListAndFixOnesThatHaveSameGeoPoint_FixStackingIssue() {
DecimalFormat decimalFormatTool = new DecimalFormat("000.0000");
decimalFormatTool.setRoundingMode(RoundingMode.DOWN);
for(int backPointer=0; backPointer <= (esTools.size()-1); backPointer++){
Map<String, Double> compareA = esTools.get(backPointer).getUserChosenGeopoint();
Double compareA_Latitude = compareA.get("_latitude");
compareA_Latitude= Double.valueOf(decimalFormatTool.format(compareA_Latitude));
Double compareA_Longitude = compareA.get("_longitude");
compareA_Longitude= Double.valueOf(decimalFormatTool.format(compareA_Longitude));
System.out.println("compareA_Lat= "+ compareA_Latitude+ ", compareA_Long= "+ compareA_Longitude);
for(int frontPointer=0; frontPointer <= (esTools.size()-1); frontPointer++){
if(backPointer==frontPointer){
continue;
}
Map<String, Double> compareB = esTools.get(frontPointer).getUserChosenGeopoint();
Double compareB_Latitude = compareB.get("_latitude");
compareB_Latitude= Double.valueOf(decimalFormatTool.format(compareB_Latitude));
Double compareB_Longitude = compareB.get("_longitude");
compareB_Longitude= Double.valueOf(decimalFormatTool.format(compareB_Longitude));
if((compareB_Latitude.equals(compareA_Latitude)) && (compareB_Longitude.equals(compareA_Longitude))) {
System.out.println("these tools match");
Random randomGen = new Random();
Double randomNumLat = randomGen.nextDouble() * 0.00015;
int addOrSubtractLatitude= ( randomGen.nextBoolean() ? 1 : -1 );
randomNumLat = randomNumLat*addOrSubtractLatitude;
Double randomNumLong = randomGen.nextDouble() * 0.00015;
int addOrSubtractLongitude= ( randomGen.nextBoolean() ? 1 : -1 );
randomNumLong = randomNumLong*addOrSubtractLongitude;
System.out.println("Adding Random Latitude="+ randomNumLat + ", Longitude= "+ randomNumLong);
System.out.println("\n");
Map<String, Double> latitudeLongitude = new HashMap<>();
latitudeLongitude.put("_latitude", (compareB_Latitude+ randomNumLat));
latitudeLongitude.put("_longitude", (compareB_Longitude+ randomNumLong));
esTools.get(frontPointer).setUserChosenGeopoint(latitudeLongitude);
}
}
}
}
So what the above method does is scan through my ArrayList and see if there are any two Tools have matching points. If the Lat Long points match, move one slightly.
Expanding on the answers given above, just ensure you set maxZoom option when initializing the map object.
Adding to above answers but offering an alternative quick solution in php and wordpress. For this example I am storing the location field via ACF and looping through the posts to grab that data.
I found that storing the lat / lng in an array and check the value of that array to see if the loop matches, we can then update the value within that array with the amount we want to shift our pips by.
//This is the value to shift the pips by. I found this worked best with markerClusterer
$add_to_latlng = 0.00003;
while ($query->have_posts()) {
$query->the_post();
$meta = get_post_meta(get_the_ID(), "postcode", true); //uses an acf field to store location
$lat = $meta["lat"];
$lng = $meta["lng"];
if(in_array($meta["lat"],$lat_checker)){ //check if this meta matches
//if matches then update the array to a new value (current value + shift value)
// This is using the lng value for a horizontal line of pips, use lat for vertical, or both for a diagonal
if(isset($latlng_storer[$meta["lng"]])){
$latlng_storer[$meta["lng"]] = $latlng_storer[$meta["lng"]] + $add_to_latlng;
$lng = $latlng_storer[$meta["lng"]];
} else {
$latlng_storer[$meta["lng"]] = $meta["lng"];
$lng = $latlng_storer[$meta["lng"]];
}
} else {
$lat_checker[] = $meta["lat"]; //just for simple checking of data
$latlng_storer[$meta["lat"]] = floatval($meta["lat"]);
$latlng_storer[$meta["lng"]] = floatval($meta["lng"]);
}
$entry[] = [
"lat" => $lat,
"lng" => $lng,
//...Add all the other post data here and use this array for the pips
];
} // end query
Once I've grabbed these locations I json encode the $entry variable and use that within my JS.
let locations = <?=json_encode($entry)?>;
I know this is a rather specific situation but I hope this helps someone along the line!
Extending answers above, when you got joined strings, not added/subtracted position (e.g. "37.12340-0.00069"), convert your original lat/longitude to floats, e.g. using parseFloat(), then add or subtract corrections.

DirectX 11 Alpha Blending Not Working

Okay, so I have been trying to get Alpha Blending to work in my 3D application but it just doesn't want to happen. I am drawing 2d images with an orthogonal projection at the very end of the rendering loop (depth testing remains enabled) and the image textures have transparent parts but they render black.
Here is my blending code:
D3D11_BLEND_DESC blendStateDesc;
ZeroMemory(&blendStateDesc, sizeof(D3D11_BLEND_DESC));
blendStateDesc.AlphaToCoverageEnable = FALSE;
blendStateDesc.IndependentBlendEnable = FALSE;
blendStateDesc.RenderTarget[0].BlendEnable = TRUE;
blendStateDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
blendStateDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
blendStateDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
blendStateDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_SRC_ALPHA;
blendStateDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_DEST_ALPHA;
blendStateDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
blendStateDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
if (FAILED(device->CreateBlendState(&blendStateDesc, &blendState))) {
printf("Failed To Create Blend State\n");
}
deviceContext->OMSetBlendState(blendState, NULL, 0xFFFFFF);
And if it helps here is the texture description:
D3D11_TEXTURE2D_DESC texDesc;
texDesc.Width = TextureWidth;
texDesc.Height = textureHeight;
texDesc.MipLevels = 1;
texDesc.ArraySize = 1;
texDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
texDesc.SampleDesc.Count = 1;
texDesc.SampleDesc.Quality = 0;
texDesc.Usage = D3D11_USAGE_IMMUTABLE;
texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
texDesc.CPUAccessFlags = 0;
texDesc.MiscFlags = 0;
I am only using a single render target and not pre-multiplying alphas inside the shaders. I have looked everywhere and tried all manner of different combinations for the D3D11_BLEND_STATE but nothing has worked.
The closest I can get is when I set the AlphaToCoverage to TRUE but then it doesn't work if I change the alpha of the vertices, and I know for what I'm doing AlphaToCoverage should be FALSE.
I know this is a very old question but i had a similiar issue.
What i had to do was to make sure you set/enabble the blend state before drawing and then disable after the draw call of the transparent 2d image. More information can be found: DirectX Image texture quad displays underlying controls color where it is transparent

Flex/ActionScript - rotate Sprite around its center

I have created a Sprite in Actionscript and rendered it to a Flex Canvas. Suppose:
var fooShape:Sprite = new FooSpriteSubclass();
fooCanvas.rawChildren.addChild(myshape);
//Sprite shape renders on screen
fooShape.rotation = fooNumber;
This will rotate my shape, but seems to rotate it around the upper-left
point of its parent container(the canvas).
How can I force the Sprite to rotate about is own center point? I could obviously
write code to calculate the rotation, and then have it re-render, but I think there
must be a built-in way to do this, and certainly do not want to 'reinvent the wheel'
if possible.
I am using FlexBuilder, and therefore do not have access to the full Flash API.
Thank you much!
The following steps are required to rotate objects based on a reference point (using Matrix object and getBounds):
Matrix translation (moving to the reference point)
Matrix rotation
Matrix translation (back to original position)
For example to rotate an object 90 degrees around its center:
// Get the matrix of the object
var matrix:Matrix = myObject.transform.matrix;
// Get the rect of the object (to know the dimension)
var rect:Rectangle = myObject.getBounds(parentOfMyObject);
// Translating the desired reference point (in this case, center)
matrix.translate(- (rect.left + (rect.width/2)), - (rect.top + (rect.height/2)));
// Rotation (note: the parameter is in radian)
matrix.rotate((90/180)*Math.PI);
// Translating the object back to the original position.
matrix.translate(rect.left + (rect.width/2), rect.top + (rect.height/2));
Key methods used:
Matrix.rotate
Matrix.translate
DisplayObject.getBounds
Didn't have much luck with the other examples. This one worked for me. I used it on a UIComponent.
http://www.selikoff.net/2010/03/17/solution-to-flex-image-rotation-and-flipping-around-center/
private static function rotateImage(image:Image, degrees:Number):void {
// Calculate rotation and offsets
var radians:Number = degrees * (Math.PI / 180.0);
var offsetWidth:Number = image.contentWidth/2.0;
var offsetHeight:Number = image.contentHeight/2.0;
// Perform rotation
var matrix:Matrix = new Matrix();
matrix.translate(-offsetWidth, -offsetHeight);
matrix.rotate(radians);
matrix.translate(+offsetWidth, +offsetHeight);
matrix.concat(image.transform.matrix);
image.transform.matrix = matrix;
}
Actually I had to add this code to make above solutions work for me.
private var _rotateCount = 0;
var _origginalMatrix:Matrix=new Matrix();
.........
if (_rotateCount++ >= 360 / angleDegrees)
{
myObject.transform.matrix = _origginalMatrix;
_rotateCount = 0;
return;
}
var matrix:Matrix = myObject.transform.matrix;
....
Without that after some long time rotated object slowly moves somewhere right top.
An alternative solution is to put your object inside another View, move it so that your image's center is at the container's top-left corner, and then rotate the container.
import spark.components.*;
var myContainer:View = new View();
var myImage:Image = new Image();
myContainer.addElement(myImage);
myImage.x = myImage.width / -2;
myImage.y = myImage.height / -2;
addElement(myContainer);
myContainer.rotation = whateverAngle;
One issue might be that the width of the image isn't know at the moment it is created, so you might want to find a way around that. (Hardcode it, or see if myImage.preliminaryWidth works)
/**
* Rotates the object based on its center
* Parameters: #obj => the object to rotate
* # rotation => angle to rotate
* */
public function RotateAroundCenter(obj:Object, rotation:Number):void
{
var bound:Rectangle = new Rectangle();
// get the bounded rectangle of objects
bound = obj.getRect(this);
// calculate mid poits
var midx1:Number = bound.x + bound.width/2;
var midy1:Number = bound.y + bound.height/2;
// assign the rotation
obj.rotation = rotation;
// assign the previous mid point as (x,y)
obj.x = midx1;
obj.y = midy1;
// get the new bounded rectangle of objects
bound = obj.getRect(this);
// calculate new mid points
var midx2:Number = bound.x + bound.width/2;
var midy2:Number = bound.y + bound.height/2;
// calculate differnece between the current mid and (x,y) and subtract
//it to position the object in the previous bound.
var diff:Number = midx2 - obj.x;
obj.x -= diff;
diff = midy2 - obj.y;
obj.y -= diff;
}
//////////////////
Usage:
you can use the above function as described below,
var img:Canvas = new Canvas()
RotateAroundCenter(img, rotation);
This will help you
REf: http://subashflash.blogspot.in/2010/08/rotation-of-object-based-on-center.html
If you want to rotate around the center, merely center the asset inside your sprite by setting the internal assets x and y to half of the width and height of the asset. This swill center your content and allow it to rotate around a center point.
An example of runtime loaded assets is as follows:
var loader:Loader = new Loader():
var request:URLRequest = new URLRequest(path/to/asset.ext);
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, _onLoaderComplete);
loader.load(request);
private function _onLoaderComplete(e:Event):void
{
var mc:MovieClip = e.target.content as MovieClip;
mc.x = -mc.width * 0.5;
mc.y = -mc.height * 0.5;
mc.rotation = 90;
addChild(mc);
}

Resources