/** * create a new identifier that is one larger than the given * identifier, with the first element set to front. */ public AreaIdentifier(int front, AreaIdentifier back) { if (front < 0) { throw new ArgumentException("value must not be negative", "front"); } path = new int[back.path.Length + 1]; path[0] = front; Array.Copy(back.path, 0, path, 1, back.path.Length); }
/** * if the id id empty (at a terminal node), return 0, * otherwise throw an invalid id exception * TODO figure out why we do this */ public override Scaled Origin(AreaIdentifier id) { if (id.End) { return(0); } else { throw new InvalidIdentifier(); } }
/** * simple areas are terminsl nodes, so make sure the identifer * is empty at this point, and return this node, otherwise * throw an invalid id exception */ public override Area GetArea(AreaIdentifier identifier) { if (identifier.End) { return(this); } else { throw new InvalidIdentifier(); } }
/** * create a new identifier that is next identifier relative * to the given identifier. this takes the given identifier and * makes a new identifier that has a path length one less than * the given identier, and copies the all items except the first * one. So if the given identifier is [k1,k2,k3,...,kn], the * new identifier will be [k2,k3,...,kn]. * If the previous identifer is allready empty, an * InvalidArgument exception is thrown. */ public AreaIdentifier(AreaIdentifier previous) { if (previous.path.Length > 0) { path = new int[previous.path.Length - 1]; previous.path.CopyTo(path, 1); } else { throw new ArgumentException( "the previous identifier must not be empty", "previous"); } }
/** * if the id is for this node, return 0. otherwise if the id is for * a child node, return that node's left side. */ public override Scaled RightSide(AreaIdentifier id) { if (id.End) { return(0); } else if (id.Current < content.Length) { return(content[id.Current].RightSide(id++)); } else { throw new InvalidIdentifier(); } }
/** * get the right side value. * the identier is only valid if it is for the child * node, or one of the child node's descendants. a * bin container can not have a right side value. */ public override Scaled RightSide(AreaIdentifier id) { if (id.End) { throw new InvalidOperation(); } else if (id.Current == 0) { id.MoveNext(); return(child.RightSide(id)); } else { throw new InvalidIdentifier(); } }
/** * create an identifier for a descendant area. * as a BinContainerArea can only have one direct child area, * the only valie identifiers are ones that are at the end of * thier path, indicating that it identifies this this node, * or an identifier with its' current element being zero, indicating * that the current leg of its's path identifies the zero'th and * only child node. */ public override Area GetArea(AreaIdentifier id) { if (id.End) { return(this); } else if (id.Current == 0) { id.MoveNext(); return(child.GetArea(id)); } else { throw new InvalidIdentifier(); } }
/** * get a child area that has a path to this node * if the identifier is at its's last item, this final step * in the path, so return this node, otherwise, if the current step * is valid (less than the size of the child node list, the child * area at the current position will get the path moved to the next * position. If the id is not at it's end, and the current item is * out of range, an invalid id exception is thrown. */ public override Area GetArea(AreaIdentifier id) { if (id.End) { return(this); } else if (id.Current < content.Length) { Area current = content[id.Current]; id.MoveNext(); return(current.GetArea(id)); } else { throw new InvalidIdentifier(); } }
/** * TODO write this up */ public override Scaled Origin(AreaIdentifier id) { if (id.End) { // get the origin for this node. return(0); } else if (id.Current == 0) { // get the origin for the child node id.MoveNext(); return(child.Origin(id)); } else { // bad monkey throw new InvalidIdentifier(); } }
/** * get the width of all nodes up to the identified nodes, * plus the the origin of the identifed node. * This is the relative distance from the identified node's origin * to this node's origin. */ public override Scaled Origin(AreaIdentifier id) { if (id.End) { return(0); } else if (id.Current < content.Length) { Scaled width = 0; // all nodes up to, but not including the identified node for (int i = 0; i < id.Current; i++) { width += content[i].BoundingBox.Width; } return(content[id.Current].Origin(id++) + width); } else { throw new InvalidIdentifier(); } }
/** * not supported on simple nodes * TODO find out why */ public override Scaled RightSide(AreaIdentifier id) { throw new InvalidOperation(); }
public virtual float LeftSide(AreaIdentifier id) { return(0); }
/** * compute the horizontal component of the identified node's * origin with respect to this node's origin, e.g. the identified * node's reference point with respect to this node's refernce point. * The following recursive relation holds: * * 1: a node with no child nodes returns 0: * a.Origin([]) = 0 * * 2: a horizontal array returns the width of all previous nodes * plus the origin of the identified node: * HorizontalArray.Origin([k1,k2,k3,...kn] = sum(0.width -> k1.width) + * k1.Origin([k2,k3,...kn]) * * 3: a node with child nodes that is not a horizontal array * returns the identified node's origin: * a.Origin([k1,k2,k3...kn]) = k1.Origin([k2,k3,...,kn]) */ public virtual float Origin(AreaIdentifier id) { return(0); }
/** * get an area with an identifier that is a relative path * to this node. */ public virtual Area GetArea(AreaIdentifier id) { return(null); }