I have a flashlite3 application with navigation consisting of icons the user can browse left or right through infinitely.
The basic algorithm i'm using now works (and is adequate for this project) however, part of the solution depends on a duplicate of the array of icons. Depending on the number of items in the array, and/or the size of the element contents, this solution could become less efficient. I'm interested in a solution or algorithm(in any language) that could achieve the same thing while being scalable & efficient.
Heres a portion of relevant code in the setter function for mutating the '_selectedItem' property, which:
Evaluates the current '_selectedItem' and the new '_value'
Based on step 1 pop,unshifts right, or shift,pops left
Repeats step 2 until the icon matching the '_selectedItem' is in the center of the array
This code runs using 3 arrays:
[static] Array of positions. There are 5 icons, 3 are visible at a time, so position 0 is off stage, position 1 is 1/3, position 2 is 1/2 ..
When instantiating the icons 2 arrays are created: _viewArray & _icons. The order of _viewArray mimics the order to be displayed and _icons is left alone and used for the loop condition checking
///Actionscript2///
public function set selectedItem(value:Number)
{
var w=Stage.width;
if(value > _icons.length-1)
{
value=0;
}else if(value < 0)
{
value=_icons.length-1;
}
if(value > _selectedIndex)
{
while(_viewArray[Math.floor(_icons.length*.5)] != _icons[value])
{
var element;
element=_viewArray.pop();
_viewArray.unshift(element);
}
}else if(value < _selectedIndex)
{
while(_viewArray[Math.floor(_icons.length*.5)]!=_icons[value])
{
var element;
element=_viewArray.shift();
_viewArray.push(element);
}
}
for(var i:Number=0;i<_viewArray.length;i++)
{
if(i>=1 && i<= _icons.length-2)
{
_viewArray[i]._visible=true;
}else
{
_viewArray[i]._visible=false;
}
Tweener.addTween(_viewArray[i],{_x:positions[i],_alpha:80,time:.5,transition:'elasticIn'})
}
Tweener.addTween(_icons[(_viewArray.length*.5)-1],{_alpha:100,time:.0,transition:'elasticIn'});
Tweener.addTween(_selectedServiceIndicator,{_alpha:0,time:.3,transition:'elasticIn',onComplete:function() {Tweener.addTween(this,{_alpha:100,time:.2,transition:'elasticIn'});}});
var eventObject:Object = {target:this, type:'SelectedItemChange'};
eventObject.value=value;
for(var key in _serviceData[value])
eventObject[key]=_serviceData[value][key];
dispatchEvent(eventObject);
_selectedIndex=value;
}
Why does each element of the _viewArray has to actually store the icon, rather than only the index into the _icons array? This way you only have the icons stored once, and _viewArray just stores their presentation order.
Related
I am using kotlin in combination with lwjgl. So far I had the following code that ran several thousand times per second:
// val textureMap = HashMap<Int, Texture>()
fun bind() {
var index = 0
for(entry in textureMap) {
glActiveTexture(GL_TEXTURE0 + index)
entry.value.bind()
program.setInt(entry.key, index)
++index
}
}
So while this was running absolutely fast and consumed virtually 0 of my frame time as expected I had to replace it because it created an Iterator in every call, eventually leading to tens of thousands of those objects eventually getting garbage collected and halting my program for a few milliseconds which is of course not usable in my application.
So I went ahead and changed it to the following code:
// textures = ArrayList<Texture>()
// indices = ArrayList<Int>()
fun bind() {
var index = 0
while(index < textures.size) {
val uniform = indices[index]
val texture = textures[index]
glActiveTexture(GL_TEXTURE0 + index)
texture.bind()
program.setInt(uniform, index)
++index
}
}
Now for some reason I am noticing a massive drop in performance, namely the function now uses several seconds per frame. Using jvisualvm I was able to determine that all that time is spent in glActiveTexture in the native part as well as the native function in program.setInt(...). I am absolutely stumped why this is the case, especially after comparing the byte code of the two.
This is the decompiled class file for the first (fast) version:
public final void bind()
{
int index = 0;
Map localMap = (Map)this.textureMap;
for (Map.Entry entry : localMap.entrySet())
{
GL13.glActiveTexture(33984 + index);
((Texture)entry.getValue()).bind(); Program
tmp66_63 = this.program;
if (tmp66_63 == null) {
Intrinsics.throwUninitializedPropertyAccessException("program");
}
tmp66_63.setInt(((Number)entry.getKey()).intValue(), index);
index++;
}
}
And that is the byte code of the slow version:
public final void bind()
{
int index = 0;
while (index < this.textures.size())
{
Integer uniform = (Integer)this.indices.get(index);
Texture texture = (Texture)this.textures.get(index);
GL13.glActiveTexture(33984 + index);
texture.bind(); Program
tmp52_49 = this.program;
if (tmp52_49 == null) {
Intrinsics.throwUninitializedPropertyAccessException("program");
}
Integer tmp62_61 = uniform;Intrinsics.checkExpressionValueIsNotNull(tmp62_61, "uniform");tmp52_49.setInt(tmp62_61.intValue(), index);
index++;
}
}
I am extremely confused what is going on here. In both versions the call to glActiveTexture is GL_TEXTURE0 + <an int value>, yet one takes so much more time thatn the other.
Does anyone have an idea what I am missing here?
Basically my entire question can be removed. I should have debugged and not only profiled. The problem was the code that populated the lists, and it didnt remove the old values so the lists grew larger and larger and the loop just ran so many more times over time...
In case anyone was wondering how I fixed my problem with the allocations I essentially created two collections, one is containing the uniforms and one is mapping them to textures. And then I can iterate over the uniforms and then get the respective texture. So no pointless Iterator objects are created but I am also not having any duplicates :)
I currently face the following problem:
I have 64 labels. Label_1 all the way up to Label_64.
I also have an int i.
"i" also goes from 1-64
I want that, when i == 1 Label_1 shall display an image. If i == 2, Label_2 shall display that image and so on.
Currently I'd do that with:
if(i == 1)
{
QPixmap pix("...");
ui->label_1->setPixmap(pix);
}
if(i == 2)
{
QPixmap pix("...");
ui->label_2->setPixmap(pix);
}
if(i == 3)
{
QPixmap pix("...");
ui->label_3->setPixmap(pix);
}
...
Is there some way to do that easier? Something like:
QPixmap pix("...");
ui->label_i->setPixmap(pix);
where the choosen label is directly defined by i?
You can store a list of QLabels.
QList<QLabel*> labels;
labels.at(i)->setPixmap(pix)
The disadvantage of this method is that you should manually assign ui->label_i to labels.at(i) for every i from 1 to 64 once:
labels.insert(0, NULL); // empty space to keep numbering the same.
labels.insert(1, ui->labels_1);
labels.insert(2, ui->labels_2);
...
labels.insert(64, ui->labels_64);
Depending on your specific case, you may use a more tricky solution. For example, if all the labels are stored in a QVBoxLayout at position 1 to 64, you can access label i as follows:
QVBoxLayout *layout = ...;
QLabel *label = qobject_cast<QWidget*> (layout->itemAt(i)->widget ());
if (label) // should be true if assumption is correct
label->setPixmap(pix);
You can also use method two to initialise the list of method 1.
See the Qt documentation for more information.
I'm an Italian student and I'm new in programming. I need your help for a school project.
I'm making a blob tracking program using Daniel Shiffman's tutorials. Currently I have 2 blobs on the screen. I am identifying them with 2 IDs: number 0 and number 1.
I need to put some conditions on those blobs: if one blob is in a certain part of the screen and the other one is in another part, I need to call a function.
I don't know how to put the if conditions separately for the two ids. Below is some pseudo code of what I would like to achieve:
for (id==0)
if (...) and
for (id==1)
if(...) then {
void()
}
I would really appreciate any help!
I don't really know where you want the blobs to be when the desired function fires, but I can try to give you an example...
Blob
Assign some sort of position variable, in this case PVector, to your blob object.
class Blob {
PVector position;
Blob (PVector position) {
this.position = position;
}
void update() {
*random movements, etc...*
}
}
Create two blob objects
Create two objects and assign a position to each of them.
Blob[] blobs = new Blob[2];
void setup() {
size(400, 400);
blobs[0] = new Blob(5, new PVector(40, 40));
blobs[1] = new Blob(13, new PVector(100, 100));
}
Check if blobs is at left or right side of the screen
I check if blob[0] is at the left side of the screen and if blob[1] is at right side of the screen. If they are, at the same time, the desiredFunction(); will fire.
void draw() {
for (int i = 0; i < blobs.length; i++) {
blobs.update();
}
if (blobs[0].position.x < (width / 2) && blobs[1].position.x < (width / 2) {
desiredFunction();
}
}
Remember
This is just an example. You could of course check other parts of the screen instead of the left and right parts. You can also use IDs on your blobs instead of an array, I just thought it was better to just use an array in this case.
PS: I wrote this answer without having processing started. The code has certainly a couple of typing errors.
For the example you have described, you can achieve this using the && operator in one if statement.
First assign the conditions you want to test to boolean variables. For example, create the boolean variables id0IsThere, and id1IsThere, and set them to true if the blobs are in the locations you want them to be in. Then use the following if statement:
if (id0IsThere && id1IsThere) {
yourFunction();
}
The && operator means that the code inside the if statement that executes yourFunction() is only executed if both conditions are true. In this case, if both blobs are in the positions you want them to be in. Hope that helps. Read more about if statements and the && operator here:
https://processing.org/reference/if.html
https://processing.org/reference/logicalAND.html
I'm working on a GUI that displays a list of elements.
All the elements are in a one dimensional iterable array, so displaying them would normally look something like this:
foreach (Element e: elements) {
display.Display(e);
}
I now need a way to organize the elements in a tree structure like in this example:
In my system, there is no distinction between "folder" elements and "file" elements, but I can access an element's 'depth' and 'isExpanded' values.
How can I determine whether an element should be displayed based on data taken from iterating through previous elements?
I think I've figured it out, but there may be some cases that mess it up:
bool prevIsCollapsed = false;
int collapsedPropertyDepth = 0;
// iterate through each property of this component
for (Property p : properties)
{
int depth = property.depth;
if (prevIsCollapsed && depth > collapsedPropertyDepth)
{
// dont display this property
continue;
}
if (!property.isExpanded)
{
prevIsCollapsed = true;
collapsedPropertyDepth = depth;
}
else
{
prevIsCollapsed = false;
}
}
I am trying to learn LINQ but it is quite confusing at first!
I have a collection of items that have a color property (MyColor). I have another collection of all colors (called AvailableColors - lets say 10 for example).
I want to get a random color from the AvailableColors that does not already exist in my collection.
My current C# code just gets a random color but I would like to rewrite this in LINQ to take in the current color collection and exclude those from the possible options:
public MyColor GetRandomColour()
{
return AvailableColors[new Random().Next(0, AvailableColors.Count)];
}
so it would take in the existing collection:
public MyColor GetRandomColour(ListOfSomethingWithColorProperty)
Thanks for any pointers!
Excluding already-used colors implies saving of state. You might be better off writing an iterator and using yield return to return the next random color in the sequence. This allows you to "remember" which colors have already been used.
Once you have that, you can call it using Take(1) from Linq, if you wish.
// assumes Random object is available, preferrably a re-used instance
Color color = AvailableColors
.Except(myItems.Select(item => item.Color).Distinct())
.OrderBy(c => random.Next())
.FirstOrDefault();
Probably not terribly efficient, but also probably not a concern given a small number of items.
Another approach is to randomly order the available colors once beforehand, therefore you can go in order. Use a List<Color> so you can remove elements as you use them, or save the current index with each pull. Once the list is depleted or the index exceeds the length of the array, notify your user that you're all out of colors.
var rnd = new Random(); // don't keep recreating a Random object.
public MyColor GetRandomColour(List<Something> coll)
{
var len = rnd.Next(0, AvailableColors.Count- coll.Count);
return AvailableColors.Except(coll.Select(s=>s.MyColor)).Skip(len).First();
}
I'm going to suggest that you be Linq-minded and create a good, general purpose IEnumerable<T> extension method that does the heavy lifting you require and then your GetRandomColor functions are simpler and you can use the extension method for other similar tasks.
So, first, define this extension method:
public static IEnumerable<T> SelectRandom<T>(this IEnumerable<T> #this, int take)
{
if (#this == null)
{
return null;
}
var count = #this.Count();
if (count == 0)
{
return Enumerable.Empty<T>();
}
var rnd = new Random();
return from _ in Enumerable.Range(0, take)
let index = rnd.Next(0, count)
select #this.ElementAt(index);
}
This function allows you to select zero or more randomly chosen elements from any IEnumerable<T>.
Now your GetRandomColor functions are as follows:
public static MyColor GetRandomColour()
{
return AvailableColors.SelectRandom(1).First();
}
public static MyColor GetRandomColour(IEnumerable<MyColor> except)
{
return AvailableColors.Except(except).SelectRandom(1).First();
}
The second function accepts an IEnumerable<MyColor> to exclude from your available colors so to call this function you need to select the MyColor property from your collection of items. Since you did not specify the type of this collection I felt it was better to use IEnumerable<MyColor> rather than to make up a type or to define an unnecessary interface.
So, the calling code looks like this now:
var myRandomColor = GetRandomColour(collectionOfItems.Select(o => o.MyColor));
Alternatively, you could just directly rely on Linq and the newly created extension method and do this:
var myRandomColor =
AvailableColors
.Except(collectionOfItems.Select(o => o.MyColor))
.SelectRandom(1)
.First();
This alternative is more readable and understandable and will aid maintainability of your code. Enjoy.
There's a nifty way to select a random element from a sequence. Here it's implemented as an extention method:
public static T Random<T>(this IEnumerable<T> enumerable)
{
var rng = new Random(Guid.NewGuid().GetHashCode());
int totalCount = 0;
T selected = default(T);
foreach (var data in enumerable)
{
int r = rng.Next(totalCount + 1);
if (r >= totalCount)
selected = data;
totalCount++;
}
return selected;
}
This method uses the fact that probability to choose n-th element over m-th when iterating is 1/n.
With this method, you can select your colour in one line:
var color = AvailableColors.Except(UsedColors).Random();