public SlopeArcher(BaseVisualMode mode, List <IVisualEventReceiver> sectors, VisualSidedefSlope handle1, VisualSidedefSlope handle2, double theta, double offsetangle, double scale) { this.mode = mode; this.sectors = sectors; this.handle1 = handle1; this.handle2 = handle2; this.theta = theta; this.offsetangle = offsetangle; this.scale = scale; heightoffset = 0.0; handleline = new Line2D(handle1.GetCenterPoint(), handle2.GetCenterPoint()); length = handleline.GetLength(); if (handle1.Level.type == SectorLevelType.Ceiling) { baseheight = handle1.Level.extrafloor ? handle1.Level.sector.FloorHeight : handle1.Level.sector.CeilHeight; } else { baseheight = handle1.Level.extrafloor ? handle1.Level.sector.CeilHeight : handle1.Level.sector.FloorHeight; } baseheightoffset = 0.0; }
//mxd public void DrawLine3DFloor(int x1, int y1, int x2, int y2, ref PixelColor c, PixelColor c2) { Line2D line = new Line2D(x1, y1, x2, y2); float length = line.GetLength(); if (length < DASH_INTERVAL * 2) { DrawLineSolid(x1, y1, x2, y2, ref c2); } else { float d1 = DASH_INTERVAL / length; float d2 = 1.0f - d1; Vector2D p1 = line.GetCoordinatesAt(d1); Vector2D p2 = line.GetCoordinatesAt(d2); DrawLineSolid(x1, y1, (int)p1.x, (int)p1.y, ref c2); DrawLineSolid((int)p1.x, (int)p1.y, (int)p2.x, (int)p2.y, ref c); DrawLineSolid((int)p2.x, (int)p2.y, x2, y2, ref c2); } }
//mxd public override void OnMouseMove(MouseEventArgs e) { base.OnMouseMove(e); // Anything to do? if ((!selectpressed && !editpressed) || closestline == null) { hintlabel.Text = string.Empty; return; } // Do something... Vector2D perpendicular = closestline.Line.GetPerpendicular().GetNormal(); if (panel.Distance != 0) { perpendicular *= panel.Distance; // Special cases... } Vector2D center = closestline.GetCenterPoint(); Line2D radius = new Line2D(center, center - perpendicular); float u = radius.GetNearestOnLine(mousemappos - mousedownoffset); int dist = (panel.Distance == 0 ? 1 : panel.Distance); // Special cases... int offset = (int)Math.Round(dist * u - dist); bool updaterequired = false; // Clamp values? bool clampvalue = !General.Interface.ShiftState; // Change verts amount if (selectpressed && editpressed) { if (prevoffset != 0) { // Set new verts count without triggering the update... panel.SetValues(panel.Vertices + Math.Sign(prevoffset - offset), panel.Distance, panel.Angle, panel.FixedCurve); // Update hint text hintlabel.Text = "Vertices: " + panel.Vertices; updaterequired = true; } } // Change distance else if (selectpressed && !panel.FixedCurve) { if (float.IsNaN(u)) { // Set new distance without triggering the update... panel.SetValues(panel.Vertices, 0, panel.Angle, panel.FixedCurve); // Special cases... } else { int newoffset; if (clampvalue) { newoffset = (panel.Distance + offset) / panel.DistanceIncrement * panel.DistanceIncrement; // Clamp to 8 mu increments } else { newoffset = panel.Distance + offset; } // Set new distance without triggering the update... panel.SetValues(panel.Vertices, newoffset, panel.Angle, panel.FixedCurve); } // Update hint text hintlabel.Text = "Distance: " + panel.Distance; updaterequired = true; } // Change angle else if (editpressed && prevoffset != 0) { int newangle = 0; if (panel.FixedCurve) { // Flip required? if (panel.Angle == 0 && (Math.Sign(offset - prevoffset) != Math.Sign(panel.Distance))) { // Set new distance without triggering the update... panel.SetValues(panel.Vertices, -panel.Distance, panel.Angle, panel.FixedCurve); // Recalculate affected values... perpendicular *= -1; radius.v2 = center - perpendicular; u = radius.GetNearestOnLine(mousemappos - mousedownoffset); } //TODO: there surely is a way to get new angle without iteration... float targetoffset = radius.GetLength() * u; float prevdiff = float.MaxValue; int increment = (clampvalue ? panel.AngleIncrement : 1); for (int i = 1; i < panel.MaximumAngle; i += increment) { // Calculate diameter for current angle... float ma = Angle2D.DegToRad(i); float d = (closestline.Length / (float)Math.Tan(ma / 2f)) / 2; float D = d / (float)Math.Cos(ma / 2f); float h = D - d; float curdiff = Math.Abs(h - targetoffset); // This one matches better... if (curdiff < prevdiff) { newangle = i; } prevdiff = curdiff; } // Clamp to 5 deg increments if (clampvalue) { newangle = (newangle / panel.AngleIncrement) * panel.AngleIncrement; } } else { int diff = (int)Math.Round((offset - prevoffset) * renderer.Scale); if (panel.Angle + diff > 0) { if (clampvalue) { newangle = (panel.Angle / panel.AngleIncrement + Math.Sign(diff)) * panel.AngleIncrement; // Clamp to 5 deg increments } else { newangle = panel.Angle + diff; } } } // Set new angle without triggering the update... panel.SetValues(panel.Vertices, panel.Distance, newangle, panel.FixedCurve); // Update hint text hintlabel.Text = "Angle: " + panel.Angle; updaterequired = true; } // Update UI if (updaterequired) { // Update label position float labeldistance; if (panel.Angle == 0) { labeldistance = 0; // Special cases! } else if (panel.FixedCurve) { float ma = Angle2D.DegToRad(panel.Angle); float d = (closestline.Length / (float)Math.Tan(ma / 2f)) / 2; float D = d / (float)Math.Cos(ma / 2f); labeldistance = D - d; } else { labeldistance = Math.Abs(panel.Distance); } labeldistance += 16 / renderer.Scale; Vector2D labelpos = radius.GetCoordinatesAt(labeldistance / radius.GetLength()); hintlabel.Move(labelpos, labelpos); // Trigger update OnValuesChanged(null, EventArgs.Empty); } // Store current offset prevoffset = offset; }
public float GetLength() { return(l2d.GetLength()); }
public float GetLength() { return(Line2D.GetLength(v2.x - v1.x, v2.y - v1.y)); }
private static int GetLength(int x1, int y1, int x2, int y2) { return((int)Line2D.GetLength(new Point2D(x1, y1), new Point2D(x2, y2))); }
// This generates the vertices to split the line with, from start to end private List<Vector2D> GenerateCurve(Line2D line, int vertices, float angle, bool backwards, float distance, bool fixedcurve) { // Make list List<Vector2D> points = new List<Vector2D>(vertices); //Added by Anders Åstrand 2008-05-18 //The formulas used are taken from http://mathworld.wolfram.com/CircularSegment.html //c and theta are known (length of line and angle parameter). d, R and h are //calculated from those two //If the curve is not supposed to be a circular segment it's simply deformed to fit //the value set for distance. //The vertices are generated to be evenly distributed (by angle) along the curve //and lastly they are rotated and moved to fit with the original line //calculate some identities of a circle segment (refer to the graph in the url above) double c = line.GetLength(); double theta = angle; double d = (c / Math.Tan(theta / 2)) / 2; double R = d / Math.Cos(theta / 2); double h = R - d; double yDeform = fixedcurve ? 1 : distance / h; if (backwards) yDeform = -yDeform; double a, x, y; Vector2D vertex; for (int v = 1; v <= vertices; v++) { //calculate the angle for this vertex //the curve starts at PI/2 - theta/2 and is segmented into vertices+1 segments //this assumes the line is horisontal and on y = 0, the point is rotated and moved later a = (Math.PI - theta) / 2 + v * (theta / (vertices + 1)); //calculate the coordinates of the point, and distort the y coordinate //using the deform factor calculated above x = Math.Cos(a) * R; y = (Math.Sin(a) * R - d) * yDeform; //rotate and transform to fit original line vertex = new Vector2D((float)x, (float)y).GetRotated(line.GetAngle() + Angle2D.PIHALF); vertex = vertex.GetTransformed(line.GetCoordinatesAt(0.5f).x, line.GetCoordinatesAt(0.5f).y, 1, 1); points.Add(vertex); } // Done return points; }