// Is this OCAD coordinate starting a hole? static bool IsOcadCoordHoleStart(OcadCoord coord) { if ((coord.y & 2) != 0) return true; else return false; }
// Is this OCAD coordinate a bezier control point? static bool IsOcadCoordBezierControl(OcadCoord coord) { if ((coord.x & 3) != 0) return true; else return false; }
// Is this OCAD coordinate a area boundary cutout? static bool IsOcadCoordBoundaryCutOut(OcadCoord coord) { if ((coord.x & 8) != 0) return true; else return false; }
internal static OcadCoord[] FixOcadCoords(OcadCoord[] coords, bool allowHoles, out int numHoles, out bool anyCutouts) { bool foundProblem = false; int numBezierControls = 0; // tracks the current number of bezier controls found. numHoles = 0; anyCutouts = false; if (coords.Length == 0) return coords; if (IsOcadCoordBezierControl(coords[0])) foundProblem = true; for (int i = 0; i < coords.Length; ++i) { OcadCoord coord = coords[i]; if (IsOcadCoordAnyCutOut(coord)) anyCutouts = true; if (i >= 1 && IsOcadCoordHoleStart(coord)) { if (IsOcadCoordBezierControl(coord)) foundProblem = true; if (numBezierControls != 0) foundProblem = true; if (!allowHoles) foundProblem = true; else ++numHoles; } if (IsOcadCoordBezierControl(coord)) ++numBezierControls; else { if (numBezierControls != 0 && numBezierControls != 2) foundProblem = true; numBezierControls = 0; } } if (numBezierControls != 0) foundProblem = true; // should not end with bezier controls. // If there were no problems, just return the argument and done (fast, common case). if (!foundProblem) return coords; else return PatchUpOcadCoords(coords, allowHoles); }
// Is this COAD coord any cutout? static bool IsOcadCoordAnyCutOut(OcadCoord coord) { if (((coord.x & 0xC) != 0) || ((coord.y & 4) != 0)) return true; else return false; }
// Scan the OCAD coordinates and fix the following problems: // 1. not exactly two bezier control points in a row // 2. start or end with bezier control points // 3. holes when none are allowed. // If holes are allowed, counts how many there are. static OcadCoord[] PatchUpOcadCoords(OcadCoord[] coords, bool allowHoles) { int numBezierControls = 0; // number of consecutive bezier control points found. bool atStart = true; // are we at the start or the start of a hole? List<OcadCoord> list = new List<OcadCoord>(); // the list of coordinates we are building up. for (int i = 0; i < coords.Length; ++i) { OcadCoord coord = coords[i]; if (IsOcadCoordHoleStart(coord)) { if (numBezierControls != 0) { // remove trailing bezier control points. list.RemoveRange(list.Count - numBezierControls, numBezierControls); numBezierControls = 0; } atStart = true; if (!allowHoles) break; } if (IsOcadCoordBezierControl(coord)) { // At the start ignore bezier control points. if (!atStart) { ++numBezierControls; list.Add(coord); } } else { if (numBezierControls != 0 && numBezierControls != 2) list.RemoveRange(list.Count - numBezierControls, numBezierControls); numBezierControls = 0; if (atStart && list.Count != 0) coord.y |= 2; // we need to start a hole here, since the bezier that started the hole might have been nuked. list.Add(coord); atStart = false; } } // Remove trailing bezier control points. if (numBezierControls != 0) list.RemoveRange(list.Count - numBezierControls, numBezierControls); return list.ToArray(); }
public static void WriteCoords(BinaryWriter writer, OcadCoord[] coords) { foreach (OcadCoord coord in coords) coord.Write(writer); }
//PointF[] lineBuilder = new PointF[1]; // used to build lines in CreateSymPath. PointF PointFromOcadCoord(OcadCoord coord) { return new PointF(ToWorldDimensions(coord.x >> 8), ToWorldDimensions(coord.y >> 8)); }
PointKind PointKindFromOcadCoord(OcadCoord coord) { if ((coord.x & 3) != 0) return PointKind.BezierControl; else if ((coord.y & 1) != 0) return PointKind.Corner; else if ((coord.y & 8) != 0) return PointKind.Dash; else return PointKind.Normal; }
OcadCoord[] GetTextObjectCoords(TextSymbol sym) { TextSymDef symdef = ((TextSymDef) sym.Definition); PointF location = sym.Location; SizeF size = sym.TextSize; float angle = sym.Rotation; float width = sym.Width; PointF[] points; if (width > 0) { // Formatted text points = new PointF[4]; float topAdjust = symdef.FontEmHeight - (symdef.FontAscent + symdef.FontDescent); float height = size.Height + symdef.FontEmHeight - symdef.FontAscent; location.Y -= (float) (topAdjust * Math.Sin((angle + 90.0) / 360.0 * 2 * Math.PI)); location.X -= (float) (topAdjust * Math.Cos((angle + 90.0) / 360.0 * 2 * Math.PI)); points[3] = location; location.Y -= (float) (width * Math.Cos((angle + 90.0) / 360.0 * 2 * Math.PI)); location.X += (float) (width * Math.Sin((angle + 90.0) / 360.0 * 2 * Math.PI)); points[2] = location; location.Y -= (float) (height * Math.Sin((angle + 90.0) / 360.0 * 2 * Math.PI)); location.X -= (float) (height * Math.Cos((angle + 90.0) / 360.0 * 2 * Math.PI)); points[1] = location; location.Y += (float) (width * Math.Cos((angle + 90.0) / 360.0 * 2 * Math.PI)); location.X -= (float) (width * Math.Sin((angle + 90.0) / 360.0 * 2 * Math.PI)); points[0] = location; } else { // Unformatted text float topAdjust = symdef.FontAscent; float height = symdef.FontEmHeight; float descent = symdef.FontDescent; points = new PointF[5]; location.Y -= (float) (topAdjust * Math.Sin((angle + 90.0) / 360.0 * 2 * Math.PI)); location.X -= (float) (topAdjust * Math.Cos((angle + 90.0) / 360.0 * 2 * Math.PI)); points[0] = location; location.Y -= (float) (descent * Math.Sin((angle + 90.0) / 360.0 * 2 * Math.PI)); location.X -= (float) (descent * Math.Cos((angle + 90.0) / 360.0 * 2 * Math.PI)); if (symdef.FontAlignment == TextSymDefAlignment.Right) { location.Y += (float) (size.Width * Math.Cos((angle + 90.0) / 360.0 * 2 * Math.PI)); location.X -= (float) (size.Width * Math.Sin((angle + 90.0) / 360.0 * 2 * Math.PI)); } else if (symdef.FontAlignment == TextSymDefAlignment.Center) { location.Y += (float) ((size.Width/2) * Math.Cos((angle + 90.0) / 360.0 * 2 * Math.PI)); location.X -= (float) ((size.Width/2) * Math.Sin((angle + 90.0) / 360.0 * 2 * Math.PI)); } points[1] = location; location.Y -= (float) (size.Width * Math.Cos((angle + 90.0) / 360.0 * 2 * Math.PI)); location.X += (float) (size.Width * Math.Sin((angle + 90.0) / 360.0 * 2 * Math.PI)); points[2] = location; location.Y += (float) ((descent+height) * Math.Sin((angle + 90.0) / 360.0 * 2 * Math.PI)); location.X += (float) ((descent+height) * Math.Cos((angle + 90.0) / 360.0 * 2 * Math.PI)); points[3] = location; location.Y += (float) (size.Width * Math.Cos((angle + 90.0) / 360.0 * 2 * Math.PI)); location.X -= (float) (size.Width * Math.Sin((angle + 90.0) / 360.0 * 2 * Math.PI)); points[4] = location; } OcadCoord[] coords = new OcadCoord[points.Length]; for (int i = 0; i < coords.Length; ++i) coords[i] = OcadCoordFromPoint(points[i]); return coords; }
SymPath CreateSymPath(OcadCoord[] coords) { int dummy; bool anyCutouts; coords = FixOcadCoords(coords, false, out dummy, out anyCutouts); PointF[] points = new PointF[coords.Length]; PointKind[] kinds = new PointKind[coords.Length]; byte[] startStopFlags = null; if (anyCutouts) startStopFlags = new byte[coords.Length - 1]; for (int i = 0; i < coords.Length; ++i) { points[i] = PointFromOcadCoord(coords[i]); kinds[i] = PointKindFromOcadCoord(coords[i]); if (anyCutouts && i < coords.Length - 1) startStopFlags[i] = StartStopFlagsFromCoord(coords[i]); } return new SymPath(points, kinds, startStopFlags, false); }
OcadCoord[] CoordsFromSymPathWithHoles(SymPathWithHoles path) { OcadCoord[] firstCoords = CoordsFromSymPath(path.MainPath); SymPath[] holes = path.Holes; if (holes == null) return firstCoords; int totalLength = firstCoords.Length; OcadCoord[][] holeCoords = new OcadCoord[holes.Length][]; for (int i = 0; i < holes.Length; ++i) { holeCoords[i] = CoordsFromSymPath(holes[i]); totalLength += holeCoords[i].Length; } OcadCoord[] fullCoords = new OcadCoord[totalLength]; Array.Copy(firstCoords, 0, fullCoords, 0, firstCoords.Length); totalLength = firstCoords.Length; for (int i = 0; i < holes.Length; ++i) { Array.Copy(holeCoords[i], 0, fullCoords, totalLength, holeCoords[i].Length); fullCoords[totalLength].y |= 2; // mark beginning of hole. totalLength += holeCoords[i].Length; } return fullCoords; }
OcadCoord[] CoordsFromSymPath(SymPath path) { PointF[] points = path.Points; PointKind[] kinds = path.PointKinds; byte[] startStopFlags = path.StartStopFlags; int length = points.Length; if (path.LastPointSynthesized) length -= 1; OcadCoord[] coords = new OcadCoord[length]; for (int i = 0; i < length; ++i) { coords[i] = OcadCoordFromPoint(points[i]); switch (kinds[i]) { case PointKind.Normal: break; case PointKind.Dash: if (version >= 7) coords[i].y |= 8; break; case PointKind.Corner: coords[i].y |= 1; break; case PointKind.BezierControl: if (i > 0 && kinds[i-1] == PointKind.BezierControl) coords[i].x |= 2; else coords[i].x |= 1; break; } if (startStopFlags != null && i < startStopFlags.Length) { if ((startStopFlags[i] & SymPath.DOUBLE_LEFT_STARTSTOPFLAG) != 0) coords[i].x |= 4; if ((startStopFlags[i] & SymPath.DOUBLE_RIGHT_STARTSTOPFLAG) != 0) coords[i].y |= 4; if ((startStopFlags[i] & SymPath.AREA_BOUNDARY_STARTSTOPFLAG) != 0) coords[i].x |= 8; } } return coords; }
public void Read(BinaryReader reader, int version) { LowerLeft = new OcadCoord(); LowerLeft.Read(reader); UpperRight = new OcadCoord(); UpperRight.Read(reader); if (version <= 8) { Pos = reader.ReadInt32(); Len = reader.ReadInt16(); Sym = reader.ReadInt16(); } else { Pos = reader.ReadInt32(); Len = reader.ReadInt32(); Sym = reader.ReadInt32(); ObjType = reader.ReadByte(); Rex = reader.ReadByte(); Status = reader.ReadByte(); ViewType = reader.ReadByte(); Color = reader.ReadInt16(); reader.ReadInt16(); ImpLayer = reader.ReadInt16(); reader.ReadInt16(); } }
// Is this OCAD coordinate a left-double-ine cutout? static bool IsOcadCoordLeftCutOut(OcadCoord coord) { if ((coord.x & 4) != 0) return true; else return false; }
PointF[] PointsFromOcadCoord(OcadCoord[] coords) { PointF[] pts = new PointF[coords.Length]; for (int i = 0; i < coords.Length; ++i) pts[i] = PointFromOcadCoord(coords[i]); return pts; }
// Is this OCAD coordinate a right-double-ine cutout? static bool IsOcadCoordRightCutOut(OcadCoord coord) { if ((coord.y & 4) != 0) return true; else return false; }
// Convert flags in the OCAD coord to the sympath start/stop flags. byte StartStopFlagsFromCoord(OcadCoord coord) { byte b = 0; if (IsOcadCoordLeftCutOut(coord)) b |= SymPath.DOUBLE_LEFT_STARTSTOPFLAG; if (IsOcadCoordRightCutOut(coord)) b |= SymPath.DOUBLE_RIGHT_STARTSTOPFLAG; if (IsOcadCoordBoundaryCutOut(coord)) b |= SymPath.AREA_BOUNDARY_STARTSTOPFLAG; return b; }
// Creates holes, and also closes the path (and holes) SymPathWithHoles CreateAreaSymPath(OcadCoord[] coords) { int numHoles; bool anyCutouts; coords = FixOcadCoords(coords, true, out numHoles, out anyCutouts); SymPath[] holes; if (numHoles > 0) holes = new SymPath[numHoles]; else holes = null; SymPath path = null; // Pass 2: allocate the correct sizes of arrays and fill them in int startIndex = 0; int holeNumber = -1; for (int i = 1; i <= coords.Length; ++i) { if (i == coords.Length || IsOcadCoordHoleStart(coords[i])) { // Found the end of the main path or hole. int size = i - startIndex; int arraySize = size; // Make a closed path by duplicating first coord? bool closed = (size <= 1 || PointFromOcadCoord(coords[i-1]) != PointFromOcadCoord(coords[startIndex])); if (closed) { ++arraySize; } PointF[] points = new PointF[arraySize]; PointKind[] kinds = new PointKind[arraySize]; byte[] startStopFlags = null; if (anyCutouts) startStopFlags = new byte[arraySize - 1]; for (int pointIndex = 0; pointIndex < size; ++pointIndex) { points[pointIndex] = PointFromOcadCoord(coords[pointIndex + startIndex]); kinds[pointIndex] = PointKindFromOcadCoord(coords[pointIndex + startIndex]); if (startStopFlags != null && pointIndex < startStopFlags.Length) startStopFlags[pointIndex] = StartStopFlagsFromCoord(coords[pointIndex + startIndex]); } if (closed) { points[arraySize - 1] = PointFromOcadCoord(coords[startIndex]); kinds[arraySize - 1] = PointKindFromOcadCoord(coords[startIndex]); } SymPath p = new SymPath(points, kinds, startStopFlags, closed); if (holeNumber == -1) path = p; else holes[holeNumber] = p; ++holeNumber; startIndex = i; } } return new SymPathWithHoles(path, holes); }
public static OcadCoord[] ReadCoords(BinaryReader reader, int nCoord) { OcadCoord[] coords = new OcadCoord[nCoord]; for (int i = 0; i < nCoord; ++i) { coords[i].Read(reader); } return coords; }