I want to create a 2D array of points that links to my 2D array of components - arrays

I am making a circuit diagram drawer for a school project and have a 2D array that stores whether 2 components are connected or not. I want to find a way to have an array that then stores the co-ordinates of these points so that if they are deleted, it can find the points and get rid of the connection
ElseIf P(1).X = Nothing And P(1).Y = Nothing Then
P(1).X = pointx
P(1).Y = pointy
Form1.Drawlines() 'run the DrawLines sub in Form1.vb
NoOfNodes = NoOfNodes + 1 'increment the NoOfNodes Variable by 1
Node2 = COMPONENTID
Connections(Node1, Node2) = true
This is the code that stores the points being drawn, at the end the value of Connections is set to true to show that there is a connection between the components.
I need a way to have another array that can say something along the lines of:
Connections(Node1,Node2) = (P(1),P(0))
any contribution is much appreciated,
Charlie

Sounds like each element in your array should point to an instance of a class. On the class you can pack as many attributes and as much information about the connection as you like.

Related

Visio VBA trying to get a list of containers and member shapes

Background: I have some code that runs through a Visio page and returns all the shapes. Many of these shapes are in containers, so I would like to know what container a shape belong to.
Original approach: I was hoping to retrieve the "parent" container of each shape (I only need one level of container, there are no containers within containers) using the Shape.ContainingShape property but that was only returning '0' for every shape.
If anyone has a solution for how I was originally trying to get the container, that would be the most elegant. But since I can't get that to work, I am trying the following alternative, which is also presenting a roadblock.
Current approach: I was able to get a list of all the containers on the page, and now I would like to pull the member shapes for each container. It's not as clean, but it would allow me to cross-reference the shapes and get the containers they belong to.
Issue: I am getting "Error 13 Type Mismatch" when trying to create an array with column 0 being the container name, and column 1 being the member shapes.
' Create array of containers and member shapes
Dim arr() As Long
Dim vsoMemberShape As Shape
Dim vsoContainerShape As Shape
Dim containerArr() As Long
Dim rows As Integer
Dim i As Integer
For Each ContainerID In vsoPage.GetContainers(visContainerIncludeNested)
Set vsoContainerShape = vsoPage.Shapes.ItemFromID(ContainerID)
arr = vsoContainerShape.ContainerProperties.GetMemberShapes(1)
rows = UBound(arr)
ReDim containerArr(0 To rows, 0 To 1)
For i = 0 To UBound(arr)
Set memberShape = vsoPage.Shapes.ItemFromID(arr(i))
containerArr(i, 0) = vsoContainerShape.NameU
containerArr(i, 1) = vsoMemberShape.NameU
Next
Next
' The following code is in a For loop, not shown
' shapeToName is what I want to compare to the member shapes in the container
' array defined above, and then retrieve the corresponding container
' This is where the error is popping up
shapeToName = CStr(vsoShapeTo.Name)
Dim x As Integer
x = Application.Match(shapeToName, Application.Index(containerArr, 0, 1), 0)
shapeContainer = containerArr(x, 1)
I think what you're looking for is Shape.MemberOfContainers, which returns an array of containers that a shape is a member of.
You can also have a look at this post which covers the same issue:
Visio: How to get the shapes that are contained in one shape?
I'll also throw in a link to a post by David Parker that covers containers in the context of cross-functional flowchart, which makes good use of Containers and Lists:
https://bvisual.net/2009/09/07/visio-2010-containment-and-cross-functional-flowcharts/

Is there a way to make an empty array and growing it as it gets data in vb.net?

I have been working on a project, and am attempting to make a new array for data. I have tried making an empty array with Dim Name() As String = {}. I am using a ListView, and the way I have done it there are blank spots where I have gotten rid of data. This is my current code:
Sub English(ByVal Country() As String, ByVal Language() As String)
rbDisplayallData.Checked = False
lstResults.Visible = True
lstResults.Items.Clear()
lstResults.Columns.Clear()
With lstResults
.View = View.Details
.Columns.Add("English Speaking Countries", 200, HorizontalAlignment.Left)
End With
For i = 0 To 181
Dim EnglishSpeakingCountries(i) As String
If Language(i) = "English" Then
EnglishSpeakingCountries(i) = Country(i)
End If
lstResults.Items.Add(New ListViewItem({EnglishSpeakingCountries(i)}))
Next
End Sub
I am trying to get rid of these spaces.
I Was thinking if I were to compact the array or make a new one with the same data going into a new array it would fix the issue.
If you have a solution please let me know.
There are two things that could be considered an empty array
An array with no elements, i.e. a Length of zero.
An array where every element is Nothing.
All arrays are fixed-length. Once you create an array with a particular number of elements, it always has that number of elements. You can use ReDim Preserve or Array.Resize but, in both those cases, what actually happens is that a new array is created and the elements copied from the old array. The new array is assigned to the same variable but anywhere the old array is referenced, it will still have that same number of elements. Try running this code to see that in action:
Dim a1 As String() = {}
Dim a2 As String() = {"First", "Second", "Third"}
Dim b1 = a1
Dim b2 = a2
Console.WriteLine(a1.Length)
Console.WriteLine(a2.Length)
Console.WriteLine(b1.Length)
Console.WriteLine(b2.Length)
Console.WriteLine()
ReDim Preserve a1(2)
Array.Resize(a2, 6)
Console.WriteLine(a1.Length)
Console.WriteLine(a2.Length)
Console.WriteLine(b1.Length)
Console.WriteLine(b2.Length)
Console.ReadLine()
Output:
0
3
0
3
3
6
0
3
As you'll be able to see, a1 and a2 end up referring to new arrays with the specified lengths but the original arrays with the original lengths still exist and are still accessible via b1 and b2.
If you start with an array with no elements then you can use ReDim Preserve or Array.Resize to give the appearance of resizing the array but that's not really what's happening and that should generally be avoided. If you know how many elements you'll end up with then you could create an array of that size and then set each element in turn. You'd need to keep track of the next element index though, so that's still a bit tedious.
Generally speaking, if you want an array-like data structure but you want it to be able to grow and shrink as required, you should use a collection. The most common collection is the List(Of T), where T is any type you care to specify in your code. If you want to store String objects then use a List(Of String). You can call Add to append a new item to the end of the list, as well as Insert, Remove and RemoveAt methods. You can also get or set an item by index, just as you can do for array elements.
Note that a List(Of T) actually uses an array internally and uses the aforementioned method of "resizing" that array. It optimises the process somewhat though, which makes the code easier for you to write and large collections more efficient to use.
It's worth noting that, in your own code, the Columns and Items properties of your ListView are both collections, although they are slightly different to the List(Of T) class.
Looking at your original code, this:
For i = 0 To 181
Dim EnglishSpeakingCountries(i) As String
If Language(i) = "English" Then
EnglishSpeakingCountries(i) = Country(i)
End If
lstResults.Items.Add(New ListViewItem({EnglishSpeakingCountries(i)}))
Next
could be changed to this:
Dim englishSpeakingCountries As New List(Of String)
For i = 0 To 181
If Language(i) = "English" Then
englishSpeakingCountries.Add(Country(i))
lstResults.Items.Add(Countries(i))
End If
Next
Note that you're just adding items to two collections. I guess the question is whether you actually need this extra collection at all. If you do want to use it later then you need to assign it to a member variable rather than a local variable. If you don't need it later then don't create it at all. As I said, you're already adding items to a collection in the ListView. Maybe that's all you need, but you haven't provided enough info for us to know.

Looping Through a Bitmap Array

Dim bmpNew As Bitmap = Nothing
Dim Bitmaps(15) As Bitmap
For b = 0 To Bitmaps.Count - 1
If Bitmaps.Contains(bmpNew) Then
Else
If Bitmaps(b) Is Nothing Then
If Bitmaps(b) Is bmpNew Then
Else
Bitmaps(b) = bmpNew
End If
Else
End If
End If
ListBox1.Items.Add(b)
Next
I am developing an application that generates random images every time the button is pressed. After generating the image, it loops through an array of bitmaps which are initially empty. What it should do is fill the array with every new image that it creates while making sure to not add it if it already exists in the array. I have tried many attempts and this method is the only one that actually makes sense and is very close to what I am trying to achieve, but it still produces duplicates in my array.
What am I missing?

AI help for Corona SDK

I've created a game which loops through a table of properties to create enemies to place on screen. The created enemies are stored in a variable called "baddie", and things like their x and y value are determined by the properties I gave them in the table. Currently, "baddie" creates 3 enemies at varying spots on screen. It looks something like this.
for i=1, #level[section]["enemies"] do
local object = level[section]["enemies"][i]
baddie = display.newSprite(baddieSheet, baddieData)
baddie.anchorX = 0.5
baddie.anchorY = 1
baddie.x = object["position"][1]; baddie.y = object["position"][2];
baddie.xScale = -1
baddie.myName = "Baddie"
baddie.health = 15
baddie:setSequence("standrt"); baddie:play()
physics.addBody(baddie, "dynamic", {radius=22, density=0.1, friction=10.0, bounce=0.0})
baddie.isFixedRotation = true
enemyGroup:insert(baddie)
end
I then inserted all of the created instances stored in the baddie variable, into a display group called "enemyGroup."
Now here's my question. I'm working on my game's AI and storing it all in an enterFrame listener. I want to make a "True/False" flag called "inRange." When the enemy's x position is within 20 pixels of the player's x, inRange = true. When it's true, the enemy will attack him. But I haven't figured out a way to make the inRange flag check for each individual enemy, instead of all of them.
I was thinking of something like,
for i = 1, enemyGroup.numChildren do
enemyGroup[i].widthBetween = enemyGroup[i].x - sprite.x
if enemyGroup[i].widthBetween <= 20 and enemyGroup[i].widthBetween >= -20 then
enemyGroup[i].inRange = true
else
enemyGroup[i].inRange = false
end
end
But the issue is, enemyGroup[i].inRange is a local value and I can't call for it in outside of the loop or in other functions. This is obviously problematic, because in another function I want to have each individual enemy punch, roll, jump, etc when their individual inRange property is true. Is there a way I can store enemyGroup[i].inRange so that I can call for it whenever?
Sorry if this question is confusing. It's been a struggle to word it.
I'm not sure why this isn't working for you. enemyGroup[i].inRange is not local, its an attribute of the object at enemyGroup[i]. It should be avalble anywhere you can access enemyGroup[i].
Personally I would have not used a display.newGroup() for this, instead I would have just created an array/table that's scoped for the whole scene.
local baddies = {}
then in your loop:
--enemyGroup:insert(baddie) instead of this, do this:
baddies[#baddies + 1] = baddie
Then you have a table that you can loop over, but it's really more code style than functionality. As long as your enemyGroup is scoped at a high enough level that any function that the scene can see.
you should create a file in the structure below:
module(..., package.seeall)
enemyGroup = {}
and in all your files where you want to use this table, first of all require this file( assume you named this file enemies.lua):
local enemiesArray = require "enemies"
-- somewhere in your code:
enemiesArray.enemyGroup[i].isRange = true -- or whatever you like to do
there is one better option for you to use _G variable. when you store an object to _G you can access that wherever you want( like the famous design pattern Singleton ). just set the variable one time and use it anywhere and as much as you want. for example:
-- in one file you set enemy table:
_G.enemies = enemyGroup
-- somewhere else in nowhere :)
print(_G.enemies.isRange)

Logical-Indexing for Matlab-object-arrays

Is there any way in Matlab R2011b to apply logical-indexing to object-arrays? The objects which fulfill specific condition(s) regarding their properties should be returned. At best the solution is also possible with object-arrays that are a property of another object (aggregation).
In my project there are a lot of entities which have to be identified by their manifold features. Matlab objects with their properties provide a clear data foundation for this purpose. The alternative of using structs (or cells) and arrays of indices seems to be too confusing. Unfortunately the access to the properties of objects is a little bit complicated.
For Example, all Objects in myArray with Element.val==3 should be returned:
elementsValIsThree = myElements(Element.val==3);
Best solution so far:
find([myElements.val]==3);
But this doesn't return the objects and not the absolute index if a subset of myElements is input.
Another attempt returns only the first Element and needs constant properties:
myElements(Element.val==3);
A minimal example with class definition etc. for clarification:
% element.m
classdef Element
properties
val
end
methods
function obj = Element(value)
if nargin > 0 % to allow empty construction
obj.val = value;
end
end
end
end
Create array of Element-Objects:
myElements(4) = Element(3)
Now myElements(4) has val=3.
I'm not sure I understood the question, but the logical index can be generated as
arrayfun(#(e) isequal(e.val,3), myElements);
So, to pick the elements of myElements whose val field equals 3:
elementsValIsThree = myElements(arrayfun(#(e) isequal(e.val,3), myElements));

Resources