Resetting List to new quantity of objects - c#

I'm having a problem with an accumulation of Point3ds in List. When I change the number of int agents (via a gui slider in grasshopper) the quantity keeps increasing rather than resetting to whatever the new quantity should be. I'm guessing that somewhere I should be re-initializing the list or clearing it everytime the value is changed? What would be the correct to do this?
protected override void SolveInstance(IGH_DataAccess DA)
{
BoundingBox box = new BoundingBox(0.0, 0.0, 0.0, boundx, boundy, boundz);
DA.SetData("Bounding Box", box);
DA.SetData("Start", "The current trigger is set to " + started.ToString());
// Initialize Agents
for (int i = 0; i < agents; i++)
{
double xPos = RandomfromDouble(0.0, boundx);
double yPos = RandomfromDouble(0.0, boundy);
double zPos = RandomfromDouble(0.0, boundz);
Point3d pos = new Point3d(xPos, yPos, zPos); // Create Agent Start Position
Vector3d vec = new Vector3d(xPos + RandomfromDouble(-360.00, 360.00), yPos + RandomfromDouble(-360.00, 360.00), zPos + RandomfromDouble(-360.00, 360.00)); // Create Agent Start Vector
Agent agent = new Agent(pos, vec, alignment, separation, cohesion, neighborRadius);
allAgents.Add(agent);
DA.SetData("Debug", "# of Agents Created: " + allAgents.Count);
}
// Get agent positions
List<Point3d> agentPositions = new List<Point3d>();
List<Vector3d> agentVectors = new List<Vector3d>();
agentPositions = allAgents.Select(agent => agent.Pos).ToList();
agentVectors = allAgents.Select(agent => agent.Vec).ToList();
DA.SetData("Agent Count", allAgents.Count);
DA.SetDataList("Agent Points", agentPositions);
DA.SetDataList("Agent Vectors", agentVectors);
if (started)
{
DA.SetData("Start", "The current trigger is set to " + started.ToString());
for (int i = 0; i < generations; i++)
{
DA.SetData("Debug", "# of Generations: " + i);
foreach (Agent agent in allAgents)
{
DA.SetData("Debug", "# of Agents: " + i);
agent.UpdateAgent(allAgents);
}
}
}
else if (!started)
{
DA.SetData("Start", "The current trigger is set to " + started.ToString());
//return;
}
}
public double RandomfromDouble(double from, double to)
{
double diff = Math.Abs(from - to);
return rnd.NextDouble() * diff + from ;
}

If I'm reading your code correctly, your issue is that the allAgents list keeps getting longer. As you guessed, that's because you're creating the list once, at the top, and then you only ever add to it, within the for loop that says // Initialize Agents.
If your intent is to reset the list at this point, then before you enter the for loop I think you need to do allAgents.Clear(). This will empty the list, and then you loop through and add the new Agents within the loop.

Related

Ui button doesn't move correctly

I have a code for a crafting system that checks if the inventory has the ingredients needed to craft an item and adds a button to craft it. The problem is when I want to position my button it goes way off the canvas. I have seen some people saying that it has something to do with rect transform. I've been stuck with it for over an hour. Any help is appreciated.
I have tried
removing the setparent() function,
using anchoredPosition,
using localPosition
My code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Crafting : MonoBehaviour
{
public List<recipe> recipes = new List<recipe>();
public GameObject base_item, parent;
List<GameObject> items = new List<GameObject>();
public int y = 75;
public int x = -45;
public Inv inv;
private void Start()
{
inv = GetComponent<Inv>();
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.Tab))
{
checkitems();
Debug.Log("y = " + y + " x = " + (x - 40));
}
}
public void checkitems()
{
for (int i = 0; i < recipes.Count; i++)
{
recipe r = recipes[i];
for (int x = 0; x < r.ingredients.Count; x++)
{
if (!inv.hasitem(r.ingredients[x])){
return;
}
}
showitem(r.result);
}
}
public void onClick(int _slot)
{
recipe r = recipes[_slot];
for (int i = 0; i < r.ingredients.Count; i++)
{
inv.removeitem(inv.getitem(r.ingredients[i]));
}
inv.additem(inv.getFirstAvailable(), r.result, r.stack);
}
public void showitem(string name)
{
GameObject obj = Instantiate(base_item);
if (items.Count != 0)
{
if (((items.Count) % 3) != 0)
{
Debug.Log("first thing");
obj.GetComponent<RectTransform>().position = new Vector2(x, y);
obj.transform.SetParent(parent.transform);
obj.SetActive(true);
items.Add(obj);
x = x + 40;
Debug.Log("x + 40");
}
else if (((items.Count + 1) % 3) == 0)
{
Debug.Log("second thing");
x = -45;
Debug.Log("x + 40");
y = y + 40;
Debug.Log(" y + 40");
obj.GetComponent<RectTransform>().position = new Vector2(x, y);
obj.transform.SetParent(parent.transform);
obj.SetActive(true);
items.Add(obj);
}
}else
{
obj.GetComponent<RectTransform>().position = new Vector2(x, y);
obj.transform.SetParent(parent.transform);
obj.SetActive(true);
items.Add(obj);
x = x + 40;
Debug.Log("x + 40");
}
}
}
Blue circle where it spawns. Red circle where I want it to be
Seems you are confusing a bunch of terms for being the issue of your problem. Firstly I want to address the red X over your scroll bar. Whenever this occurs, it means that your RectTransform of this UI object has been dragged from its positive vertices to negative or vice versa, causing it to almost invert. I would correct this but it is not the reason your objects are not childing correctly.
Generally, with UI objects, I would never use LocalPosition, just AnchoredPosition. LocalPosition is a field from Transform which I believe RectTransform inherits from. As RectTransforms have a lot of modifications to their position from pivots, anchors, and anchored positions, the LocalPosition will most likely need to recalculate data to properly move the object, whereas AnchoredPosition has already done these calculations.
I believe the issue with your current code is how you are using SetParent. There is a second parameter of SetParent which governs whether the object keeps the same position based in world space after being childed. As you are not passing in a new bool for this parameter, it is defaulting to true. As you want your objects to be childed to the parent but not keep their world space positions, you would want to pass in false.
In your case, as it looks as if you want to set objects in a grid-like pattern childed to this ScrollRect, I would attach a GridLayoutGroup to the Content of your scroll and child the new objects to this object. You can set the max columns of this grid and spacing to give the same layout you are attempting to achieve in code.
To summarize, I would remove all the hand placement you are doing in code with LocalPosition and AnchorPosition and just attach a GridLayoutGroup. To fix the current positioning of your objects relative to the parent, change all lines of obj.transform.SetParent(parent.transform); to obj.transform.SetParent(parent.transform, false);. If you want to keep changing position locally in code instead of a layout element, use SetParent first, and use AnchoredPosition instead of LocalPosition as the SetParent with false passed in will override the position you set.

Converting between coordinate systems causing rotation/gimbal issues! Need assistance

I am trying to write a .bvh animation exporter for c# and am using this export_bvh.py script from Blender as an example to copy.
My Unity exporter script basically stores the bone's rotations every frame when the scene is active. After the scene stops it then saves that list of euler rotations to the .bvh file.
I have managed to get the header part of the file looking ok, but I am now having trouble calculating the angles for the bones.
From my understanding, they are the compound angles by multiplying the parent's global transform matrix by the child's transform matrix and a rest position matrix. But the details are not very clear to me.
So I have done my best to examine and copy the way the matrices are multiplied in the export_bvh.py script, and even though I feel I have made some progress, I still face an issue which has been present from the very start, after importing my recorded animations, the rotations are sometimes way off and sometimes not. Which I believe (but am not certain) is due to Blender being right-handed and Unity being left-handed coordinate systems.
For example, when I start the Unity scene and begin to record the animation, I then move some of the bones in my armature (which gets recorded), then after saving the animation I go to try importing the .bvh into Blender. After inspecting the animation I notice that when a bone was rotated along multiple axes it will have strange results in the animation and some of the rotations either snap around or appear to wobble violently. But usually when rotating along a single axes it appears to move in the correct direction.
I have created this video which explains the issue better and shows some examples:
MORE DETAILS on YouTube
Here is the complete script for this project:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SimpleBVH5 : MonoBehaviour {
string bvhOutput;
public string savePath = "C:\\animations\\animation.bvh";
public int fps = 60;
Quaternion rootRotationOffset;
//ARMATURE BONES SECTION
public Transform hip;
public Transform spine;
public Transform chest;
public Transform shoulderR;
public Transform upper_armR;
public class DecoratedBone {
public Transform bone;
public DecoratedBone parent; // decorated bone parent, set in a later loop
public Vector3 rest_bone_head; // blender armature bone head position
public Matrix4x4 rest_arm_mat; // blender rest matrix (armature space)
public Matrix4x4 rest_arm_imat; // rest_arm_mat inverted
}
List<DecoratedBone> dBones;
//INITIALIZATION SECTION
void OnEnable () {
dBones = new List<DecoratedBone> ();
rootRotationOffset = hip.rotation;
int level = 0;
bvhOutput = "HIERARCHY\n";
bvhOutput += "ROOT hip\n";
var dBone = new DecoratedBone ();
dBone.bone = hip;
dBone.rest_bone_head = hip.position;
var rest_arm_mat = GetMatrix (dBone, rootRotationOffset);
dBone.rest_arm_mat = rest_arm_mat;
dBone.rest_arm_imat = rest_arm_mat.inverse;
dBones.Add (dBone);
bvhOutput += "{\n";
var offset = hip.position;
bvhOutput += "\tOFFSET " + offset.x.ToString("F6") + " " + (-offset).z.ToString("F6") + " " + offset.y.ToString("F6") + "\n";
bvhOutput += "\tCHANNELS 6 Xposition Yposition Zposition Xrotation Yrotation Zrotation\n";
var spineBone = InsertHierarchy (ref level, "spine", spine, dBone);
InsertHierarchy (ref level, "chest", chest, spineBone);
AscendLevel (ref level, chest, chest.GetChild (0), 1);
var shoulderRBone = InsertHierarchy (ref level, "shoulder.R", shoulderR, spineBone);
InsertHierarchy (ref level, "upper_arm.R", upper_armR, shoulderRBone);
AscendLevel (ref level, upper_armR, upper_armR.GetChild (0));
bvhOutput += "}\n";
bvhOutput += "MOTION\n";
bvhOutput += "Frames: 1\n";
bvhOutput += "Frame Time:\t" + (1.0f / fps).ToString("F6") + "\n";
StartCoroutine (RecordRoutine ()); // Finished building header info, Begin recording keyframes
}
void OnDestroy() {
System.IO.File.WriteAllText(savePath, bvhOutput);
print ("SAVED FILE!!!");
}
// HEADER SECTION HELPERS
DecoratedBone InsertHierarchy(ref int level, string name, Transform bone, DecoratedBone parent) {
/* Creats hierarchy header info for bones with parents */
string tabs = GetLevelTabs(level);
bvhOutput += tabs + "JOINT "+name+"\n";
bvhOutput += tabs + "{\n";
var dBone = new DecoratedBone ();
dBone.bone = bone;
dBone.parent = parent;
dBone.rest_bone_head = bone.position;
var rest_arm_mat = GetMatrix (dBone, rootRotationOffset);
dBone.rest_arm_mat = rest_arm_mat;
dBone.rest_arm_imat = rest_arm_mat.inverse;
dBones.Add (dBone); // Add bone to the list of bones (in the order it was created in the hiereachy/header).
var offset = bone.position - parent.bone.position;
bvhOutput += tabs + "\tOFFSET " + offset.x.ToString("F6") + " " + (-offset).z.ToString("F6") + " " + offset.y.ToString("F6") + "\n";
bvhOutput += tabs + "\tCHANNELS 3 Xrotation Yrotation Zrotation\n";
level++; // Increase the level in the hierarchy (increases depth in .bvh file and ensures curly braces will be added properly)
Debug.DrawLine (parent.bone.position, bone.position, Color.cyan, 10.0f); // Outline the skeleton in the viewport for debugging
return dBone;
}
string GetLevelTabs(int level) {
string tabs = "";
for (int lev = 0; lev <= level; lev++) {
tabs += "\t";
}
return tabs;
}
void EndSite(int level, Transform bone, Transform endEffector) {
string tabs = GetLevelTabs(level);
bvhOutput += tabs + "End Site\n";
bvhOutput += tabs + "{\n";
var offset = endEffector.position - bone.position;
bvhOutput += tabs + "\tOFFSET " + offset.x.ToString("F6") + " " + (-offset).z.ToString("F6") + " " + offset.y.ToString("F6") + "\n"; // 1 0 0\n";
bvhOutput += tabs + "}\n";
Debug.DrawRay (bone.position, offset, Color.cyan, 10.0f);
}
void AscendLevel (ref int level, Transform bone, Transform endEffector, int stopLevel = 0) {
EndSite (level, bone, endEffector);
for (int lev = level; lev > stopLevel; lev--) {
for (int tab = 0; tab < lev; tab++) {
bvhOutput += "\t";
}
bvhOutput += "}\n";
}
level = stopLevel;
}
//RECORDED MOTION SECTION
IEnumerator RecordRoutine () {
/*A simplified re-write of Blender's export_bvh.py script https://github.com/sftd/blender-addons/blob/master/io_anim_bvh/export_bvh.py*/
string line; // The string used to build each line of data.
float time = Time.time;
float interval = 1.0f / fps; // The record frame interval.
while (isActiveAndEnabled) { // Runs while the scene is actively running.
yield return new WaitUntil (() => (Time.time - time) >= interval); // Wait for desired time interval.
time = Time.time; // Reset the timer.
yield return new WaitForEndOfFrame (); // Wait for all transforms to be updated.
line = ""; // Clear the line data and prepare for next line of data.
//First do calculations for the root (hip) bone.
var p = dBones[0].rest_bone_head;
var trans = Matrix4x4.Translate (p);
var itrans = Matrix4x4.Translate (-p);
var pose_mat = GetMatrix(dBones [0], rootRotationOffset);
var rest_arm_imat = dBones [0].rest_arm_imat;
var mat_final = pose_mat * rest_arm_imat;
mat_final = itrans * mat_final * trans;
var loc = mat_final.GetPosition () ;
var rot = mat_final.GetRotation ().eulerAngles;
line += // Add root's (hip bone) data to the line of data.
(-loc.x).ToString("F6") + " " + //Output location of root bone
(-loc.z).ToString("F6") + " " +
(loc.y).ToString("F6") + " " +
(rot.x).ToString("F6") + " " + //Output rotation of root bone
(rot.z).ToString("F6") + " " +
(-rot.y).ToString("F6") + " ";
// Now do calculations for each child bone
for (int i = 1; i < dBones.Count; i++) {
p = dBones [i].rest_bone_head;
trans = Matrix4x4.Translate (p);
itrans = Matrix4x4.Translate (-p);
mat_final =
dBones [i].parent.rest_arm_mat * GetMatrix(dBones [i].parent).inverse *
GetMatrix(dBones [i]) * dBones [i].rest_arm_imat;
mat_final = itrans * mat_final * trans;
//loc = mat_final.GetPosition () + (trackedObjects [i].rest_bone_head - trackedObjects [i].parent.rest_bone_head); //Position is not required for non-root bones
rot = mat_final.GetRotation ().eulerAngles;
line += // Add children's data to the line of data.
(rot.x).ToString("F6") + " " + //Output rotation of child bone
(rot.z).ToString("F6") + " " +
(-rot.y).ToString("F6") + " ";
}
line += "\n"; // Done adding line.
if (Application.isPlaying) {
bvhOutput += line; // Add the data to the file's contents only if the scene is actively running.
}
}
}
Matrix4x4 GetMatrix (DecoratedBone dBone, Quaternion offsetRotation = default(Quaternion)) {
//return trackedObject.obj.localToWorldMatrix;
return Matrix4x4.TRS(
dBone.bone.position,
offsetRotation.Equals(default(Quaternion)) ? dBone.bone.rotation : dBone.bone.rotation * offsetRotation, //the offsetRotation (aka hip.rotation) should be applied to all bones with parents.
Vector3.one
);
}
}
Thanks for anyone who can help!

When calculating the space for each direction when the grid size is multiply by 1.5 the directions are wrong why?

If the grid is 10x10 or 23x7 it's working fine but when the grid have 1.5 spaces between the cubes the directions sometimes are wrong.
This is the grid script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GridGenerator : MonoBehaviour
{
public GameObject gridBlock;
public int gridWidth = 10;
public int gridHeight = 10;
public GameObject[] allBlocks;
private GameObject[] wallsParents = new GameObject[4];
void Start()
{
wallsParents[0] = GameObject.Find("Top Wall");
wallsParents[1] = GameObject.Find("Left Wall");
wallsParents[2] = GameObject.Find("Right Wall");
wallsParents[3] = GameObject.Find("Bottom Wall");
GenerateGrid();
allBlocks = GameObject.FindGameObjectsWithTag("Blocks");
var findpath = GetComponent<PathFinder>();
findpath.FindPath();
}
public void AutoGenerateGrid()
{
allBlocks = GameObject.FindGameObjectsWithTag("Blocks");
for (int i = 0; i < allBlocks.Length; i++)
{
DestroyImmediate(allBlocks[i]);
}
var end = GameObject.FindGameObjectWithTag("End");
DestroyImmediate(end);
GenerateGrid();
allBlocks = GameObject.FindGameObjectsWithTag("Blocks");
var findpath = GetComponent<PathFinder>();
findpath.FindPath();
}
public void GenerateGrid()
{
for (int x = 0; x < gridWidth; x++)
{
for (int z = 0; z < gridHeight; z++)
{
GameObject block = Instantiate(gridBlock, Vector3.zero, gridBlock.transform.rotation) as GameObject;
block.transform.parent = transform;
block.transform.name = "Block";
block.transform.tag = "Blocks";
block.transform.localPosition = new Vector3(x * 1.5f, 0, z * 1.5f);
block.GetComponent<Renderer>().material.color = new Color(241, 255, 0, 255);
if (x == 0)//TOP
{
block.transform.parent = wallsParents[0].transform;
block.transform.name = "TopWall";
block.transform.tag = "Blocks";
}
else if (z == 0)//LEFT
{
block.transform.parent = wallsParents[1].transform;
block.transform.name = "LeftWall";
block.transform.tag = "Blocks";
}
else if (z == gridHeight - 1)//RIGHT
{
block.transform.parent = wallsParents[2].transform;
block.transform.name = "RightWall";
block.transform.tag = "Blocks";
}
else if (x == gridWidth - 1)//BOTTOM
{
block.transform.parent = wallsParents[3].transform;
block.transform.name = "BottomWall";
block.transform.tag = "Blocks";
}
}
}
}
}
On this line i'm adding the spaces between the cubes:
block.transform.localPosition = new Vector3(x * 1.5f, 0, z * 1.5f);
Then in another script i'm trying to find what directions next are possible to move to.
private void Directions()
{
GridGenerator gridgenerator = GetComponent<GridGenerator>();
Vector3 playerPosition;
playerPosition = player.localPosition;
if (playerPosition.x > 0)
{
// can go left
possibleDirections[0] = "Can go left";
}
else
{
possibleDirections[0] = "Can't go left";
}
if (playerPosition.x + 1 < gridgenerator.gridWidth * 1.5f)
{
// can go right
possibleDirections[1] = "Can go right";
}
else
{
possibleDirections[1] = "Can't go right";
}
if (playerPosition.z > 0)
{
// can go backward
possibleDirections[2] = "Can go backward";
}
else
{
possibleDirections[2] = "Can't go backward";
}
if (playerPosition.z + 1 < gridgenerator.gridHeight * 1.5f)
{
// can go backward
possibleDirections[3] = "Can go forward";
}
else
{
possibleDirections[3] = "Can't go forward";
}
}
possibleDirections is array string type
When the grid size is 10x10 without spaces between cubes this two lines:
if (playerPosition.x + 1 < gridgenerator.gridWidth * 1.5f)
if (playerPosition.z + 1 < gridgenerator.gridHeight * 1.5f)
Was:
if (playerPosition.x + 1 < gridgenerator.gridWidth)
if (playerPosition.z + 1 < gridgenerator.gridHeight)
But when i added the spaces between the cubes i tried to add to the gridgenerator.gridWidth and gridgenerator.gridHeight the * 1.5
But it didn't work so i tried also:
if (playerPosition.x + 1 < gridgenerator.gridWidth * (1 + 1.5))
if (playerPosition.z + 1 < gridgenerator.gridHeight * (1 + 1.5))
1 is the cube width and 1.5 is the space. But this is not working good either.
In the screenshot the player is in the top left corner facing up(forward)
He can't move forward but in the inspector it says "Can go forward" And should be "Can't go forward"
It only happens when there are spaces between the cubes.
This line is wrong:
if (playerPosition.x + 1 < gridgenerator.gridWidth * 1.5f)
Your gridWidth variable stores the number of cubes, not their collective spacing. You have 10 cubes representing move spaces, determining the out-of-bounds this value should remain constant (it's still only 10 cubes, even if they're spaced with a half-block worth of space between them).
You need to convert from the player's scene location (transform.position.x) to a board space location (likely dividing by the same multiplier used to space the cubes out).
Alternatively, the "this makes my soul cry" solution of doing this:
if (playerPosition.x + 1.5f < gridgenerator.gridWidth * 1.5f)
Because the next cube is 1.5 scene units away, not 1. And this makes my soul cry because it makes your code full of hard-coded 1.5f multipliers and offsets rather than keeping such things to a single, fixed, constant value stored Elsewhere and used sparingly.
Related:
possibleDirections[0] = "Can go left";
Why are you using stringly typed things? There are values called booleans for a reason...

Object transform.localScale not changing

I am adding some objects in the game but for same reason, the first object I add from a generic list do not change in localScale.
As you can see from the image below, the console displays that localScale is correct, but when you look at the gameview and inspector, the object has a Vector.zero localScale. What's weird is that all the other properties of the object is correct (i.e. object.name is correctly name 3, 7).
The objects after the first are all displayed correctly as well.
Update: If I don't use Queue<GameObject> tile = new Queue<GameObject>(), things work normally..
Here's the script:
public void animateGrid(List<int[]> matchTile, List<int[]> moveTile, List<int[]> appendTile){
animating = true;
Queue<GameObject> tile = new Queue<GameObject>();
Debug.Log ("MatchTile count: " + matchTile.Count);
Debug.Log ("AddTile count: " + appendTile.Count);
foreach(int[] i in matchTile){
tile.Enqueue(getGameObject(i[0], i[1]));
match (tile.Peek());
}
Debug.Log ("tile: " + tile.Count);
foreach(int[] j in appendTile){
int x1 = j[0], y1 = j[1],
x2 = j[2], y2 = j[3];
GameObject gameObj = tile.Dequeue();
Debug.Log ("tileNo");
append ( gameObj,
getCoordinateFromGrid(x2, y2),
x2, y2,
grid.filled[x1, y1]
);
}
...
}
private void match(GameObject tile){
Hashtable optional = new Hashtable();
optional.Add("ease", LeanTweenType.easeInBounce);
LeanTween.scale(tile, Vector3.zero, 0.05f, optional);
tile.SetActive(false);
}
private void append(GameObject tile, Vector3 position, int x, int y, int type){
float tileSize = 1f / 9f;
tile.renderer.material.color = getColor(type);
tile.tag = getType(type);
tile.name = x + "," + y;
tile.transform.parent = transform.FindChild("Filled").transform;
tile.transform.position = position;
tile.transform.localScale = new Vector3(tileSize, tileSize, 70f);
tile.SetActive(true);
Debug.Log ("added scale: " + tile.transform.localScale + " x:" + x + " y:" + y);
}
If I don't use Queue tile = new Queue(), things work normally. I think its a bug.

Finding What point the mouse is over going too slow

Ok, so right now when i click on the grid it goes through all the 'paths' on the grid and checks if they're an ellipse and if the mouse is over them, and if there's 2 selected it calculated the distance apart.... but if i get 50+ points on the grid, clicking on a point does nothing.... Is there any more efficient way of doing this ?
Here's my code:
foreach (var x in GraphPanel.Children)
{
try
{
if (((Path)x).IsMouseOver && ((Path)x).Data.ToString() == "System.Windows.Media.EllipseGeometry")
{
listViewPoints.SelectedItems.Add(listViewPoints.Items[PointIndex]);
var converter = new System.Windows.Media.BrushConverter();
var brush = (System.Windows.Media.Brush)converter.ConvertFromString("#FFB1D100");
((Path)x).Stroke = brush;
((Path)x).StrokeThickness = 8;
if (listViewPoints.SelectedItems.Count == 2)
{
double diffX;
double diffY;
double ptAX = ((Points)listViewPoints.SelectedItems[0]).A;
double ptAY = ((Points)listViewPoints.SelectedItems[0]).B;
double ptBX = ((Points)listViewPoints.SelectedItems[1]).A;
double ptBY = ((Points)listViewPoints.SelectedItems[1]).B;
if (ptAX > ptBX)
{
diffX = ptAX - ptBX;
}
else
{
diffX = ptBX - ptAX;
}
if (ptAY > ptBY)
{
diffY = ptAY - ptBY;
}
else
{
diffY = ptBY - ptAY;
}
//the distance between the points = sqr/-diff in x squared + diff in y squared
double result = Math.Sqrt(Math.Pow(diffX,2) + Math.Pow(diffY,2));
CalculatedDistanceApart.Content = "Distance Apart: " + result.ToString() + "'";
}
}
if (((Path)x).Data.ToString() == "System.Windows.Media.EllipseGeometry")
{
PointIndex++;
}
}
catch { }
}
Instead of using a Path you could add ellipses to the grid and just attach a MouseLeftButtonUp event handler to each ellipse.
You wouldn't need all this hit-test code.
Well I don't know about your slow IsMouseOver, but the whole thing can certainly be sped and tidied up:
//why make these for every item?
var converter = new System.Windows.Media.BrushConverter();
var brush = (System.Windows.Media.Brush)converter.ConvertFromString("#FFB1D100");
foreach (var x in GraphPanel.Children)
{
//this is tidier, but what if it's not a Path, is that possible?
var path = (Path)x;
//jump out here if it's not the right type, reduces nesting and removes one comparison
if(!(path.Data is System.Windows.Media.EllipseGeometry)) continue;
try
{
if (path.IsMouseOver)
{
listViewPoints.SelectedItems.Add(listViewPoints.Items[PointIndex]);
path.Stroke = brush;
path.StrokeThickness = 8;
if (listViewPoints.SelectedItems.Count == 2)
{
double ptAX = ((Points)listViewPoints.SelectedItems[0]).A;
double ptAY = ((Points)listViewPoints.SelectedItems[0]).B;
double ptBX = ((Points)listViewPoints.SelectedItems[1]).A;
double ptBY = ((Points)listViewPoints.SelectedItems[1]).B;
//you're going to square these, so negatives don't matter
double diffX = ptAX - ptBX;
double diffY = ptAY - ptBY;
//the distance between the points = sqr/-diff in x squared + diff in y squared
//don't use Math.Pow for squaring
double result = Math.Sqrt(diffX*diffX + diffY*diffY);
CalculatedDistanceApart.Content = "Distance Apart: " + result + "'";
//are we done now?
}
}
PointIndex++;
}
catch { }
}
Math.Pow(x,2) vs x * x

Categories