/// <summary> /// Merges the edge wrap behavior of two transitions from face to face to vertex. /// </summary> /// <param name="face0ToFace1">The edge wrap data of the first transition.</param> /// <param name="face1ToVert">The edge wrap data of the second transition</param> /// <returns>The combined edge wrap behavior of chaining the two given transitions.</returns> public static EdgeWrap ChainFaceToFaceToVert(EdgeWrap face0ToFace1, EdgeWrap face1ToVert) { // Move the face-to-face data over into the face-to-vert region, and then combine // the two together, masking to keep only the face-to-vert bits, and then cancel // out any positive and negative directions on the same axis. return(EliminateContraryDirections((ShiftFaceToFaceAsFaceToVert(face0ToFace1) | face1ToVert) & EdgeWrap.FaceToVert)); }
/// <summary> /// Merges the edge wrap behavior of two transitions from vertex to face to face. /// </summary> /// <param name="vertToFace0">The edge wrap data of the first transition.</param> /// <param name="face0ToFace1">The edge wrap data of the second transition</param> /// <returns>The combined edge wrap behavior of chaining the two given transitions.</returns> public static EdgeWrap ChainVertToFaceToFace(EdgeWrap vertToFace0, EdgeWrap face0ToFace1) { // Move the face-to-face data over into the vert-to-face region, and then combine // the two together, masking to keep only the vert-to-face bits, and then cancel // out any positive and negative directions on the same axis. return(EliminateContraryDirections((vertToFace0 | ShiftFaceToFaceAsVertToFace(face0ToFace1)) & EdgeWrap.VertToFace)); }
/// <summary> /// Merges the edge wrap data of two partially specified twin half edges so that the edge wrap data for each half edge is fully specified. /// </summary> /// <param name="halfEdge0">The edge wrap data of the first half edge twin to merge.</param> /// <param name="halfEdge1">The edge wrap data of the second half edge twin to merge.</param> public static void CrossMergeTwins(ref EdgeWrap halfEdge0, ref EdgeWrap halfEdge1) { var invertedHalfEdge0 = InvertEdgeRelations(halfEdge0); var invertedHalfEdge1 = InvertEdgeRelations(halfEdge1); halfEdge0 = FromEdgeRelations(halfEdge0 | invertedHalfEdge1); halfEdge1 = FromEdgeRelations(invertedHalfEdge0 | halfEdge1); }
public NeighborFilter1D(EdgeWrap wrap) { EdgeWrap = wrap; if (EdgeWrap == EdgeWrap.Zero) { _defaultCell = new Cell(0, _emptyRule, _defaultFilter); } }
/// <summary> /// Inverts the edge relations of the edge wrap data, swapping positive and negative directions, and swapping edge-to-something and something-to-edge relations. /// </summary> /// <param name="edgeWrap">The edge wrap data to invert.</param> /// <returns>The inverted edge wrap data, with all non-edge relations cleared.</returns> public static EdgeWrap InvertEdgeRelations(EdgeWrap edgeWrap) { // Invert the positive and negative directions. var negAsPos = (uint)(edgeWrap & EdgeWrap.Neg) >> 1; var posAsNeg = (uint)(edgeWrap & EdgeWrap.Pos) << 1; var invertedDirections = (EdgeWrap)(negAsPos | posAsNeg); // Swap the edge-to and to-edge relations. return (ShiftToEdgeAsEdgeTo(invertedDirections) & EdgeWrap.EdgeTo | ShiftEdgeToAsToEdge(invertedDirections) & EdgeWrap.ToEdge); }
public void Filter_ReturnsExpected(int[] states, int index, EdgeWrap wrap, int[] expected) { var cells = new Cell[states.Length, 1]; var filter = new NeighborFilter1D(wrap); for (int x = 0; x < states.Length; x++) { cells[x, 0] = new Cell(states[x], _rule, filter); } var filteredCells = filter.Filter(cells, index, 0); var actual = filteredCells.Select(x => x.State).ToArray(); Assert.Equal(expected, actual); }
/// <summary> /// Derives the full edge wrap data from just the flags involving edges. /// </summary> /// <param name="edgeWrap">The partial edge wrap data which only specifies wrap behavior for transitions involving edges.</param> /// <returns>The full edge wrap data which specifies wrap behavior for all transition types.</returns> public static EdgeWrap FromEdgeRelations(EdgeWrap edgeWrap) { // Binary layout: // 28 24 20 16 12 8 4 0 // [F->F][F->V][V->F][V->V][E->F][E->V][F->E][V->E] // // [F->E][F->E][V->E][V->E] (toEdge) // chained to // [E->F][E->V][E->F][E->V] (edgeTo) // produces // [F->F][F->V][V->F][V->V] (non-edge relations, before contary direction elimination) var toEdge = ((uint)(edgeWrap & EdgeWrap.FaceToEdge) << 8) | ((uint)(edgeWrap & EdgeWrap.ToEdge) << 4) | (uint)(edgeWrap & EdgeWrap.VertToEdge); var edgeTo = (uint)(edgeWrap & EdgeWrap.EdgeTo) | ((uint)(edgeWrap & EdgeWrap.EdgeTo) >> 8); return(EliminateContraryDirections((EdgeWrap)((toEdge | edgeTo) << 16) | (edgeWrap & EdgeWrap.Edge))); }
/// <summary> /// Eliminates any opposing wrap directions in the given edge wrap data, since a positive and negative wrap along the same axis essentially cancel each other out. /// </summary> /// <param name="edgeWrap">The edge wrap data to sanitize by eliminating opposing wrap directions.</param> /// <returns>A sanitized form of the provided edge wrap data without any opposing wrap directions.</returns> public static EdgeWrap EliminateContraryDirections(EdgeWrap edgeWrap) { // Take all the negative axis bits, shift them right to align with positive // axis bits, and then bitwise-and the negative and positive axis bits together. // The result are bits set only where both the negative and positive directions // are active for a given axis. var mask = ((uint)(edgeWrap & EdgeWrap.Neg) >> 1) & (uint)edgeWrap; // Duplicate the set bits back over into the negative axis bits, and then negate // the whole thing, causing negative/positive bit pairs to be 00 whenever both // bits were set originally, and 11 otherwise. mask = ~(mask | (mask << 1)); // Use this mask to zero out any axes that had both positive and negative // directions set. return(edgeWrap & (EdgeWrap)mask); }
/// <summary> /// Adjusts the original edge wrap data to include additional vertex-to-vertex wrap behavior as if it were vertex-to-edge wrap behavior. /// </summary> /// <param name="original">The original edge wrap data.</param> /// <param name="adjustment">The vertex-to-vertex adjustment.</param> /// <returns>The original edge wrap data adjusted according to the additional vertex-to-vertex wrap behavior.</returns> public static EdgeWrap ModifySourceVertEdgeRelations(EdgeWrap original, EdgeWrap adjustment) { return(FromEdgeRelations( (ShiftVertToVertAsVertToEdge(adjustment) | original) & EdgeWrap.VertToEdge | original & ~EdgeWrap.VertToEdge)); }
/// <summary> /// Merges the edge wrap behavior of two transitions from face to face to face. /// </summary> /// <param name="face0ToFace1">The edge wrap data of the first transition.</param> /// <param name="face1ToFace2">The edge wrap data of the second transition</param> /// <returns>The combined edge wrap behavior of chaining the two given transitions.</returns> public static EdgeWrap ChainFaceToFaceToFace(EdgeWrap face0ToFace1, EdgeWrap face1ToFace2) { // Combine the two edge wraps together, masking to keep only the face-to-face bits, // and then cancel out any positive and negative directions on the same axis. return(EliminateContraryDirections((face0ToFace1 | face1ToFace2) & EdgeWrap.FaceToFace)); }
/// <inheritdoc/> public override Vector3 ReverseOffsetFaceToFaceAttribute(Vector3 position, EdgeWrap edgeWrap) { return(ReverseOffsetAttribute(position, EdgeWrapUtility.FaceToFaceAsGeneric(edgeWrap))); }
/// <summary> /// Merges the edge wrap behavior of two transitions from edge to vertex to vertex. /// </summary> /// <param name="edgeToVert0">The edge wrap data of the first transition.</param> /// <param name="vert0ToVert1">The edge wrap data of the second transition</param> /// <returns>The combined edge wrap behavior of chaining the two given transitions.</returns> public static EdgeWrap ChainEdgeToVertToVert(EdgeWrap edgeToVert0, EdgeWrap vert0ToVert1) { return(EliminateContraryDirections((edgeToVert0 | ShiftVertToVertAsEdgeToVert(vert0ToVert1)) & EdgeWrap.EdgeToVert)); }
/// <inheritdoc/> public override Vector3 OffsetFaceToVertAttribute(Vector3 position, EdgeWrap edgeWrap) { return(OffsetAttribute(position, EdgeWrapUtility.FaceToVertAsGeneric(edgeWrap))); }
/// <inheritdoc/> public virtual Vector3 OffsetVertToEdgeAttribute(Vector3 position, EdgeWrap edgeWrap) { return(position); }
/// <inheritdoc/> public virtual Vector3 ReverseOffsetVertToVertAttribute(Vector3 position, EdgeWrap edgeWrap) { return(position); }
/// <summary> /// Adjusts the original edge wrap data to include additional vertex-to-vertex wrap behavior as if it were edge-to-vertex wrap behavior. /// </summary> /// <param name="original">The original edge wrap data.</param> /// <param name="adjustment">The vertex-to-vertex adjustment.</param> /// <returns>The original edge wrap data adjusted according to the additional vertex-to-vertex wrap behavior.</returns> public static EdgeWrap ModifyTargetVertEdgeRelations(EdgeWrap original, EdgeWrap adjustment) { return(FromEdgeRelations( (original | ShiftVertToVertAsEdgeToVert(adjustment)) & EdgeWrap.EdgeToVert | original & ~EdgeWrap.EdgeToVert)); }
/// <summary> /// Merges the face/edge wrap behavior of two transitions from face to face to face as if collapsing the two intermediate edges and middle face into a single edge. /// </summary> /// <param name="edge0">The edge wrap data of the first transition.</param> /// <param name="edge1">The edge wrap data of the second transition</param> /// <returns>The combined edge wrap behavior of chaining the two given transitions.</returns> public static EdgeWrap ChainFaceEdgeRelations(EdgeWrap edge0, EdgeWrap edge1) { return(EliminateContraryDirections( (ShiftFaceToFaceAsFaceToEdge(edge0) | edge1) & EdgeWrap.FaceToEdge | (edge0 | ShiftFaceToFaceAsEdgeToFace(edge1)) & EdgeWrap.EdgeToFace)); }
/// <summary> /// Merges the vertex/edge wrap behavior of two transitions from vertex to vertex to vertex as if collapsing the two intermediate edges and middle vertex into a single edge. /// </summary> /// <param name="edge0">The edge wrap data of the first transition.</param> /// <param name="edge1">The edge wrap data of the second transition</param> /// <returns>The combined edge wrap behavior of chaining the two given transitions.</returns> public static EdgeWrap ChainVertEdgeRelations(EdgeWrap edge0, EdgeWrap edge1) { return(EliminateContraryDirections( (ShiftVertToVertAsVertToEdge(edge0) | edge1) & EdgeWrap.VertToEdge | (edge0 | ShiftVertToVertAsEdgeToVert(edge1)) & EdgeWrap.EdgeToVert)); }
/// <summary> /// Merges the edge wrap behavior of two transitions from edge to face to face. /// </summary> /// <param name="edgeToFace0">The edge wrap data of the first transition.</param> /// <param name="face0ToFace1">The edge wrap data of the second transition</param> /// <returns>The combined edge wrap behavior of chaining the two given transitions.</returns> public static EdgeWrap ChainEdgeToFaceToFace(EdgeWrap edgeToFace0, EdgeWrap face0ToFace1) { return(EliminateContraryDirections((edgeToFace0 | ShiftFaceToFaceAsEdgeToFace(face0ToFace1)) & EdgeWrap.EdgeToFace)); }
/// <summary> /// Merges the edge wrap behavior of two transitions from face to face to edge. /// </summary> /// <param name="face0ToFace1">The edge wrap data of the first transition.</param> /// <param name="face1ToEdge">The edge wrap data of the second transition</param> /// <returns>The combined edge wrap behavior of chaining the two given transitions.</returns> public static EdgeWrap ChainFaceToFaceToEdge(EdgeWrap face0ToFace1, EdgeWrap face1ToEdge) { return(EliminateContraryDirections((ShiftFaceToFaceAsFaceToEdge(face0ToFace1) | face1ToEdge) & EdgeWrap.FaceToEdge)); }
/// <inheritdoc/> public virtual Vector3 OffsetFaceToVertAttribute(Vector3 position, EdgeWrap edgeWrap) { return(position); }
/// <summary> /// Adjusts the original edge wrap data to include additional face-to-face wrap behavior as if it were edge-to-face wrap behavior. /// </summary> /// <param name="original">The original edge wrap data.</param> /// <param name="adjustment">The face-to-face adjustment.</param> /// <returns>The original edge wrap data adjusted according to the additional face-to-face wrap behavior.</returns> public static EdgeWrap ModifyTargetFaceEdgeRelations(EdgeWrap original, EdgeWrap adjustment) { return(FromEdgeRelations( (original | ShiftFaceToFaceAsEdgeToFace(adjustment)) & EdgeWrap.EdgeToFace | original & ~EdgeWrap.EdgeToFace)); }
/// <inheritdoc/> public virtual Vector3 ReverseOffsetFaceToFaceAttribute(Vector3 position, EdgeWrap edgeWrap) { return(position); }
/// <summary> /// Adjusts the original edge wrap data to include additional face-to-face wrap behavior as if it were face-to-edge wrap behavior. /// </summary> /// <param name="original">The original edge wrap data.</param> /// <param name="adjustment">The face-to-face adjustment.</param> /// <returns>The original edge wrap data adjusted according to the additional vertex-to-vertex wrap behavior.</returns> public static EdgeWrap ModifySourceFaceEdgeRelations(EdgeWrap original, EdgeWrap adjustment) { return(FromEdgeRelations( (ShiftFaceToFaceAsFaceToEdge(adjustment) | original) & EdgeWrap.FaceToEdge | original & ~EdgeWrap.FaceToEdge)); }
/// <summary> /// Merges the edge wrap behavior of two transitions from vertex to vertex to vertex. /// </summary> /// <param name="vert0ToVert1">The edge wrap data of the first transition.</param> /// <param name="vert1ToVert2">The edge wrap data of the second transition</param> /// <returns>The combined edge wrap behavior of chaining the two given transitions.</returns> public static EdgeWrap ChainVertToVertToVert(EdgeWrap vert0ToVert1, EdgeWrap vert1ToVert2) { // Combine the two edge wraps together, masking to keep only the vert-to-vert bits, // and then cancel out any positive and negative directions on the same axis. return(EliminateContraryDirections((vert0ToVert1 | vert1ToVert2) & EdgeWrap.VertToVert)); }
/// <summary> /// Shifts the first axis relation bits of the given edge wrap data to become second axis relations. /// </summary> /// <param name="axis0">The edge wrap data to shift.</param> /// <returns>The edge wrap data shifted so that the first axis relations are now second axis relations.</returns> /// <remarks><note type="important">All bits other than the second axis bits should be considered garbage, /// and should therefore be masked away or otherwise corrected before they are inadvertently used.</note></remarks> private static EdgeWrap ShiftAxis0AsAxis1(EdgeWrap axis0) { return((EdgeWrap)((uint)axis0 << 2)); }
/// <inheritdoc/> public override Vector3 ReverseOffsetVertToVertAttribute(Vector3 position, EdgeWrap edgeWrap) { return(ReverseOffsetAttribute(position, EdgeWrapUtility.VertToVertAsGeneric(edgeWrap))); }
/// <summary> /// Shifts the second axis relation bits of the given edge wrap data to become first axis relations. /// </summary> /// <param name="axis1">The edge wrap data to shift.</param> /// <returns>The edge wrap data shifted so that the second axis relations are now first axis relations.</returns> /// <remarks><note type="important">All bits other than the first axis bits should be considered garbage, /// and should therefore be masked away or otherwise corrected before they are inadvertently used.</note></remarks> private static EdgeWrap ShiftAxis1AsAxis0(EdgeWrap axis1) { return((EdgeWrap)((uint)axis1 >> 2)); }
/// <summary> /// Constructs an instance of neighbor data using the given vertex index and edge wrap data. /// </summary> /// <param name="vertexIndex">The index of the neighbor vertex.</param> /// <param name="edgeWrap">The edge wrap data of the neighbor edge.</param> public NeighborData(int vertexIndex, EdgeWrap edgeWrap = EdgeWrap.None) { this.vertexIndex = vertexIndex; this.edgeWrap = edgeWrap; }
/// <summary> /// Merges the edge wrap behavior of two transitions from vertex to vertex to edge. /// </summary> /// <param name="vert0ToVert1">The edge wrap data of the first transition.</param> /// <param name="vert1ToEdge">The edge wrap data of the second transition</param> /// <returns>The combined edge wrap behavior of chaining the two given transitions.</returns> public static EdgeWrap ChainVertToVertToEdge(EdgeWrap vert0ToVert1, EdgeWrap vert1ToEdge) { return(EliminateContraryDirections((ShiftVertToVertAsVertToEdge(vert0ToVert1) | vert1ToEdge) & EdgeWrap.VertToEdge)); }