//private static FieldOctree<GravityCell> BuildFieldSprtNode_OLD(List<GravityCell> allLeaves, MapOctree[] ancestors, double[] ancestorMasses, MapOctree node) //{ // #region Add up mass // // Add up all the mass sitting in the ancestors // double massFromAbove = 0d; // if (ancestorMasses != null) // { // for (int cntr = 0; cntr < ancestorMasses.Length; cntr++) // { // // Each child shares 1/8th of the parent's mass + 1/64th of the grandparents, etc // // (these masses directly at each ancestor is of the objects that are straddling the lines between nodes) // massFromAbove += ancestorMasses[cntr] * Math.Pow(.125d, ancestorMasses.Length - cntr); // } // } // double massOfNode = 0d; // if (node.Items != null) // { // foreach (MapObjectInfo item in node.Items) // { // massOfNode += item.Mass; // } // } // #endregion // if (!node.HasChildren) // { // #region Leaf // // Exit Function // GravityCell cell = new GravityCell(massFromAbove + massOfNode, node.CenterPoint); // allLeaves.Add(cell); // return new FieldOctree<GravityCell>(node.MinRange, node.MaxRange, node.CenterPoint, cell); // #endregion // } // // Make the return node // FieldOctree<GravityCell> retVal = new FieldOctree<GravityCell>(node.MinRange, node.MaxRange, node.CenterPoint); // #region Build ancestor arrays // // Create new arrays that hold this node's values (to pass to the children) // MapOctree[] ancestorsNew = null; // double[] ancestorMassesNew = null; // if (ancestors == null) // { // // This is the root // ancestorsNew = new MapOctree[] { node }; // ancestorMassesNew = new double[] { massOfNode }; // } // else // { // // This is a middle ancestor // ancestorsNew = new MapOctree[ancestors.Length + 1]; // Array.Copy(ancestors, ancestorsNew, ancestors.Length); // ancestorsNew[ancestorsNew.Length - 1] = node; // ancestorMassesNew = new double[ancestorMasses.Length + 1]; // Array.Copy(ancestorMasses, ancestorMassesNew, ancestorMasses.Length); // ancestorMassesNew[ancestorMassesNew.Length - 1] = massOfNode; // } // #endregion // #region Add the children // //NOTE: The map's octree will leave children null if there are no items in them. But this tree always has all 8 children // if (node.X0_Y0_Z0 == null) // { // retVal.X0_Y0_Z0 = BuildFieldSprtNode(allLeaves, massFromAbove + massOfNode, new Point3D(node.MinRange.X, node.MinRange.Y, node.MinRange.Z), new Point3D(node.CenterPoint.X, node.CenterPoint.Y, node.CenterPoint.Z)); // } // else // { // retVal.X0_Y0_Z0 = BuildFieldSprtNode(allLeaves, ancestorsNew, ancestorMassesNew, node.X0_Y0_Z0); // } // if (node.X0_Y0_Z1 == null) // { // retVal.X0_Y0_Z1 = BuildFieldSprtNode(allLeaves, massFromAbove + massOfNode, new Point3D(node.MinRange.X, node.MinRange.Y, node.CenterPoint.Z), new Point3D(node.CenterPoint.X, node.CenterPoint.Y, node.MaxRange.Z)); // } // else // { // retVal.X0_Y0_Z1 = BuildFieldSprtNode(allLeaves, ancestorsNew, ancestorMassesNew, node.X0_Y0_Z1); // } // if (node.X0_Y1_Z0 == null) // { // retVal.X0_Y1_Z0 = BuildFieldSprtNode(allLeaves, massFromAbove + massOfNode, new Point3D(node.MinRange.X, node.CenterPoint.Y, node.MinRange.Z), new Point3D(node.CenterPoint.X, node.MaxRange.Y, node.CenterPoint.Z)); // } // else // { // retVal.X0_Y1_Z0 = BuildFieldSprtNode(allLeaves, ancestorsNew, ancestorMassesNew, node.X0_Y1_Z0); // } // if (node.X0_Y1_Z1 == null) // { // retVal.X0_Y1_Z1 = BuildFieldSprtNode(allLeaves, massFromAbove + massOfNode, new Point3D(node.MinRange.X, node.CenterPoint.Y, node.CenterPoint.Z), new Point3D(node.CenterPoint.X, node.MaxRange.Y, node.MaxRange.Z)); // } // else // { // retVal.X0_Y1_Z1 = BuildFieldSprtNode(allLeaves, ancestorsNew, ancestorMassesNew, node.X0_Y1_Z1); // } // if (node.X1_Y0_Z0 == null) // { // retVal.X1_Y0_Z0 = BuildFieldSprtNode(allLeaves, massFromAbove + massOfNode, new Point3D(node.CenterPoint.X, node.MinRange.Y, node.MinRange.Z), new Point3D(node.MaxRange.X, node.CenterPoint.Y, node.CenterPoint.Z)); // } // else // { // retVal.X1_Y0_Z0 = BuildFieldSprtNode(allLeaves, ancestorsNew, ancestorMassesNew, node.X1_Y0_Z0); // } // if (node.X1_Y0_Z1 == null) // { // retVal.X1_Y0_Z1 = BuildFieldSprtNode(allLeaves, massFromAbove + massOfNode, new Point3D(node.CenterPoint.X, node.MinRange.Y, node.CenterPoint.Z), new Point3D(node.MaxRange.X, node.CenterPoint.Y, node.MaxRange.Z)); // } // else // { // retVal.X1_Y0_Z1 = BuildFieldSprtNode(allLeaves, ancestorsNew, ancestorMassesNew, node.X1_Y0_Z1); // } // if (node.X1_Y1_Z0 == null) // { // retVal.X1_Y1_Z0 = BuildFieldSprtNode(allLeaves, massFromAbove + massOfNode, new Point3D(node.CenterPoint.X, node.CenterPoint.Y, node.MinRange.Z), new Point3D(node.MaxRange.X, node.MaxRange.Y, node.CenterPoint.Z)); // } // else // { // retVal.X1_Y1_Z0 = BuildFieldSprtNode(allLeaves, ancestorsNew, ancestorMassesNew, node.X1_Y1_Z0); // } // if (node.X1_Y1_Z1 == null) // { // retVal.X1_Y1_Z1 = BuildFieldSprtNode(allLeaves, massFromAbove + massOfNode, new Point3D(node.CenterPoint.X, node.CenterPoint.Y, node.CenterPoint.Z), new Point3D(node.MaxRange.X, node.MaxRange.Y, node.MaxRange.Z)); // } // else // { // retVal.X1_Y1_Z1 = BuildFieldSprtNode(allLeaves, ancestorsNew, ancestorMassesNew, node.X1_Y1_Z1); // } // #endregion // // Exit Function // return retVal; //} #endregion private static FieldOctree <GravityCell> BuildField_Node(List <GravityCell> allLeaves, double mass, Point3D min, Point3D max) { Point3D center = new Point3D((min.X + max.X) * .5d, (min.Y + max.Y) * .5d, (min.Z + max.Z) * .5d); GravityCell cell = new GravityCell(mass, center); allLeaves.Add(cell); return(new FieldOctree <GravityCell>(min, max, center, cell)); }
public Vector3D GetForce(Point3D point) { Vector3D retVal = new Vector3D(0, 0, 0); // If there is a swirl, then calculate it for this point SwirlField swirl = this.Swirl; // can only hit the property once, it could be swapped out at any moment if (swirl != null) { retVal += swirl.GetForce(point); } // Boundry field BoundryField boundry = this.Boundry; if (boundry != null) { retVal += boundry.GetForce(point); } // Grab the root for the remainder of this method (the public one could swap out at any moment) var root = _fieldRoot; if (root == null) { return(retVal); } if (!Math3D.IsInside_AABB(root.MinRange, root.MaxRange, point)) { // The point is outside the root, so just assume no gravity (the root should have been big enough to surround all objects, so there shouldn't // be any requests outside the root) return(retVal); } // Recurse down, and get the leaf for this point GravityCell cell = root.GetLeaf(point); if (cell == null) { // There should be a leaf for all points within the tree. But rather than an exception, just assume zero force return(retVal); } // Exit Function return(retVal + cell.Force); }
private static FieldOctree <GravityCell> BuildField_Node(List <GravityCell> allLeaves, MapOctree[] ancestors, MapOctree node) { #region Add up mass double massOfNode = 0d; if (node.Items != null) { foreach (MapObjectInfo item in node.Items) { massOfNode += item.Mass; } } #endregion if (!node.HasChildren) { #region Leaf // Exit Function GravityCell cell = new GravityCell(BuildField_NodeSprtAncestorMass(ancestors, node.MinRange, node.MaxRange) + massOfNode, node.CenterPoint); allLeaves.Add(cell); return(new FieldOctree <GravityCell>(node.MinRange, node.MaxRange, node.CenterPoint, cell)); #endregion } // Make the return node FieldOctree <GravityCell> retVal = new FieldOctree <GravityCell>(node.MinRange, node.MaxRange, node.CenterPoint); #region Build ancestor arrays // Create new arrays that hold this node's values (to pass to the children) MapOctree[] ancestorsNew = null; if (ancestors == null) { // This is the root ancestorsNew = new MapOctree[] { node }; } else { // This is a middle ancestor ancestorsNew = new MapOctree[ancestors.Length + 1]; Array.Copy(ancestors, ancestorsNew, ancestors.Length); ancestorsNew[ancestorsNew.Length - 1] = node; } #endregion #region Add the children //NOTE: The map's octree will leave children null if there are no items in them. But this tree always has all 8 children if (node.X0_Y0_Z0 == null) { Point3D childMin = new Point3D(node.MinRange.X, node.MinRange.Y, node.MinRange.Z); Point3D childMax = new Point3D(node.CenterPoint.X, node.CenterPoint.Y, node.CenterPoint.Z); retVal.X0_Y0_Z0 = BuildField_Node(allLeaves, BuildField_NodeSprtAncestorMass(ancestors, childMin, childMax) + massOfNode, childMin, childMax); } else { retVal.X0_Y0_Z0 = BuildField_Node(allLeaves, ancestorsNew, node.X0_Y0_Z0); } if (node.X0_Y0_Z1 == null) { Point3D childMin = new Point3D(node.MinRange.X, node.MinRange.Y, node.CenterPoint.Z); Point3D childMax = new Point3D(node.CenterPoint.X, node.CenterPoint.Y, node.MaxRange.Z); retVal.X0_Y0_Z1 = BuildField_Node(allLeaves, BuildField_NodeSprtAncestorMass(ancestors, childMin, childMax) + massOfNode, childMin, childMax); } else { retVal.X0_Y0_Z1 = BuildField_Node(allLeaves, ancestorsNew, node.X0_Y0_Z1); } if (node.X0_Y1_Z0 == null) { Point3D childMin = new Point3D(node.MinRange.X, node.CenterPoint.Y, node.MinRange.Z); Point3D childMax = new Point3D(node.CenterPoint.X, node.MaxRange.Y, node.CenterPoint.Z); retVal.X0_Y1_Z0 = BuildField_Node(allLeaves, BuildField_NodeSprtAncestorMass(ancestors, childMin, childMax) + massOfNode, childMin, childMax); } else { retVal.X0_Y1_Z0 = BuildField_Node(allLeaves, ancestorsNew, node.X0_Y1_Z0); } if (node.X0_Y1_Z1 == null) { Point3D childMin = new Point3D(node.MinRange.X, node.CenterPoint.Y, node.CenterPoint.Z); Point3D childMax = new Point3D(node.CenterPoint.X, node.MaxRange.Y, node.MaxRange.Z); retVal.X0_Y1_Z1 = BuildField_Node(allLeaves, BuildField_NodeSprtAncestorMass(ancestors, childMin, childMax) + massOfNode, childMin, childMax); } else { retVal.X0_Y1_Z1 = BuildField_Node(allLeaves, ancestorsNew, node.X0_Y1_Z1); } if (node.X1_Y0_Z0 == null) { Point3D childMin = new Point3D(node.CenterPoint.X, node.MinRange.Y, node.MinRange.Z); Point3D childMax = new Point3D(node.MaxRange.X, node.CenterPoint.Y, node.CenterPoint.Z); retVal.X1_Y0_Z0 = BuildField_Node(allLeaves, BuildField_NodeSprtAncestorMass(ancestors, childMin, childMax) + massOfNode, childMin, childMax); } else { retVal.X1_Y0_Z0 = BuildField_Node(allLeaves, ancestorsNew, node.X1_Y0_Z0); } if (node.X1_Y0_Z1 == null) { Point3D childMin = new Point3D(node.CenterPoint.X, node.MinRange.Y, node.CenterPoint.Z); Point3D childMax = new Point3D(node.MaxRange.X, node.CenterPoint.Y, node.MaxRange.Z); retVal.X1_Y0_Z1 = BuildField_Node(allLeaves, BuildField_NodeSprtAncestorMass(ancestors, childMin, childMax) + massOfNode, childMin, childMax); } else { retVal.X1_Y0_Z1 = BuildField_Node(allLeaves, ancestorsNew, node.X1_Y0_Z1); } if (node.X1_Y1_Z0 == null) { Point3D childMin = new Point3D(node.CenterPoint.X, node.CenterPoint.Y, node.MinRange.Z); Point3D childMax = new Point3D(node.MaxRange.X, node.MaxRange.Y, node.CenterPoint.Z); retVal.X1_Y1_Z0 = BuildField_Node(allLeaves, BuildField_NodeSprtAncestorMass(ancestors, childMin, childMax) + massOfNode, childMin, childMax); } else { retVal.X1_Y1_Z0 = BuildField_Node(allLeaves, ancestorsNew, node.X1_Y1_Z0); } if (node.X1_Y1_Z1 == null) { Point3D childMin = new Point3D(node.CenterPoint.X, node.CenterPoint.Y, node.CenterPoint.Z); Point3D childMax = new Point3D(node.MaxRange.X, node.MaxRange.Y, node.MaxRange.Z); retVal.X1_Y1_Z1 = BuildField_Node(allLeaves, BuildField_NodeSprtAncestorMass(ancestors, childMin, childMax) + massOfNode, childMin, childMax); } else { retVal.X1_Y1_Z1 = BuildField_Node(allLeaves, ancestorsNew, node.X1_Y1_Z1); } #endregion // Exit Function return(retVal); }