How do I refresh a TMS layer in OpenLayers? - refresh

I have a TMS layer that looks something like this:
var v = 1;
my_tms = new OpenLayers.Layer.TMS(
"My TMS",
"my_mapserver.php?v="+my_var+"&",
{ transparent: 'true', type:'png', getURL:get_my_url }
);
Where my_mapserver.php returns map tiles according to the value of v.
The app allows users to change v, and I simply want to refresh the my_tms layer, however, so far the only way I can get it to refresh is by destroying the map and recreating it.
I thought I could just do something like this:
v = 2;
my_tms = new OpenLayers.Layer.TMS(
"My TMS",
"my_mapserver.php?v="+my_var+"&",
{ transparent: 'true', type:'png', getURL:get_my_url }
);
my_tms.redraw();
However, these tiles are not getting requested when I redraw().
Any help is appreciated.

As TMS layers inherits from Grid layer you could try to call clearGrid() method to remove all existing tiles and then spiralTileLoad() to load new ones.

layer.redraw();, OpenLayers.Strategy.Refresh and clearGrid() didn't help me in reloading tiles of OpenLayers.Layer.TMS layer in OpenLayers 2.13.1, but helped:
layer.mergeNewParams({});

Related

Can't assign the landscape LayerInfo object to a landscape

I've been developing an automated system that requires me to generate the LayerInfo objects of a given Landscape. So far I've been able to generate the required LayerInfo object's, but I wasn't able to assign them, or to be more precise, when I try to assign the necessary layers in the ULandscapeInfo property they appear in the editor but are not assigned, unless I save them and restart the engine, they also appear weird in the editor, as you can see in the image. I think it's a similar problem to the one in this thread. The code bellow it's responsible for assignig the LayerInfo:
// This method creates a
// new layer info object
UWorld * currentWorld = GetWorld();
ULevel * level = currentWorld->GetLevel(0); // TODO : just for debuging
ULandscapeLayerInfoObject* layerInfo = Landscape->CreateLayerInfo(*(layerName), level);
bool isDirty = layerInfo->MarkPackageDirty();
// Get a reference for the landscape Info
ULandscapeInfo* landscapeInfo = Landscape->GetLandscapeInfo();
landscapeInfo->CreateLayerEditorSettingsFor(layerInfo);
FLandscapeInfoLayerSettings* layerSettings = &landscapeInfo->Layers[1];
landscapeInfo->Layers[0] = FLandscapeInfoLayerSettings(layerInfo, Landscape);
UEditorAssetLibrary::SaveAsset(assetName, false);
// Assign the respective values
if (!layerSettings->LayerInfoObj)
{
layerSettings->Owner = Landscape;
layerSettings->LayerInfoObj = layerInfo;
layerSettings->bValid = true;
}
Editor Screenshot

Override open variable for class in Swift and SpriteKit for use in XCode's ActionEditor

I'm trying to make small platformer game, just in learning purposes. I've tried to animate character with array of SKTextures like this:
let animation: SKAction = SKAction.animate(
with: frames.map {
let texture : SKTexture = SKTexture(imageNamed: $0)
texture.filteringMode = SKTextureFilteringMode.nearest
return texture
},
timePerFrame: 0.15
)
frames variable is array of SKTextures. I've used map to set filtering mode for each texture. This works fine and dandy, but than i've discovered that i can create animations (actions) in ActionEditor in XCode with AnimateWithTextures action. And here lies my problem. This is much more efficient, but i can't change filtering mode for textures in animation in ActionEditor. I've looked into SKTexture class and saw this:
open class SKTexture : NSObject, NSCopying, NSCoding {
...
/**
The filtering mode the texture should use when not drawn at native size. Defaults to SKTextureFilteringLinear.
*/
open var filteringMode: SKTextureFilteringMode
...
}
If i'm not mistaken open means that i can override variable, but i don't know how. I want to set default value of filteringMode to SKTextureFilteringMode.nearest for all SKTextures so ActionEditor will use textures with texture filtering set to nearest neighbor.
Also if you know how to set filtering mode for textures in specific action – i would like to know how to do it too. Thanks
you can create a function to setup the animation for you, and create an extension to SKTexture with your custom init, and when your ready just call it to your node.
extension SKTexture { // Declare this extension outside your class decleration
convenience init(customImageNamed: String) {
self.init(imageNamed: customImageNamed)
self.filteringMode = .nearest
}
}
func setupAnimationWithPrefix(_ prefix: String, start: Int, end: Int, timePerFrame: TimeInterval) -> SKAction{
var textures = [SKTexture]()
for i in start...end{
textures.append(SKTexture(customImageNamed: "\(prefix)\(i)"))
}
return SKAction.animate(with: textures, timePerFrame: timePerFrame)
}
if you have 10 images named image1, image2, image3 ect..then this is how you would use this function
func runAction(){
let action = setupAnimationWithPrefix("image", start: 1, end: 10, timePerFrame: 0.1)
yourNode.run(action)
} // you can change timePerFrame to your liking i find 0.1 sec per frame the best
Unfortunately you can't override a variable without subclassing it, that is to do something like
class MyTexture: SKTexture {
from there, you could override the variable:
override var filteringMode: SKTextureFilteringMode {
get {
return .nearest
}
set {
}
}
That should work, but now you can't change the filtering mode, ever (without going through a bunch of hooplah).
So the more apt way would be to set the default value via the initializer, but SKTexture has no public designated initializers, so that option is out of the window.
So your best bet is going to be the convenience init extension by Arie, or just make a plain function that returns a new texture:
func nearestTexture(imageNamed name: String) -> SKTexture {
let newTex = SKTexture(imageNamed: name)
newTex.filteringMode = .nearest
return newTex
}
let texture: SKTexture = nearestTexture(imageNamed: "lol")
ActionEditor is still very limited in features, you are going to have to write some kind of code behind to allow for texture filtering. If you do not plan on scaling your sprites (Note I said sprite, not scene, these are two different behaviors), then I would not even worry about texture filtering, the time difference would be negligible.

QML Map: Large amount of displayed items

I have a performance issue while displaying large amounts MapItems on a Map provided by the QML Location module. I already asked the question here (https://forum.qt.io/topic/79229/large-amount-of-qml-mapitems), but nobody could help me, so I wanted to try it here once. I also found this question (How to use the QML/QtLocation module for displaying a large amount of offline data on a map?), but before adding another dependency, I wanted to see if my code can be improved so that QML can handle this situation without any help.
I am currently trying to plot a large amount of items onto a QML Map (30,000 - 120,000 points). These items shall be updated dependent of the position of a QSlider. Performance decreases strongly from about 1,000 items upwards, when I use 30,000 it takes several minutes until the QML Map has all the data visualized and is responsive again. I have a machine which is absolutely capable of fulfilling this task in general, so I think the problem is QML. I am using Qt 5.8.
Is there any way to improve this performance or is it just not possible with a QML-map to plot so many MapItems at a time? I tried MapCircles, Polylines, Polygons and MapQuickItems with images, but for me it seems like the performance issue just arises from adding this amount of MapItems, as I could not see a significant difference in processing time between these types.
I have more data on the map visualized, which should not be refreshed every time the QSlider is moved. Even though I tried just to clear all MapItems and add the new ones for performance tests, but even this did not improve the performance.
My code (a bit abstracted) looks like this:
///-------------- Widget.cpp-----------------///
void ProcessInput(int qslider_pos) {
QVariantList lat_vec;
QVariantList lon_vec;
// Fill vectors with lateral and longitudinal positions
// ...
// Clean current points on map and draw new ones
SendToQmlFuncRemovePoints();
SendToQmlFuncAddPoints(lat_vec, lon_vec);
}
void QmlConnector::SendToQmlFuncRemovePoints()
{
QVariant returnedValue;
QMetaObject::invokeMethod(QmlMapSingleton::instance()->GetRoot(), "remove_points",
Q_RETURN_ARG(QVariant, returnedValue));
}
void QmlConnector::SendToQmlFuncAddPoints(QVariantList input_one, QVariantList input_two)
{
QVariant returnedValue;
QMetaObject::invokeMethod(QmlMapSingleton::instance()->GetRoot(), "add_points",
Q_RETURN_ARG(QVariant, returnedValue),
Q_ARG(QVariant, QVariant::fromValue(input_one)), Q_ARG(QVariant, QVariant::fromValue(input_two)));
}
.
///-------------- Map.qml -----------------///
Map {
anchors.fill: parent
property variant points: ({})
property int pointCounter: 0
Plugin
{
id: osmplugin
name: "osm"
PluginParameter { name: "osm.mapping.highdpi_tiles"; value: true }
}
Component.onCompleted: {
points = new Array();
}
id: map
plugin: osmplugin
//Javascript functions
function add_points(array_lat, array_lon) {
var myArray = new Array()
var component = Qt.createComponent("mapcircle.qml");
for (var i=0; i<array_lat.length; i++)
{
var object = component.createObject(map, { "center": QtPositioning.coordinate(array_lat[i], array_lon[i]})
map.addMapItem(object)
myArray.push(object)
}
map.points = myArray
}
function remove_points() {
var count = map.points.length
for (var i = 0; i<count; i++){
map.removeMapItem(map.points[i])
map.points[i].destroy()
}
map.points = []
}
}
.
///-------------- mapcircle.qml -----------------///
import QtQuick 2.0
import QtLocation 5.6
MapCircle {
radius: 1
border.width: 0
color: 'green'
}
Qt says that the performance decreases with the number of elements added to the map. Do you need all the points to be visible on the map in the same time, if not you can play around with visibility.
Can't you use QQuickPaintedItem to paint the points in C++ and wrap it into an MapQuickItem, if you have multiple polygonsfor e.g? But also there are some limitation, you cannot have to big images displayed.
If you need all the points maybe you can have different points based on the map zoom level and reduce the number of points added to the map at small zoom level, as was recommended on the other group ...

How can I get other layer in the same scene in cocos2d-x?

I have several layers in the scene, like TLayer,HLayer,TouchLayer. How can I get HLayer in HLayer? The solution I take is that I pass Layer to other Layer. However I met some problems recently. I push the Scene and pop Scene while TouchLayer still exists. So my problem is that is it right to pass HLayer to TouchLayer. Or is there a better way to do it in Cocos2d-x?
In the init() function in Scene:
this->setbackgroundLayer(BackgroundLayer::create());
CC_BREAK_IF(!backgroundLayer);
this->addChild(backgroundLayer);
this->setTLayer(TcharacterLayer::create(backgroundLayer->tianzige));
CC_BREAK_IF(!TLayer);
this->addChild(TLayer);
this->setHLayer(HcharacterLayer::create(testCharacter,backgroundLayer->tianzige_draw));
CC_BREAK_IF(!HLayer);
this->addChild(HLayer);
this->settouchLayer(TouchLayer::create(TLayer,HLayer));
CC_BREAK_IF(!touchLayer);
this->addChild(touchLayer);
I made my own create function:
TouchLayer* TouchLayer::create(TcharacterLayer* t,HcharacterLayer* h){
TouchLayer* pRet = new TouchLayer();
if (pRet && pRet->init(t,h))
{
pRet->autorelease();
return pRet;
}else
{
delete pRet;
pRet = NULL;
return NULL;
}
}
Here's how we've done this in the past. Define a set of tags for our layers.
typedef enum {
kBgLayerTag,
kHLayerTag,
kTLayerTag,
kTouchLayerTag
} MyLayerTags
Then while creating the layers set layer specific tags:
this->setTLayer(TcharacterLayer::create(backgroundLayer->tianzige));
CC_BREAK_IF(!TLayer);
TLayer->setTag(kTLayerTag);
this->addChild(TLayer);
And in TouchLayer access the TLayer and others like:
TcharacterLayer* myTLayer = this->getParent()->getChildByTag(kTLayerTag);
Sure, there is nothing wrong in adding a layer as a child. I would do that this way :
BackgroundLayer has all the necessary layers as children (remember to add TouchLayer as the last one and then pass Touch to others) and then you only add BackgroundLayer to your scene. There is even more simple way (probably better): to make BackgroundLayer inherit all the previous ones - but that depends on how much scenes you are going to make.
Edit:
1)
BackgroundLayer * bglayer = BackgroundLayer::create();
TcharacterLayer * tcharlayer = TcharacterLayer::create();
HcharacterLayer * hcharlayer = HcharacterLayer::create();
TouchLayer * tlayer = TouchLayer::create();
bglayer->addChild(tcharlayer);
bglayer->addChild(hcharlayer);
bglayer->addChild(tlayer);
this->addChild(bglayer);
(assuming this as a CCScene)
2)
class BackgroundLayer : public TcharacterLayer, HcharacterLayer, TouchLayer
{
...
}
In the first case you can give each layer a specific tag and then get the layer by getChildByTag(int tag) or just create fields in the BackgroundLayer class for each layer.

I can not change the name of my opacity.Its change.Its change?

Would anyone know how to change the name of the menu opacity to a name of my choice in Slice?
Thank's.
This can be done with the .name function of dat.gui.
gui.add(volume, 'opacity').name('Transparency');
That's a dat.gui question and not really related to XTK. Basically you have to create a wrapper object:
var settings = {
transparency: 1.0
}
transparency would be your new name.
Then, you define the controller using the settings object
var opacityController = lhgui.add(settings, 'transparency', 0, 1);
And in the callback, adjust the XTK opacity value:
opacityController.onChange(function() {
mesh.opacity = settings.transparency;
});