public static bool LinesCross(Vector3 aStart, Vector3 aEnd, Vector3 bStart, Vector3 bEnd) { var slopeA = Slope.FromPoints(aStart, aEnd); var slopeB = Slope.FromPoints(bStart, bEnd); var intersection = slopeA.CalculateIntersection(slopeB); if (intersection.Type == IntersectionType.NONE) { return(false); } if (intersection.Type == IntersectionType.OVERLAP) { return(true); } var p = intersection.Point; var minAX = Mathf.Min(aStart.x, aEnd.x); var maxAX = Mathf.Max(aStart.x, aEnd.x); var minAZ = Mathf.Min(aStart.z, aEnd.z); var maxAZ = Mathf.Max(aStart.z, aEnd.z); if (p.x < minAX || p.x > maxAX || p.z < minAZ || p.z > maxAZ) { return(false); } var minBX = Mathf.Min(bStart.x, bEnd.x); var maxBX = Mathf.Max(bStart.x, bEnd.x); var minBZ = Mathf.Min(bStart.z, bEnd.z); var maxBZ = Mathf.Max(bStart.z, bEnd.z); return(!(p.x < minBX || p.x > maxBX || p.z < minBZ || p.z > maxBZ)); }
static void Day3(List <string> mapInput) { Slope slope = new Slope(right: 3, down: 1); ConsoleHelper.PrintHeader("DAY 03 - part 01"); var map = new Map(mapInput); map.TraverseDown(slope); var answer = map.TreeCount; Console.WriteLine($"Answer: {answer}"); List <Slope> slopes = new List <Slope>() { new Slope(right: 1, down: 1), new Slope(right: 3, down: 1), new Slope(right: 5, down: 1), new Slope(right: 7, down: 1), new Slope(right: 1, down: 2) }; ConsoleHelper.PrintHeader("DAY 03 - part 02"); map = new Map(mapInput); long answerPart2 = map.Benchmark(slopes); Console.WriteLine($"Answer: {answerPart2}"); }
public Fraction Tangent(LineFr that) // tan(theta) = (m1 - m2)/(1 + (m1*m2)) { if (isParallelTo(that)) { return(Fraction.Zero); } if (IsVertical()) { if (that.IsHorizontal()) { return(-1); } return(Slope.Inverse()); } if (that.IsVertical()) { if (that.IsHorizontal()) { return(-1); } return(Slope); } if (isPerpendicularTo(that)) { return(-1); } return((Slope - that.Slope) / (1 + Slope * that.Slope)); }
public void Check_that_slopes_do_not_overlap() { var verticalFromOrigo = Slope.FromPoints(Vector3.zero, Vector3.forward); var horizontalFromOrigo = Slope.FromPoints(Vector3.zero, Vector3.right); var verticalOffset = Slope.FromPoints(new Vector3(1, 0, 0), new Vector3(1, 0, 1)); var horizontalOffset = Slope.FromPoints(new Vector3(0, 0, 1), new Vector3(2, 0, 1)); var upRightFromOrigo = Slope.FromPoints(Vector3.zero, new Vector3(1, 0, 1)); var upRightOffsetFromOrigo = Slope.FromPoints(new Vector3(1, 0, 2), new Vector3(2, 0, 3)); var downRightFromOrigo = Slope.FromPoints(Vector3.zero, new Vector3(1, 0, -1)); var downRightOffsetFromOrigo = Slope.FromPoints(new Vector3(1, 0, 1), new Vector3(2, 0, 0)); var fromOrigo = Slope.FromPoints(Vector3.zero, new Vector3(1, 0, 3)); var offsetFromOrigo = Slope.FromPoints(new Vector3(1, 0, 1), new Vector3(2, 0, 4)); checkNotOverlap(verticalFromOrigo, horizontalFromOrigo); checkNotOverlap(verticalFromOrigo, verticalOffset); checkNotOverlap(verticalFromOrigo, horizontalOffset); checkNotOverlap(verticalFromOrigo, upRightFromOrigo); checkNotOverlap(verticalFromOrigo, upRightOffsetFromOrigo); checkNotOverlap(verticalFromOrigo, upRightFromOrigo); checkNotOverlap(verticalFromOrigo, upRightOffsetFromOrigo); checkNotOverlap(verticalFromOrigo, downRightFromOrigo); checkNotOverlap(verticalFromOrigo, downRightOffsetFromOrigo); checkNotOverlap(verticalFromOrigo, fromOrigo); checkNotOverlap(verticalFromOrigo, offsetFromOrigo); }
public void SolvePartTwo() { ReadInputFile(); var slopeOne = new Slope(1, 1); var slopeOneTrees = CountTreesGivenSlope(slopeOne); var slopeTwo = new Slope(3, 1); var slopeTwoTrees = CountTreesGivenSlope(slopeTwo); var slopeThree = new Slope(5, 1); var slopeThreeTrees = CountTreesGivenSlope(slopeThree); var slopeFour = new Slope(7, 1); var slopeFourTrees = CountTreesGivenSlope(slopeFour); var slopeFive = new Slope(1, 2); var slopeFiveTrees = CountTreesGivenSlope(slopeFive); var treeMultiple = (long)slopeOneTrees * slopeTwoTrees * slopeThreeTrees * slopeFourTrees * slopeFiveTrees; Console.WriteLine(string.Format(DayThreeConstants.DayThreePartTwoAnswer, slopeOne.Right, slopeOne.Down, slopeOneTrees, slopeTwo.Right, slopeTwo.Down, slopeTwoTrees, slopeThree.Right, slopeThree.Down, slopeThreeTrees, slopeFour.Right, slopeFour.Down, slopeFourTrees, slopeFive.Right, slopeFive.Down, slopeFiveTrees, treeMultiple.ToString("##,###"))); }
// Samling av metoder för Geoprocessor. #region Geoproccesing Methods // Skapar lutningslager. public IRasterLayer createSlope(System.String inRaster, System.String outPath) { if (slope != null) { return(slope); } IRasterLayer rLayer = new RasterLayer(); if (inRaster == "" || outPath == "") { MessageBox.Show("Check your rasters"); } else { Geoprocessor gp = new Geoprocessor(); gp.OverwriteOutput = true; //gp.AddOutputsToMap = false; Slope slopeTool = new Slope(); slopeTool.in_raster = inRaster; slopeTool.out_raster = outPath; IGeoProcessorResult geoProcessorResult = (IGeoProcessorResult)gp.Execute(slopeTool, null); rLayer.CreateFromFilePath(outPath); slope = rLayer; } return(rLayer); }
private void checkIntersect(Slope slopeA, Slope slopeB, Vector3 intersectionPoint) { var intersection = slopeA.CalculateIntersection(slopeB); Assert.AreEqual(IntersectionType.INTERSECT, intersection.Type); TestMethods.AreEqualIsh(intersectionPoint, intersection.Point); }
/// <summary> 将一级边坡中的所有子边坡进行合并 </summary> /// <param name="subSlopes">某一级边坡中的所有子边坡集合</param> /// <param name="fill"></param> /// <param name="dir"></param> /// <returns></returns> private Slope MergeSubSlopes(List <Slope> subSlopes, bool fill, MergeProtectionDirection dir) { var innerS = subSlopes[0]; var outerS = subSlopes[subSlopes.Count - 1]; var s = new Slope(innerS.GetMainLevel(), innerS.InnerPoint, outerS.OuterPoint); switch (dir) { case MergeProtectionDirection.顶部: s.ProtectionMethod = fill ? innerS.ProtectionMethod : outerS.ProtectionMethod; break; case MergeProtectionDirection.底部: s.ProtectionMethod = fill ? outerS.ProtectionMethod : innerS.ProtectionMethod; break; case MergeProtectionDirection.靠近中线: s.ProtectionMethod = innerS.ProtectionMethod; break; case MergeProtectionDirection.远离中线: s.ProtectionMethod = outerS.ProtectionMethod; break; default: s.ProtectionMethod = null; break; } return(s); }
public ActionResult RecommendUsers(string userName) { User user; using (RecommenderContext db = new RecommenderContext()) { user = db.Users.Where(u => u.Name == userName).FirstOrDefault(); } Slope slope = new Slope(); var recommendedUsers = slope.GetRecommendations(user); foreach (var u in recommendedUsers) { using (RecommenderContext db = new RecommenderContext()) { db.UserToUser.Add(new UserToUser() { User1 = user, User2 = u.Key }); db.SaveChanges(); } } return(RedirectToAction("Index", new { userName = userName })); }
public override int GetHashCode() { unchecked { return((Slope.GetHashCode() * 397) ^ Intercept.GetHashCode()); } }
public void SlopeIsWorking() { var raster = Raster.Open(Path.Combine("Data", "kriging.bgd")); var actual = Slope.GetSlope(raster, 1, true, null); try { Assert.IsNotNull(actual); Assert.AreEqual(raster.Extent, actual.Extent); Assert.AreEqual(raster.NumColumns, actual.NumColumns); Assert.AreEqual(raster.NumRows, actual.NumRows); Assert.AreEqual(raster.CellHeight, actual.CellHeight); Assert.AreEqual(raster.CellWidth, actual.CellWidth); // Test that some output values are non zeros and non NoData var existsSomeValidValues = false; for (int i = 0; i < raster.NumRows; i++) { for (int j = 0; j < raster.NumColumns; j++) { if (raster.Value[i, j] != 0 && raster.Value[i, j] != raster.NoDataValue) { existsSomeValidValues = true; goto finCycle; } } } finCycle: Assert.IsTrue(existsSomeValidValues); } finally { File.Delete(actual.Filename); } }
public void Check_that_slopes_overlap() { var verticalFromOrigo = Slope.FromPoints(Vector3.zero, Vector3.forward); var horizontalFromOrigo = Slope.FromPoints(Vector3.zero, Vector3.right); var verticalOffset = Slope.FromPoints(new Vector3(1, 0, 0), new Vector3(1, 0, 1)); var horizontalOffset = Slope.FromPoints(new Vector3(0, 0, 1), new Vector3(2, 0, 1)); var upRightFromOrigo = Slope.FromPoints(Vector3.zero, new Vector3(1, 0, 1)); var upRightOffsetFromOrigo = Slope.FromPoints(new Vector3(1, 0, 2), new Vector3(2, 0, 3)); var downRightFromOrigo = Slope.FromPoints(Vector3.zero, new Vector3(1, 0, -1)); var downRightOffsetFromOrigo = Slope.FromPoints(new Vector3(1, 0, 1), new Vector3(2, 0, 0)); var fromOrigo = Slope.FromPoints(Vector3.zero, new Vector3(1, 0, 3)); var offsetFromOrigo = Slope.FromPoints(new Vector3(1, 0, 1), new Vector3(2, 0, 4)); checkOverlapsSelf(verticalFromOrigo); checkOverlapsSelf(horizontalFromOrigo); checkOverlapsSelf(verticalOffset); checkOverlapsSelf(horizontalOffset); checkOverlapsSelf(upRightFromOrigo); checkOverlapsSelf(upRightOffsetFromOrigo); checkOverlapsSelf(downRightFromOrigo); checkOverlapsSelf(downRightOffsetFromOrigo); checkOverlapsSelf(fromOrigo); checkOverlapsSelf(offsetFromOrigo); }
/// <summary> /// Returns the average curvature of the substroke /// </summary> public double getAvgCurvature(Substroke sub) { this.arclength = new ArcLength(sub.Points); this.slope = new Slope(sub.Points); this.curve = new Curvature(sub.Points, arclength.Profile, slope.TanProfile); return(curve.AverageCurvature); }
public void TraverseDown(Slope slope) { while (Position.Y < _height - 1) { Move(slope); } }
/// <summary> 检查边坡是否与指定的标高相交,并返回交点在 AutoCAD 中的几何坐标 </summary> /// <param name="slp"></param> /// <param name="ele"></param> /// <param name="intersPt">返回交点</param> /// <returns></returns> private static bool ValidateElevation(SlopeLine slp, CutMethod method, double ele, out Point2d intersPt, out Slope slopeSeg) { intersPt = Point2d.Origin; slopeSeg = null; var slpData = slp.XData; var sec = slp.Section; var cutY = GetCutY(slpData, sec, method, ele); // sec.GetYFromElev(ele); // 指定的标高在此断面中所对应的 AutoCAD 中的坐标Y值 const double tolerance = 0.01; foreach (var seg in slpData.Slopes) { bool within = (seg.TopPoint.Y - cutY >= tolerance) && (cutY - seg.BottomPoint.Y >= tolerance); if (within) // 说明此子边坡与指定的标高相交 { var l = new LineSegment2d(new Point2d(seg.BottomPoint.X, seg.BottomPoint.Y), new Point2d(seg.TopPoint.X, seg.TopPoint.Y)); var intersPts = l.IntersectWith(new Line2d(new Point2d(0, cutY), new Vector2d(1, 0))); if (intersPts != null) { slopeSeg = seg; intersPt = intersPts[0]; return(true); } } } return(false); }
public void UpdateEntry(double currentPrice) { if (!_isWaitSlope) { if (PositonType == MarketPosition.Long && currentPrice > _currentSlope.Price + _strategy.SwingHorizontal) { if (currentPrice < _rayContainer.RealRayPrice(_rayContainer.EntryRay)) { SetVariablesWithoutStop(); return; } _lastSlope = _currentSlope; SetStopRay(LocalMin(0, _currentSlope.Bar, ref _lastMinimumOrMaximum) - _strategy.StopLevel); SavingSlopeAndEmail(); } else if (PositonType == MarketPosition.Short && currentPrice < _currentSlope.Price - _strategy.SwingHorizontal) { if (currentPrice > _rayContainer.RealRayPrice(_rayContainer.EntryRay)) { SetVariablesWithoutStop(); return; } _lastSlope = _currentSlope; SetStopRay(LocalMax(0, _currentSlope.Bar, ref _lastMinimumOrMaximum) + _strategy.StopLevel); SavingSlopeAndEmail(); } } }
private Slope PostResult(int till, Slope result) { while (result.Bar + 1 < till) { if (PositonType == MarketPosition.Long) { if (_strategy.High[result.Bar + 1] >= _strategy.High[result.Bar]) { result = new Slope(result.Bar + 1, _strategy.High[result.Bar + 1]); } else { break; } } else { if (_strategy.Low[result.Bar + 1] <= _strategy.Low[result.Bar]) { result = new Slope(result.Bar + 1, _strategy.Low[result.Bar + 1]); } else { break; } } } return(result); }
public MultiplyConform(float[] fixed_points, Edge e, Slope s) { this.gen_opts = new MultiplyConformOpt(fixed_points, e, s); this.gen_type = GeneratorType.MultiplyConform; this.draw_editor = true; Debug.Log("is mul conf opt: " + this.gen_opts.GetType()); }
private int CountTreesGivenSlope(Slope slope) { int horizontalPosition = 0, verticalPosition = 0, treeCount = 0; if (!InputLines.Any()) { return(treeCount); } var mapWidth = InputLines.ElementAt(0).Length; var mapLength = InputLines.Count(); while (verticalPosition < mapLength) { if (InputLines.ElementAt(verticalPosition)[horizontalPosition].Equals('#')) { treeCount++; } horizontalPosition = (horizontalPosition + slope.Right) % mapWidth; verticalPosition += slope.Down; } return(treeCount); }
/// <summary> /// Creates a new roofing section rectangle /// </summary> /// <param name="rect">The bounds of the rectangle</param> /// <param name="goesUp">Specifies the orientation of the rectangle</param> /// <param name="tent">Specifies that the rectangle is tent shaped</param> /// <param name="sloped">Specifies that the rectangle is sloped (half roof)</param> /// <param name="slope">The slope side if the piece is sloped</param> public RoofRect(Rectangle rect, bool goesUp, bool tent, bool sloped, Slope slope) { Rectangle = rect; m_GoesUp = goesUp; m_Tent = tent; m_Sloped = sloped; m_Slope = slope; }
public static double?Angle(double?angle, Slope to, Slope from) { if (angle == null) { return(null); } return(Angle((double)angle, to, from)); }
private async Task <long> Part1() { var map = await ParseInput(); var slope = new Slope(3, 1); return(map.CountTrees(slope)); }
public Map Move(Slope slope) { var position = CalculatePosition(slope); SetPosition(position); return(this); }
/** * Return the slope of a given tile * @param tile Tile to compute slope of * @param h If not \c NULL, pointer to storage of z height * @return Slope of the tile, except for the HALFTILE part */ /*inline*/ public static Slope GetTilePixelSlope(TileIndex tile, ref int h) { Slope s = GetTileSlope(tile, ref h); //if (h != NULL) * h *= (int)TileConstants.TILE_HEIGHT; return(s); }
/// <summary> /// Creates a new roofing section rectangle /// </summary> /// <param name="rect">The bounds of the rectangle</param> /// <param name="goesUp">Specifies the orientation of the rectangle</param> /// <param name="tent">Specifies that the rectangle is tent shaped</param> /// <param name="sloped">Specifies that the rectangle is sloped (half roof)</param> /// <param name="slope">The slope side if the piece is sloped</param> public RoofRect(System.Drawing.Rectangle rect, bool goesUp, bool tent, bool sloped, Slope slope) { m_Rectangle = rect; m_GoesUp = goesUp; m_Tent = tent; m_Sloped = sloped; m_Slope = slope; }
/// <summary> /// Creates a new roofing section rectangle /// </summary> /// <param name="rect">The bounds of the rectangle</param> /// <param name="goesUp">Specifies the orientation of the rectangle</param> /// <param name="tent">Specifies that the rectangle is tent shaped</param> /// <param name="sloped">Specifies that the rectangle is sloped (half roof)</param> /// <param name="slope">The slope side if the piece is sloped</param> public RoofRect( System.Drawing.Rectangle rect, bool goesUp, bool tent, bool sloped, Slope slope ) { m_Rectangle = rect; m_GoesUp = goesUp; m_Tent = tent; m_Sloped = sloped; m_Slope = slope; }
/// <summary> 将子边坡按指定的交点进行剪切,并返回剪切后的新的子边坡集合 </summary> /// <param name="data"></param> /// <param name="intersSeg"></param> /// <param name="intersPt"></param> public List <Slope> CutSlopeSegment(SlopeData data, Slope intersSeg, Point3d intersPt) { var slopeSegs = data.Slopes; var newSegs = new List <Slope>(); int mainLevel = intersSeg.GetMainLevel(); // 1. 先添加交叉边坡之前的子边坡 int sumBefore = 0; for (int id = 0; id < slopeSegs.Count; id++) { var slp = slopeSegs[id]; if (slp.GetMainLevel() != mainLevel) { newSegs.Add(slp); sumBefore += 1; } else { break; } } // 2. 对交叉处的子边坡进行处理 var sumMainLevel = slopeSegs.Count(r => r.GetMainLevel() == mainLevel); // 此子边坡中已经有多少个更细的子边坡 int subLevelInters = intersSeg.GetSubLevel(); // 分割后,最内侧的子边坡的Index为 n.1,最外侧的子边坡的Index为 n.9, int subL = 1; for (int i = 0; i < sumMainLevel; i++) { // 此循环的过程中改写有一个子边坡与指定的相交边坡是同一个边坡 var seg = slopeSegs[sumBefore + i]; if (seg.GetSubLevel() == subLevelInters) { var seg1 = new Slope(Slope.GetIndex(mainLevel, subL), intersSeg.InnerPoint, intersPt); var seg9 = new Slope(Slope.GetIndex(mainLevel, subL + 1), intersPt, intersSeg.OuterPoint); SetProtectionMethod(intersSeg, seg1, seg9); // newSegs.Add(seg1); newSegs.Add(seg9); subL += 2; } else { seg.SetIndex(mainLevel, subL); newSegs.Add(seg); subL += 1; } } // 修改最后一个的Index // newSegs[sumBefore + sumMainLevel].SetIndex(mainLevel, 9); // 3. 接着添加交叉边坡之后的子边坡 for (int i = sumBefore + sumMainLevel; i < slopeSegs.Count; i++) { newSegs.Add(slopeSegs[i]); } return(newSegs); }
public void UpdateSlopeLine(Slope slope) { double price = _strategy.Instrument.MasterInstrument.Round2TickSize(slope.Price); _ray = _strategy.DrawRay("Slope", false, slope.Bar, price, slope.Bar - 3, price, SlopeLineColor, DashStyle.Solid, 2); _dot = _strategy.DrawDot("slopeDot", false, 0, price, Color.Black); _text = _strategy.DrawText("SlopeText", TextForma(price), 0, price, Color.Black); _strategy.ChartControl.ChartPanel.Invalidate(); }
/** * Get the height ('z') of a bridge. * @param tile the bridge ramp tile to get the bridge height from * @return the height of the bridge. */ int GetBridgeHeight(TileIndex t) { int h; Slope tileh = TileMap.GetTileSlope(t, ref h); Foundation f = GetBridgeFoundation(tileh, DiagDirToAxis(GetTunnelBridgeDirection(t))); /* one height level extra for the ramp */ return(h + 1 + ApplyFoundationToSlope(f, ref tileh)); }
public IEnumerable <IniValueObject> ExportParameters() { List <IniValueObject> obj = new List <IniValueObject>(); obj.Add(new IniValueObject(AcceptsConfigs, "Slope", Slope.ToString())); obj.Add(new IniValueObject(AcceptsConfigs, "Slip", AllowedSlip.ToString())); return(obj); }
public double get_b() { if (true == Slope.isVertical()) { return(Double.NaN); } return(this.StartPoint.z.Value - (StartPoint.x * Slope.getAsSlope() * this.advanceDirection)); }
/// <summary> /// Adds a vertex to the roof data lying perpendicular to the Y axis of its roof edge /// </summary> /// <param name="x1">The left x coordinate of the section</param> /// <param name="x2">The right x coordinate of the section</param> /// <param name="y">The y coordinate of the section</param> /// <param name="hLimit">The limit in height for this roof</param> /// <param name="slope">The type of slope for this roof</param> /// <returns>True if the section has been correctly added</returns> private bool AddVertexX( int x1, int x2, int y, int hLimit, Slope slope ) { bool added = false; int height = 1; while ( x2 >= x1 ) { if ( slope == Slope.None || slope == Slope.Right ) { // Issue 10 - Update the code to Net Framework 3.5 - http://code.google.com/p/pandorasbox3/issues/detail?id=10 - Smjert if ( m_RoofImage.Data[ x2 + y * m_RoofImage.Width ] < height ) // Issue 10 - End { m_RoofImage.Data[ x2 + y * m_RoofImage.Width ] = height; added = true; } x2--; } if ( slope == Slope.None || slope == Slope.Left ) { // Issue 10 - Update the code to Net Framework 3.5 - http://code.google.com/p/pandorasbox3/issues/detail?id=10 - Smjert if ( m_RoofImage.Data[ x1 + y * m_RoofImage.Width ] < height ) // Issue 10 - End { m_RoofImage.Data[ x1 + y * m_RoofImage.Width ] = height; added = true; } x1++; } if ( height < hLimit ) { height++; } } return added; }
/// <summary> /// Adds a roof section perpendicular to the X axis /// </summary> /// <param name="y1">The lower y coordinate</param> /// <param name="y2">The upper y coordinate</param> /// <param name="x">The x coordinate (fixed)</param> /// <param name="hLimit">The height limit for this roof section</param> /// <param name="slope">The slope for this section</param> /// <returns>True if the section has been added</returns> private bool AddVertexY( int y1, int y2, int x, int hLimit, Slope slope ) { bool added = false; int height = 1; while ( y2 >= y1 ) { if ( slope == Slope.None || slope == Slope.Top ) { // Issue 10 - Update the code to Net Framework 3.5 - http://code.google.com/p/pandorasbox3/issues/detail?id=10 - Smjert if ( m_RoofImage.Data[ x + y2 * m_RoofImage.Width ] < height ) // Issue 10 - End { m_RoofImage.Data[ x + y2 * m_RoofImage.Width ] = height; added = true; } y2--; } if ( slope == Slope.None || slope == Slope.Bottom ) { // Issue 10 - Update the code to Net Framework 3.5 - http://code.google.com/p/pandorasbox3/issues/detail?id=10 - Smjert if ( m_RoofImage.Data[ x + y1 * m_RoofImage.Width ] < height ) // Issue 10 - End { m_RoofImage.Data[ x + y1 * m_RoofImage.Width ] = height; added = true; } y1++; } if ( height < hLimit ) { height++; } } return added; }
/** * @brief Scan through image looking for line segments of length slopesz (on either X or Y axis). * Measure their slope and enter them into 'slopes' list. * Remove each used segment from blacks[,] array. * Overwrite the segments with red in the bitmap image for debugging. */ public static int FindSegments () { byte lastBlack, thisBlack; int ni, nn, xx, yy; int nsegs = 0; int[] transits = new int[4]; for (int cy = slopesz / 2; cy < height - slopesz / 2 - 1; cy ++) { for (int cx = slopesz / 2; cx < width - slopesz / 2 - 1; cx ++) { /* * Make sure we have a black pixel in center of box. */ if (blacks[cy,cx] == 0) goto next; /* * Find first white-to-black transition around edge of box. */ lastBlack = TransitBlack (cx, cy, 0); for (ni = 0; ++ ni < 4 * slopesz;) { thisBlack = TransitBlack (cx, cy, ni); if ((lastBlack == 0) && (thisBlack != 0)) break; lastBlack = thisBlack; } if (ni >= 4 * slopesz) goto next; /* * Find remaining transitions going around the edge. * There should be exactly four, starting with a white-to-black. */ int ntrans = 0; for (nn = 0; nn < 4 * slopesz; nn ++) { int nt = (ni + nn) % (4 * slopesz); thisBlack = TransitBlack (cx, cy, nt); if (thisBlack != lastBlack) { if (ntrans == 4) goto next; transits[ntrans++] = nt; } lastBlack = thisBlack; } if (ntrans != 4) goto next; /* * Make the black-to-white transitions to point to the black pixel. * Leave the white-to-black transitions pointing at the black pixel. * * This lets, eg, a single-pixel width horizontal line have a slope * of exactly 0.0. */ transits[1] = (transits[1] + 4 * slopesz - 1) % (4 * slopesz); transits[3] = (transits[3] + 4 * slopesz - 1) % (4 * slopesz); /* * Make sure the transitions are on opposite edges. * This will tell us that the line is straight and going through the center. */ int wbdiff = 4 * slopesz + transits[0] - transits[2]; int bwdiff = 4 * slopesz + transits[1] - transits[3]; wbdiff %= 4 * slopesz; bwdiff %= 4 * slopesz; if (wbdiff < 2 * slopesz - 1) goto next; if (wbdiff > 2 * slopesz + 1) goto next; if (bwdiff < 2 * slopesz - 1) goto next; if (bwdiff > 2 * slopesz + 1) goto next; /* * Get XY of all transitions. */ int bw1x, bw1y, bw2x, bw2y; // black-to-white transitions int wb1x, wb1y, wb2x, wb2y; // white-to-black transitions TransitToXY (cx, cy, transits[0], out wb1x, out wb1y); TransitToXY (cx, cy, transits[1], out bw1x, out bw1y); TransitToXY (cx, cy, transits[2], out wb2x, out wb2y); TransitToXY (cx, cy, transits[3], out bw2x, out bw2y); /* * Calculate slope of edges. * * wb1 bw1 * - [*] * [-] - - * - - * * - - * - - * * - - * - - - * * - * - - - * * - * - - - [-] * [*] wb2 * bw2 */ int adx = wb2x - bw1x; int ady = wb2y - bw1y; int bdx = bw2x - wb1x; int bdy = bw2y - wb1y; if (adx < 0) { adx = -adx; ady = -ady; } if (bdx < 0) { bdx = -bdx; bdy = -bdy; } int avgdx = (adx + bdx) / 2; int avgdy = (ady + bdy) / 2; /* * Check for centered tick mark. */ if (!HasCenteredTickMark (cx, cy, avgdx, avgdy)) goto next; bool debug = false; if (debug) { Console.WriteLine ("FindSegments*: " + cx + "," + cy + " " + avgdx + "," + avgdy); Console.WriteLine ("FindSegments*: " + transits[0] + " " + transits[1] + " " + transits[2] + " " + transits[3]); Console.WriteLine ("FindSegments*: wb1=" + (wb1x + slopesz / 2 - cx) + "," + (wb1y + slopesz / 2 - cy)); Console.WriteLine ("FindSegments*: bw1=" + (bw1x + slopesz / 2 - cx) + "," + (bw1y + slopesz / 2 - cy)); Console.WriteLine ("FindSegments*: wb2=" + (wb2x + slopesz / 2 - cx) + "," + (wb2y + slopesz / 2 - cy)); Console.WriteLine ("FindSegments*: bw2=" + (bw2x + slopesz / 2 - cx) + "," + (bw2y + slopesz / 2 - cy)); Console.WriteLine ("FindSegments*: avgd=" + avgdy + "/" + avgdx + "=" + ((double)avgdy / (double)avgdx)); char[] line = "".PadRight (2 * slopesz + 1).ToCharArray (); for (yy = -slopesz/2; yy <= slopesz/2; yy ++) { for (xx = -slopesz/2; xx <= slopesz/2; xx ++) { line[2*xx+slopesz] = (blacks[cy+yy,cx+xx] == 0) ? '-' : '*'; } Console.WriteLine ("FindSegments*: " + new string (line)); } } /* * Add segment to list of known slopes. */ Slope sl; XY delta = new XY (avgdx, avgdy); if (!slopes.TryGetValue (delta, out sl)) { sl = new Slope (); sl.dx = delta.x; sl.dy = delta.y; slopes.Add (delta, sl); } sl.xys.AddLast (new XY (cx, cy)); nsegs ++; /* * Draw red line in image for debugging. */ DrawLine (cx - avgdx / 2, cy - avgdy / 2, cx + avgdx / 2, cy + avgdy / 2, Color.Red); /* * Erase the blacks[,] entries so we don't try to * use these same pixels for another box. */ for (yy = -slopesz / 2; yy < slopesz / 2; yy ++) { for (xx = -slopesz / 2; xx < slopesz / 2; xx ++) { blacks[cy+yy,cx+xx] = 0; } } next:; } } return nsegs; }
/** * @brief Scan the original image to determine position and slope of all lat/lon lines. * @returns bestSlope = most frequent slope encountered * recipSlope = the corresponding reciprocal slope * latLonSlopeX,Y = resultant slope */ public static void FindLatLonLines () { /* * Open original image file. */ bmp = new Bitmap (pngname); origWidth = bmp.Width; origHeight = bmp.Height; /* * Get strict black/white pixel array for easier decoding. */ Monochromaticise (bmp); if (stages) bmp.Save ("stage1.png", System.Drawing.Imaging.ImageFormat.Png); /* * Clear off border lines. Sometimes they get confused with lat/lons. */ ClearBorderLines (); if (stages) bmp.Save ("stage1m.png", System.Drawing.Imaging.ImageFormat.Png); /* * Filter out every BLOCK x BLOCK or larger size of black pixels. * This gets rid of things like runways and buildings. */ ClearLargeBlobs (); if (stages) bmp.Save ("stage2.png", System.Drawing.Imaging.ImageFormat.Png); /* * Filter out every little blob that is smaller than MAXWH. * This gets rid of most characters. */ ClearSmallBlobs (); if (stages) bmp.Save ("stage3.png", System.Drawing.Imaging.ImageFormat.Png); /* * Find sloped line segments with tick marks. * Try various sizes as the tick mark must fit completely inside the box. */ for (slopesz = 24; slopesz <= 38; slopesz += 2) { FindSegments (); } if (stages || verbose) { foreach (Slope sl in slopes.Values) { if (verbose) Console.WriteLine ("slope: " + sl.dy + "/" + sl.dx + ": " + sl.xys.Count); foreach (LongLine line in sl.GetLongLines ()) { if (!line.IsValid ()) continue; int x1 = line.begx; int y1 = line.begy; int x2 = line.endx; int y2 = line.endy; int dx = x2 - x1; int dy = y2 - y1; if (verbose) { Console.WriteLine (" line: " + x1 + "," + y1 + " .. " + x2 + "," + y2 + " = " + ((double)dy / (double)dx)); } if (stages) { for (int w = 4; w <= 8; w ++) { double d = Math.Sqrt (dx * dx + dy * dy) / 2; dx = (int)(dx / d + 0.5); dy = (int)(dy / d + 0.5); DrawLine (x1 + dy, y1 - dx, x1 - dy, y1 + dx, Color.Green); DrawLine (x2 + dy, y2 - dx, x2 - dy, y2 + dx, Color.Green); DrawLine (x1 + dy, y1 - dx, x2 + dy, y2 - dx, Color.Green); DrawLine (x1 - dy, y1 + dx, x2 - dy, y2 + dx, Color.Green); } } } } if (stages) bmp.Save ("stage4.png", System.Drawing.Imaging.ImageFormat.Png); } /* * Find slope that occurred the most times. * Assume that it is the latitude or longitude. */ foreach (Slope sl in slopes.Values) { if ((bestSlope == null) || (bestSlope.xys.Count < sl.xys.Count)) { bestSlope = sl; } } int bestdx = bestSlope.dx; int bestdy = bestSlope.dy; /* * Now take the average of the slopes of all those lines, * giving weight to the longer lines. */ bestSlope.GetFineSlope (out latLonSlopeX, out latLonSlopeY); double majorangle = Math.Atan2 (latLonSlopeY, latLonSlopeX) * 180.0 / Math.PI; if (verbose) { Console.WriteLine ("major slope " + bestdy + "/" + bestdx + " = " + latLonSlopeY + "/" + latLonSlopeX + " = " + majorangle); } double llsl = Math.Sqrt (latLonSlopeX * latLonSlopeX + latLonSlopeY * latLonSlopeY); double llsx = latLonSlopeX / llsl; double llsy = latLonSlopeY / llsl; /* * Find reciprocal slope and assume that it is the other of latitude or longitude. */ int recipdx, recipdy; foreach (Slope sl in slopes.Values) { sl.GetFineSlope (out recipdx, out recipdy); double recipl = Math.Sqrt (recipdx * recipdx + recipdy * recipdy); double recipx = recipdx / recipl; double recipy = recipdy / recipl; double dot = Math.Abs (recipx * llsx + recipy * llsy); if (dot > 2.0 / slopesz) continue; if ((recipSlope == null) || (recipSlope.xys.Count < sl.xys.Count)) { recipSlope = sl; } } if (recipSlope == null) { throw new Exception ("no reciprocal slope found"); } recipSlope.GetFineSlope (out recipdx, out recipdy); double minorangle = Math.Atan2 (recipdy, recipdx) * 180.0 / Math.PI; if (verbose) { Console.WriteLine ("minor slope " + recipSlope.dy + "/" + recipSlope.dx + " = " + recipdy + "/" + recipdx + " = " + minorangle); Console.WriteLine ("major - minor angle = " + (majorangle - minorangle)); } /* * Rotate by 90,180,270 to make it positive, ie, in range 0..89. * Then maybe rotate by -90 to put in range -44..+45. */ while ((latLonSlopeX | latLonSlopeY) < 0) { int tmp = latLonSlopeY; latLonSlopeY = -latLonSlopeX; latLonSlopeX = tmp; } if (latLonSlopeY > latLonSlopeX) { int tmp = latLonSlopeY; latLonSlopeY = -latLonSlopeX; latLonSlopeX = tmp; } if (verbose) { Console.WriteLine ("lat/lon slope = " + latLonSlopeY + "/" + latLonSlopeX + " = " + ((double)latLonSlopeY / (double)latLonSlopeX)); Console.WriteLine (" theta = " + (Math.Atan2 (latLonSlopeY, latLonSlopeX) * 180.0 / Math.PI)); } }
/** * @brief Given a list of lines within the original image, compute their * horizontal Y pixels or vertical X pixels within the rotated image. * * Input: * origWidth,origHeight = width and height of original image * portBitmap,portWidth,portHeight = rotated image * slope = collection of line segments of equal slope * * Output: * longlenverts,longlenhorzs = filled in to indicate where lat/lon lines * are in the rotated image */ public static void ComputeVertHorzLatLons (Slope slope) { // scan through each line of the given slope foreach (LongLine line in slope.GetLongLines ()) { if (!line.IsValid ()) continue; // rotate the line's endpoints from original image coords to rotated image coords XY begRot = RotateImagePoint (line.begx, line.begy, latLonSlopeX, latLonSlopeY); XY endRot = RotateImagePoint (line.endx, line.endy, latLonSlopeX, latLonSlopeY); int xdiff = begRot.x - endRot.x; int ydiff = begRot.y - endRot.y; if (xdiff < 0) xdiff = -xdiff; if (ydiff < 0) ydiff = -ydiff; // small X difference means vertical if (xdiff <= ydiff / 16) { int xavg = (begRot.x + endRot.x) / 2; if ((xavg >= 0) && (xavg < portWidth)) { longlenverts[xavg] += ydiff; } } // small Y difference means horizontal if (ydiff <= xdiff / 16) { int yavg = (begRot.y + endRot.y) / 2; if ((yavg >= 0) && (yavg < portHeight)) { longlenhorzs[yavg] += xdiff; } } } }
public float get_slopeheight(float k, float x, float m, Slope slope, float posx1, float posx2) { float height = k * (posx1 - x) + m; if (height > Math.Max(slope.leftY, slope.rightY)) height = Math.Max(slope.leftY, slope.rightY); float height2 = k * (posx2 - x) + m; if (height2 > Math.Max(slope.leftY, slope.rightY)) height2 = Math.Max(slope.leftY, slope.rightY); return Math.Max(height, height2); }
public void CollideAxis(PhysicalObject obj, Vector2 startpos, Vector2 move, Axis axis) { float xcol = 0.05f; bool touch_u = false; bool touch_r = false; bool touch_d = false; bool touch_l = false; obj.on_ladder[(int)axis] = false; Vector2 feet = new Vector2(startpos.X, startpos.Y + obj.hitbox.Y); if (axis == Axis.X) { move = new Vector2(move.X, 0); //if the ground is a slope, include the Y-movement if (obj.surface_k != 0) if (move.X * -obj.surface_k < 0) move.Y = move.X * -obj.surface_k; } else move = new Vector2(0, move.Y); obj.pos += move; int index_x = (int)obj.pos.X; int index_y = (int)obj.pos.Y; //how many tiles can the object potentially collide with int width = (int)Math.Ceiling(obj.hitbox.X) + 1; int height = (int)Math.Ceiling(obj.hitbox.Y) + 1; //get a list of all those int[][] check = new int[width * height][]; int c = 0; for (int w = 0; w < width; w++) for (int h = 0; h < height; h++) { check[c] = new int[] { w + index_x, h + index_y }; c++; } for (int i = 0; i < check.Length; i++) { Vector4 playerHitBox = new Vector4(obj.pos.X, obj.pos.Y, obj.hitbox.X, obj.hitbox.Y); //todo: other blocktypes //upper left corner of the tile int x = check[i][0]; int y = check[i][1]; if (x >= 0 && x < map[0].Length && y >= 0 && y < map.Length) { //get the tile from map Tile tile = map[y][x]; //reusable variables Vector4 tileHitBox; switch (tile.tileType) { case Tile.TileType.scenery: break; case Tile.TileType.solid: if (tile.GetType() == typeof(Slope)) { //SLABS / HALF-BLOCKS Slope slope = tile as Slope; if (slope.side == Slope.Side.floor) tileHitBox = new Vector4(x, y + (1f - slope.leftY), 1, slope.leftY); else tileHitBox = new Vector4(x, y, 1, slope.leftY); } else tileHitBox = new Vector4(x, y, 1, 1);//Regular square //Does it collide? if (VectorIntersect(playerHitBox, tileHitBox)) { if (axis == Axis.X) { if (move.X > 0) { obj.pos.X = x - obj.hitbox.X; touch_r = true; //reset velocity obj.velocity.X = xcol; } else { obj.pos.X = x + 1; touch_l = true; obj.velocity.X = -xcol; } } else { if (playerHitBox.Y < tileHitBox.Y) { obj.pos.Y = tileHitBox.Y - obj.hitbox.Y;//tile y pos - player height touch_d = true; } else { obj.pos.Y = tileHitBox.Y + tileHitBox.W;//tile y pos + tile height touch_u = true; } //reset velocity obj.velocity.Y = 0; obj.surface_k = 0; } } break; case Tile.TileType.platform: if (axis == Axis.Y) { tileHitBox = new Vector4(x, y, 1, 1);//Regular square float slope_m; float slope_k = 0; float slope_x; bool was_above = false; Slope slope = new Slope(Tile.TileType.platform, Slope.Side.floor, 0f, 0f); if (tile.GetType() == typeof(Slope)) { //SLOPES //y = kx + m //m -> plat.Y //k -> plat.right - plat.left //x -> player.x - plat.x slope = tile as Slope; if (slope.leftY == slope.rightY)//slab { if (slope.side == Slope.Side.roof)//roof slab tileHitBox = new Vector4(x, y, 1, slope.leftY); else//floor slab tileHitBox = new Vector4(x, (float)y + (1f - slope.leftY), 1, slope.leftY); } else { if (slope.side == Slope.Side.floor) { slope_m = slope.leftY; slope_k = slope.rightY - slope.leftY; slope_x = playerHitBox.X + playerHitBox.Z / 2f - (float)x; float slopeheight = get_slopeheight(slope_k, x, slope_m, slope, obj.pos.X, obj.pos.X + obj.hitbox.X); float old_slopeheight = get_slopeheight(slope_k, x, slope_m, slope, feet.X, feet.X + obj.hitbox.X); tileHitBox = new Vector4(x, (float)y + (1f - slopeheight), 1, slopeheight); was_above = feet.Y <= (float)y + (1f - old_slopeheight) + 0.0001f; } } } if (VectorIntersect(playerHitBox, tileHitBox) && (feet.Y <= tileHitBox.Y || was_above)) { //do collision if (slope.side == Slope.Side.floor) { obj.pos.Y = tileHitBox.Y - obj.hitbox.Y;//tile y pos - player height touch_d = true; } else { obj.pos.Y = tileHitBox.Y + tileHitBox.W;//tile y pos + tile height touch_u = true; } obj.velocity.Y = 0; obj.surface_k = slope_k; } } break; case Tile.TileType.ladder: tileHitBox = new Vector4(x + 1f/3, y - 1f/3, 1f/2, 4f/3); //The hitbox is "squeezed" along the x-axis to avoid the ladder being grabbed with minimal overlap. if (VectorIntersect(tileHitBox, playerHitBox)) { obj.on_ladder[(int)axis] = true; } break; case Tile.TileType.death: break; case Tile.TileType.win: break; } } } //update the objects intel if (axis == Axis.X) { obj.touch_left.Update(touch_l); obj.touch_right.Update(touch_r); } else { obj.touch_down.Update(touch_d); obj.touch_up.Update(touch_u); } }