/// <summary> /// Performs data processing that involves creating or retiring spatial features. /// Newly created features will not have any definition for their geometry - a /// subsequent call to <see cref="CalculateGeometry"/> is needed to to that. /// </summary> /// <param name="ff">The factory class for generating any spatial features</param> internal override void ProcessFeatures(FeatureFactory ff) { // If the closing point does not already exist, create one at some unspecified position OffsetPoint offset = (m_Radius as OffsetPoint); PointFeature p = (offset == null ? null : offset.Point); if (p == null) { p = ff.CreatePointFeature(DataField.ClosingPoint); } // Form the construction line (there is no associated circle at this stage, because // geometry does not get created until CalculateGeometry) ArcFeature arc = ff.CreateArcFeature(DataField.Arc, p, p); // Attach a new circle with undefined radius (at this stage, we do NOT cross-reference // it to the center point or add it to the map model, since that should be left unti; // CalculateGeometry). // Note: Setting the arc geometry also updates the circle to refer back to the feature. var circle = new Circle(m_Center, 0.0); arc.Geometry = new ArcGeometry(circle, arc.StartPoint, arc.StartPoint, true); base.SetNewLine(arc); }
/// <summary> /// Calculates positions that are parallel to a line. /// </summary> /// <param name="line">The reference line.</param> /// <param name="offset">The observed offset (either a <c>Distance</c> or an <c>OffsetPoint</c>).</param> /// <param name="sres">The position of the start of the parallel.</param> /// <param name="eres">The position of the end of the parallel.</param> /// <returns>True if positions calculated ok</returns> internal static bool Calculate(LineFeature line, Observation offset, out IPosition sres, out IPosition eres) { sres = eres = null; // Can't calculate if there is insufficient data. if (line == null || offset == null) { return(false); } // Is it an observed distance? Distance dist = (offset as Distance); if (dist != null) { return(ParallelLineUI.Calculate(line, dist, out sres, out eres)); } // The only other thing it could be is an offset point. OffsetPoint offPoint = (offset as OffsetPoint); if (offPoint != null) { PointFeature point = offPoint.Point; return(ParallelLineUI.Calculate(line, point, out sres, out eres)); } MessageBox.Show("ParallelLineUI.Calculate - Unexpected sort of observation"); return(false); }
/// <summary> /// Attempts to make a distance out of this observation and a from-point. /// </summary> /// <param name="from">The point the distance was measured from.</param> /// <returns> /// The distance, in metres on the ground. If a distance cannot be deduced, /// this will be 0.0. NOTE: may actually be a distance on the mapping plane if this /// observation is an offset point. The caller needs to check.</returns> /// <devnote> /// This function was written to assist in the implementation of the /// Intersect Direction & Distance command, which allows a distance to be specified /// using an offset point. Since offsets and distance object do not inherit from some /// place where we could define a pure virtual, this function exists to make explicit /// checks on the sort of distance we have (I don't want to define stubs for all the /// other objects which won't be able to return a distance). Re-arranging the class /// hierarchy would be better. /// </devnote> internal ILength GetDistance(PointFeature from) { // It's easy if the observation is a distance object. Distance dist = (this as Distance); if (dist != null) { return(dist); } // Can't do anything if the from point is undefined. if (from == null) { return(Length.Zero); } // See if we have an offset point. If so, the distance is the // distance from the from-point to the offset-point. OffsetPoint offset = (OffsetPoint)this; if (offset == null) { return(Length.Zero); } return(new Length(Geom.Distance(offset.Point, from))); }
/// <summary> /// Displays info for a specific distance observation. /// </summary> /// <param name="from">The point the distance was observed from.</param> /// <param name="obsv">The distance observation (either a <see cref="Distance"/>, /// or an <see cref="OffsetPoint"/>)</param> /// <param name="line">The line to show (null if no line).</param> void ShowDistance(PointFeature from, Observation obsv, LineFeature line) { // If we have an arc, define its entity type and scroll the // entity combo box to that type. Note that when the string // is selected, it is important that m_From and m_Distance // are null; otherwise <mf CdGetDist::OnSelChangeLineType> // may automatically move on to the next page of the wizard // dialog. m_From = null; m_Distance = null; m_LineType = null; if (line != null) { m_LineType = line.EntityType; lineTypeComboBox.SelectEntity(m_LineType); } // Define the from-point of the distance m_From = from; fromPointTextBox.Text = m_From.FormattedKey; // What sort of distance observation do we have? m_ObservedDistance = null; // m_pDistance m_DistancePoint = null; m_Distance = null; if (obsv is Distance) { // Display the distance in the original data entry units. Distance dist = (obsv as Distance); m_Distance = new Distance(dist); distanceTextBox.Text = m_Distance.Format(); // Create the appropriate distance observation (this is what // gets picked up when we actually go to work out the intersection. // (was on the last page of the property sheet -- see CdIntersectTwo) m_ObservedDistance = m_Distance; } else { // It SHOULD be an offset point. OffsetPoint off = (obsv as OffsetPoint); if (off == null) { throw new Exception("GetDistanceControl.ShowDistance - Unexpected type of distance."); } // Get the point involved & display it's ID. m_DistancePoint = off.Point; distanceTextBox.Text = m_DistancePoint.FormattedKey; // Create the appropriate distance observation m_OffsetPoint = new OffsetPoint(m_DistancePoint); m_ObservedDistance = m_OffsetPoint; } }
public GetDistanceControl() { InitializeComponent(); m_From = null; m_ObservedDistance = null; m_LineType = null; m_Circle = null; m_DistancePoint = null; m_Distance = null; m_OffsetPoint = null; m_Focus = null; }
public void RenderTile(OffsetPoint pos, int tilesetRow, int tilesetCol, SpriteBatch spriteBatch, Color tintColor, BlendState state, SpriteSortMode mode = SpriteSortMode.Deferred) { int viewportLeft = 0; int viewportTop = 0; PointI p = HexUtils.HexToPixel(pos, HexSize); int x = p.X - HexWidth / 2; int y = p.Y - HexHeight / 2; Rectangle sourceRectangle = new Rectangle(tilesetCol * HexTextureWidth, tilesetRow * HexTextureHeight, HexTextureWidth, HexTextureHeight); Rectangle destinationRectangle = new Rectangle(x + viewportLeft, y + viewportTop, HexWidth, HexHeight); spriteBatch.Draw(HexTexture, destinationRectangle, sourceRectangle, tintColor); }
private void GetOffsetForm_Shown(object sender, EventArgs e) { // If we already have an offset, display it. if (m_Offset != null) { // If it's an offset point, just display the point ID and disable the left/right // radio buttons. For an offset distance, display the distance and check // the appropriate radio button. if (m_Offset is OffsetPoint) { OffsetPoint op = (m_Offset as OffsetPoint); offsetTextBox.Text = String.Format("+{0}", op.Point.FormattedKey); leftRadioButton.Enabled = rightRadioButton.Enabled = false; } else if (m_Offset is OffsetDistance) { OffsetDistance od = (m_Offset as OffsetDistance); Distance dist = od.Offset; offsetTextBox.Text = dist.Format(); if (od.IsRight) { leftRadioButton.Checked = false; rightRadioButton.Checked = true; } else { rightRadioButton.Checked = false; leftRadioButton.Checked = true; } } else { throw new ArgumentException("Unexpected type of offset"); } } else { // Disable the left/right radios. They'll get enabled if // an offset distance is entered. leftRadioButton.Enabled = rightRadioButton.Enabled = false; } // OnChangeOffset is now free to null m_Offset as required. m_IsStatic = false; }
/// <summary> /// Uses the currently displayed information to try to construct a /// circle representing the distance. /// </summary> /// <returns>The constructed circle (null if a circle cannot be created /// based on the information that's currently displayed)</returns> Circle GetCurrentCircle() { Circle result = null; // Undefine the address of the relevant distance observation. m_ObservedDistance = null; if (m_From == null) { return(null); } if (m_DistancePoint != null || (m_Distance != null && m_Distance.Meters > Constants.TINY)) { double radius; // If we have an offset point, get the radius. if (m_DistancePoint != null) { radius = Geom.Distance(m_From, m_DistancePoint); } else { radius = m_Distance.Meters; } // Construct the circle result = new Circle(m_From, radius); // Create the appropriate distance observation (this is what // gets picked up when we actually go to work out the // intersection on the last page of the intersect dialog. if (m_DistancePoint != null) { m_OffsetPoint = new OffsetPoint(m_DistancePoint); m_ObservedDistance = m_OffsetPoint; } else { m_ObservedDistance = m_Distance; } } return(result); }
/// <summary> /// Creates any new spatial features (without any geometry) /// </summary> /// <param name="ff">The factory class for generating spatial features</param> internal override void ProcessFeatures(FeatureFactory ff) { m_To = ff.CreatePointFeature(DataField.To); OffsetPoint op = m_Direction.Offset as OffsetPoint; PointFeature from = (op == null ? m_Direction.From : op.Point); if (ff.HasFeatureDescription(DataField.DirLine)) { m_DirLine = ff.CreateSegmentLineFeature(DataField.DirLine, from, m_To); } if (ff.HasFeatureDescription(DataField.DistLine)) { m_DistLine = ff.CreateSegmentLineFeature(DataField.DistLine, m_From, m_To); } AssignObservedLengths(); }
/// <summary> /// Creates any new spatial features (without any geometry) /// </summary> /// <param name="ff">The factory class for generating spatial features</param> internal override void ProcessFeatures(FeatureFactory ff) { m_To = ff.CreatePointFeature(DataField.To); if (ff.HasFeatureDescription(DataField.Line1)) { OffsetPoint op1 = m_Direction1.Offset as OffsetPoint; PointFeature from1 = (op1 == null ? m_Direction1.From : op1.Point); m_Line1 = ff.CreateSegmentLineFeature(DataField.Line1, from1, m_To); } if (ff.HasFeatureDescription(DataField.Line2)) { OffsetPoint op2 = m_Direction2.Offset as OffsetPoint; PointFeature from2 = (op2 == null ? m_Direction2.From : op2.Point); m_Line2 = ff.CreateSegmentLineFeature(DataField.Line2, from2, m_To); } }
/// <summary> /// Cuts any reference made to this operation for an observed distance that was /// specified using an <see cref="OffsetPoint"/> object. /// </summary> /// <param name="dist">The distance observation. If this is not an <c>OffsetPoint</c> /// object, this function does nothing.</param> protected void CutOffsetRef(Observation dist) { // Return if the distance observation is not for an offset point OffsetPoint off = (dist as OffsetPoint); if (off == null) { return; } // Get the offset point and cut the reference it has to this operation. PointFeature point = off.Point; if (point != null) { point.CutOp(this); } }
/// <summary> /// Creates any new spatial features (without any geometry) /// </summary> /// <param name="ff">The factory class for generating spatial features</param> internal override void ProcessFeatures(FeatureFactory ff) { m_Intersection = ff.CreatePointFeature(DataField.To); // The line could be null when dealing with forward splits originating from CEdit (in // that case, the split needs to be deferred) if (m_IsSplit && m_Line != null) { LineFeature lineBefore, lineAfter; ff.MakeSections(m_Line, DataField.SplitBefore, m_Intersection, DataField.SplitAfter, out lineBefore, out lineAfter); m_LineA = lineBefore; m_LineB = lineAfter; } OffsetPoint op = m_Direction.Offset as OffsetPoint; PointFeature from = (op == null ? m_Direction.From : op.Point); if (ff.HasFeatureDescription(DataField.DirLine)) { m_DirLine = ff.CreateSegmentLineFeature(DataField.DirLine, from, m_Intersection); } }
void InitOp(ParallelLineOperation op) { // The direction is significant only if an offset distance // has been specified. m_IsLeft = false; // Pick up the offset. Observation offset = op.Offset; // If it's an observed distance, get the side. Distance dist = (offset as Distance); if (dist != null) { m_Offset = new Distance(dist); m_IsLeft = m_Offset.SetPositive(); } else { // The only other thing it could be is an offset point. OffsetPoint offPoint = (offset as OffsetPoint); if (offPoint != null) { m_Point = offPoint.Point; } } if (m_Point != null) { SelectPoint(m_Point); } else if (m_Offset != null) { offsetTextBox.Text = m_Offset.Format(); } }
/// <summary> /// Calculates the intersection point. /// </summary> /// <param name="dir">Direction observation.</param> /// <param name="distance">Distance observation.</param> /// <param name="from">The point the distance was observed from.</param> /// <param name="usedefault">True if the default intersection is required (the one /// closer to the origin of the direction line). False for the other one (if any).</param> /// <param name="xsect">The position of the intersection (if any).</param> /// <param name="xsect1">The 1st choice intersection (if any).</param> /// <param name="xsect2">The 2nd choice intersection (if any).</param> /// <returns>True if intersections were calculated. False if the distance circles /// don't intersect.</returns> internal static bool Calculate(Direction dir, Observation distance, PointFeature from, bool usedefault, out IPosition xsect, out IPosition xsect1, out IPosition xsect2) { // Initialize intersection positions. xsect = xsect1 = xsect2 = null; // Get the distance. double dist = distance.GetDistance(from).Meters; if (dist < Constants.TINY) { return(false); } // Form circle with a radius that matches the observed distance. ICircleGeometry circle = new CircleGeometry(from, dist); // See if there is actually an intersection between the direction & the circle. IPosition x1, x2; uint nx = dir.Intersect(circle, out x1, out x2); if (nx == 0) { return(false); } // If we have 2 intersections, and we need the non-default one, pick up the 2nd // intersection. If only 1 intersection, use that, regardless of the setting for // the "use default" flag. if (nx == 2 && !usedefault) { xsect = x2; } else { xsect = x1; } // Return if the distance is an offset point. OffsetPoint offset = (distance as OffsetPoint); if (offset != null) { xsect1 = x1; xsect2 = x2; return(true); } // Reduce observed distance to the mapping plane. ISpatialSystem sys = CadastralMapModel.Current.SpatialSystem; dist = dist * sys.GetLineScaleFactor(from, xsect); // And calculate the exact intersection (like above)... // Form circle with a radius that matches the reduced distance. ICircleGeometry circlep = new CircleGeometry(from, dist); // See if there is actually an intersection between the direction & the circle. nx = dir.Intersect(circlep, out x1, out x2); if (nx == 0) { return(false); } // If we have 2 intersections, and we need the non-default one, pick up the 2nd // intersection. If only 1 intersection, use that, regardless of the setting for // the "use default" flag. if (nx == 2 && !usedefault) { xsect = x2; } else { xsect = x1; } xsect1 = x1; xsect2 = x2; return(true); }
void InitOp(NewCircleOperation op, bool isUpdate) { // Get the center point and display its ID, preceded by a "+" char. m_Center = op.Center; centerTextBox.Text = String.Format("+{0}", m_Center.FormattedKey); // Get the observation that was used to specify the radius. Observation radius = op.Radius; // Make a copy of the relevant info, depending on whether the // radius was entered, or specified as an offset point. if (radius is OffsetPoint) { // Radius was specified as an offset point. OffsetPoint offset = (radius as OffsetPoint); m_RadiusPoint = offset.Point; m_RadiusDistance = null; // Display the ID of the offset point, preceded with a "+" char. radiusTextBox.Text = String.Format("+{0}", m_RadiusPoint.FormattedKey); if (isUpdate) { // If there are any incident arcs that were added using // a NewLineOperation (on the same circle), disallow the // ability to change the offset point. // @devnote Long story. In short, if the offset point // gets changed, the user could move it anywhere, so quite // a sophisticated UI could be needed to re-define where // the curves should go (failing that, if you let the user // change things, one end of the curve moves, but not the // end that met the offset point => looks bent). This is a // problem even if the curves have subsequently been // de-activated. LineFeature line = op.Line; Circle circle = line.Circle; Debug.Assert(circle != null); if (circle.HasArcsAt(m_RadiusPoint)) { radiusTextBox.Enabled = false; } } } else { // Radius is (or should be) an entered distance. m_RadiusPoint = null; Distance dist = (radius as Distance); if (dist == null) { MessageBox.Show("NewCircleForm.InitOp - Unexpected radius observation."); return; } m_RadiusDistance = new Distance(dist); // Display the radius (will call OnChangeRadius). radiusTextBox.Text = m_RadiusDistance.Format(); } // Ensure points are drawn ok. PaintAll(); }
/// <summary> /// Calculates intersection points. /// </summary> /// <param name="dist1">1st distance observation.</param> /// <param name="from1">The point the 1st distance was observed from.</param> /// <param name="dist2">2nd distance observation.</param> /// <param name="from2">The point the 2nd distance was observed from.</param> /// <param name="usedefault">True if the default intersection is required (the one that has the /// lowest bearing with respect to the 2 from points). False for the other one (if any).</param> /// <param name="xsect">The position of the intersection (if any).</param> /// <param name="xsect1">The 1st choice intersection (if any).</param> /// <param name="xsect2">The 2nd choice intersection (if any).</param> /// <returns>True if intersections were calculated. False if the distance circles /// don't intersect.</returns> internal static bool Calculate(Observation dist1, PointFeature from1, Observation dist2, PointFeature from2, bool usedefault, out IPosition xsect, out IPosition xsect1, out IPosition xsect2) { // Initialize intersection positions. xsect = xsect1 = xsect2 = null; // Get the 2 distances. double d1 = dist1.GetDistance(from1).Meters; double d2 = dist2.GetDistance(from2).Meters; if (d1 < Constants.TINY || d2 < Constants.TINY) { return(false); } // Form circles with radii that match the observed distances. ICircleGeometry circle1 = new CircleGeometry(from1, d1); ICircleGeometry circle2 = new CircleGeometry(from2, d2); // See if there is actually an intersection between the two circles. IPosition x1, x2; uint nx = IntersectionHelper.Intersect(circle1, circle2, out x1, out x2); if (nx == 0) { return(false); } // If we have 2 intersections, and we need the non-default one, pick up the 2nd // intersection. If only 1 intersection, use that, regardless of the setting for // the "use default" flag. if (nx == 2 && !usedefault) { xsect = x2; } else { xsect = x1; } // Return if both distances are offset points. OffsetPoint offset1 = (dist1 as OffsetPoint); OffsetPoint offset2 = (dist2 as OffsetPoint); if (offset1 != null && offset2 != null) { xsect1 = x1; xsect2 = x2; return(true); } // Reduce observed distances to the mapping plane. ISpatialSystem sys = CadastralMapModel.Current.SpatialSystem; if (offset1 == null) { d1 = d1 * sys.GetLineScaleFactor(from1, xsect); } if (offset2 == null) { d2 = d2 * sys.GetLineScaleFactor(from2, xsect); } // And calculate the exact intersection (like above)... // Form circles with radii that match the observed distances. ICircleGeometry circle1p = new CircleGeometry(from1, d1); ICircleGeometry circle2p = new CircleGeometry(from2, d2); // See if there is still an intersection between the two circles. nx = IntersectionHelper.Intersect(circle1p, circle2p, out x1, out x2); if (nx == 0) { return(false); } // If we have 2 intersections, and we need the non-default one, pick up the 2nd // intersection. If only 1 intersection, use that, regardless of the setting for // the "use default" flag. if (nx == 2 && !usedefault) { xsect = x2; } else { xsect = x1; } xsect1 = x1; xsect2 = x2; return(true); }
/// <summary> /// Reacts to selection of the OK button in the dialog. /// </summary> /// <param name="wnd">The dialog window. If this matches the dialog that /// this command knows about, the command will be executed (and, on success, /// the dialog will be destroyed). If it's some other window, it must /// be a sub-dialog created by our guy, so let it handle the request.</param> /// <returns>True if command finished ok</returns> internal override bool DialFinish(Control wnd) { // If it's the offset dialog that's just finished, grab info // from it, delete it, and go to the dialog for the first // terminal line. ISpatialDisplay view = ActiveDisplay; UpdateUI up = this.Update; if (m_ParDial != null) { // Get info from dialog (it'll be ONE of the two). The dialog // should only call this function after validating that one // of them is defined. m_OffsetPoint = m_ParDial.OffsetPoint; if (m_OffsetPoint == null) { m_Offset = m_ParDial.OffsetDistance; } // Destroy the dialog. KillDialogs(); // Calculate the positions for the parallel points. Calculate(); // Repaint what we know about. Draw(); // And start the dialog for the first terminal line. if (up != null) { m_TermDial1 = new TerminalControl(up, false); } else { m_TermDial1 = new TerminalControl(this, false); } //m_TermDial1.Show(); this.Container.Display(m_TermDial1); return(true); } if (m_TermDial1 != null) { // Get the first terminal line (if any). And the position. m_TermLine1 = m_TermDial1.TerminalLine; m_Term1 = m_TermDial1.TerminalPosition; // And move on to the 2nd terminal dialog. KillDialogs(); // Repaint what we know about. Draw(); // And start the dialog for the first terminal line. if (up != null) { m_TermDial2 = new TerminalControl(up, true); } else { m_TermDial2 = new TerminalControl(this, true); } this.Container.Display(m_TermDial2); //m_TermDial2.Show(); return(true); } if (m_TermDial2 == null) { throw new Exception("ParallelLineUI.DialFinish - No dialog!"); } // Get the nortthern terminal line (if any). And the position. m_TermLine2 = m_TermDial2.TerminalLine; m_Term2 = m_TermDial2.TerminalPosition; // Erase everything special that we've drawn. ErasePainting(); // And ensure the view has nothing selected (sometimes the line // last selected had been unhighlighted, although it's end points // stay highlighted for some reason). EditingController.Current.ClearSelection(); // If we are doing an update, remember the changes if (up != null) { // Get the original operation. ParallelLineOperation op = (ParallelLineOperation)up.GetOp(); if (op == null) { throw new Exception("ParallelLineUI.DialFinish - Unexpected edit type."); } // Note the offset (it SHOULD be defined) Observation offset = null; if (m_Offset != null) { offset = m_Offset; } else if (m_OffsetPoint != null) { offset = new OffsetPoint(m_OffsetPoint); } Debug.Assert(offset != null); // Remember the changes as part of the UI object (the original edit remains // unchanged for now) UpdateItemCollection changes = op.GetUpdateItems(m_Line, offset, m_TermLine1, m_TermLine2, m_IsReversed); if (!up.AddUpdate(op, changes)) { return(false); } } else { Observation offset = m_Offset; if (offset == null && m_OffsetPoint != null) { offset = new OffsetPoint(m_OffsetPoint); } Debug.Assert(offset != null); // Execute the edit ParallelLineOperation op = null; try { op = new ParallelLineOperation(m_Line, offset, m_TermLine1, m_TermLine2, m_IsReversed); op.Execute(); } catch (Exception ex) { MessageBox.Show(ex.StackTrace, ex.Message); return(false); } } // Destroy the dialog(s). KillDialogs(); // Get the base class to finish up. return(FinishCommand()); }
/// <summary> /// Starts the user interface (if any) for this command. /// </summary> /// <returns>True if command started ok.</returns> internal override bool Run() { // Don't run more than once. if (m_ParDial != null || m_TermDial1 != null || m_TermDial2 != null) { throw new Exception("ParallelLineUI.Run - Command is already running."); } // If we're doing an update, get the reference line from the original op. ParallelLineOperation op = null; UpdateUI up = this.Update; if (up != null) { op = (up.GetOp() as ParallelLineOperation); if (op == null) { throw new Exception("ParallelLineUI.Run - Unexpected edit type."); } // Pick up the line that acted as the reference line. m_Line = op.ReferenceLine; } // If it wasn't an update, we might be recalling an old op. if (op == null) { op = (this.Recall as ParallelLineOperation); } // Get old observations if necessary. if (op != null) { // Pick up the offset. Observation offset = op.Offset; // Is it an observed distance? Distance dist = (offset as Distance); if (dist != null) { m_Offset = new Distance(dist); } else { // The only other thing it could be is an offset point. OffsetPoint offPoint = (offset as OffsetPoint); if (offPoint != null) { m_OffsetPoint = offPoint.Point; } } m_IsReversed = op.IsArcReversed; m_TermLine1 = op.Terminal1; m_TermLine2 = op.Terminal2; // Ensure the reference line has been selected/highlighted (this may end up // calling OnSelectLine) EditingController.Current.Select(m_Line); // Calculate stuff & paint what we've got. Calculate(); Paint(null); } // Create modeless dialog. if (up != null) { m_ParDial = new ParallelControl(up); } else { m_ParDial = new ParallelControl(this); } this.Container.Display(m_ParDial); return(true); }