/// <summary> /// Removes a spatial object from the index /// </summary> /// <param name="o">The object to remove from the index</param> /// <returns> /// True if object removed. False if it couldn't be found. /// </returns> public bool Remove(ISpatialObject o) { if (o is IPoint) { return(m_Points.Remove(o as IPoint)); } Item item = new Item(o); SpatialType t = o.SpatialType; if (t == SpatialType.Line) { return(m_Lines.Remove(item)); } if (t == SpatialType.Text) { bool isRemoved = m_Text.Remove(item); Debug.Assert(isRemoved); return(isRemoved); } if (t == SpatialType.Polygon) { return(m_Polygons.Remove(item)); } throw new NotSupportedException("Unexpected object type: " + o.SpatialType); }
bool WriteText(ISpatialObject item) { TextFeature text = (item as TextFeature); if (this.IsTopological) { ExportKey(text); } else { } // Skip if the AutoCad layer cannot be determined Layer layer = m_Layers.GetLayer(text, m_ContinuousLineType, this.IsTopological); if (layer != null) { TextGeometry geom = text.TextGeometry; Text acText = new Text(geom.Text, GetVector(geom.Position), geom.Height); acText.Rotation = (float)geom.Rotation.Degrees; acText.Layer = layer; m_Dxf.AddEntity(acText); } return(true); }
/// <summary> /// Obtains any miscellaneous attribute data for a specific spatial object /// </summary> /// <param name="so">The object of interest</param> /// <returns>Any attributes for the spatial object (never null, but may be an empty list)</returns> List <Row> GetRows(ISpatialObject so) { List <Row> result = new List <Row>(); Feature f = (so as Feature); if (f == null && so is Polygon) { f = (so as Polygon).Label; } if (f != null && f.FeatureId != null) { FeatureId fid = f.FeatureId; IPossibleList <Row> rows = fid.Rows; if (rows != null) { foreach (Row r in rows) { result.Add(r); } } } return(result); }
/// <summary> /// Checks if an object is acceptable for trimming. /// </summary> /// <param name="thing">The candidate object.</param> /// <returns>The supplied candidate, cast to a line (given that the candidate is /// suitable for trimming). Null if the candidate is not a line, or not suitable /// for trimming.</returns> static LineFeature PreCheck(ISpatialObject thing) { // It has no be a line LineFeature line = (thing as LineFeature); if (line == null) { return(null); } // It has to be topological Topology t = line.Topology; if (t == null) { return(null); } // The line should have system-defined topological line // sections (if it doesn't that would mean that the complete // line dangles). SectionTopologyList sectionList = (t as SectionTopologyList); if (sectionList == null) { return(null); } if (sectionList.CanTrim()) { return(line); } return(null); }
/// <summary> /// Delegate called to process each polygon found within the build window. /// Called by <c>BuildIslands</c> /// </summary> /// <param name="o">An item found in the spatial index.</param> /// <returns>True (always), indicating that the spatial query should keep going.</returns> bool ProcessPolygon(ISpatialObject o) { if (!(o is Island)) { return(true); } // Just return if the enclosing polygon is already known Island pol = (Island)o; if (pol.Container != null) { return(true); } // If the island is marked as floating, and it has a window // that encloses the build window, mark it as not floating. // This covers situations where a previously floating island // is now enclosed by something. if (pol.IsFloating && pol.Extent.IsOverlap(m_NewPolygonExtent)) { pol.IsFloating = false; } pol.SetContainer(); return(true); }
/// <summary> /// Delegate called to process every polygon in the map. /// Called by <see cref="BuildLabels"/>. /// </summary> /// <param name="o">A polygon ring in the spatial index</param> /// <returns>True (always), to force examination of the entire spatial index</returns> bool FindLabelForPolygon(ISpatialObject o) { Debug.Assert(o is Ring); if (o is Polygon) { // Only process polygons that don't already have a label, and which // don't contain any islands (polygons with islands tend to cover // much larget areas, so trying to find the label this way will // probably not be very efficient). Polygon p = (Polygon)o; if (p.Label == null && !p.HasAnyIslands) { TextFeature label = new FindPolygonLabelQuery(m_Model.Index, p).Result; if (label != null) { p.ClaimLabel(label); label.SetBuilt(true); } } } return(true); }
/// <summary> /// Override does the same as <c>SpatialController.SetSelection</c>, and additionally /// tells the application's main window (the main window goes on to display a property /// grid for the current selection). /// </summary> public override bool SetSelection(ISpatialSelection newSel) { if (!base.SetSelection(newSel)) { return(false); } if (m_Main != null) { Debug.Assert(newSel != null); ISpatialObject so = newSel.Item; if (so is GeometryWrapper) { GeometryWrapper g = (GeometryWrapper)so; object o = (g == null ? null : g.UserData); m_Main.SetSelection(o); } else { m_Main.SetSelection(null); } } return(true); }
/// <summary> /// Creates a new <c>FindClosestQuery</c> (and executes it). The result of the query /// can then be obtained through the <c>Result</c> property. /// </summary> /// <param name="index">The spatial index to search</param> /// <param name="p">The search position.</param> /// <param name="radius">The search tolerance (expected to be greater than zero).</param> /// <param name="types">The type of objects to look for.</param> internal FindClosestQuery(ISpatialIndex index, IPosition p, ILength radius, SpatialType types) { if (types == 0) { throw new ArgumentNullException("Spatial type(s) not specified"); } // If the user hasn't been specific, ensure we don't search for polygons! SpatialType useTypes = (types == SpatialType.All ? SpatialType.Feature : types); Debug.Assert((useTypes & SpatialType.Polygon) == 0); // It's important to round off to the nearest micron. Otherwise you might not // get the desired results in situations where the search radius is zero. m_Position = PositionGeometry.Create(p); m_Radius = radius; m_Types = types; m_Result = null; m_Distance = m_Radius.Meters; // The query will actually involve a square window, not a circle. IWindow x = new Window(m_Position, radius.Meters * 2.0); index.QueryWindow(x, useTypes, OnQueryHit); }
/// <summary> /// Delegate that's called whenever the index finds a line. /// </summary> /// <param name="item">The item to process</param> /// <returns>True (always), indicating that the query should continue.</returns> private bool CheckLine(ISpatialObject item) { Debug.Assert(item is LineFeature); LineFeature line = (LineFeature)item; // Return if the line is non-topological if (!line.IsTopological) { return(true); } Topology t = line.Topology; if (t != null) { foreach (IDivider d in t) { CheckType types = (m_Options & DividerCheck.Check(d)); if (types != CheckType.Null) { DividerCheck check = new DividerCheck(d, types); m_Result.Add(check); } } } return(OnCheck()); }
public SpatialNode FindChildLeastEnlargement(ISpatialObject obj) { SpatialNode bestChild = null; var leastEnlargement = float.MaxValue; var leastVolume = float.MaxValue; foreach (var child in children) { var volume = CalculateVolume(child.min, child.max); var newVolume = CalculateVolume(Vector3.Min(child.min, obj.min), Vector3.Max(child.max, obj.max)); var enlargement = newVolume - volume; if (enlargement > leastEnlargement || Mathf.Approximately(enlargement, leastEnlargement) && volume >= leastVolume) { continue; } bestChild = child as SpatialNode; leastEnlargement = enlargement; leastVolume = volume; } return(bestChild); }
/* * * // * // @parm AutoCad entity. * // @parm Cross-reference of CED entity types to AutoCad layers. * // @parm The style for the annotations. * // @parm The point involved. * // * // @rdesc TRUE if annotation was written. * LOGICAL CeAutoCad::ExportAngles ( const AD_DB_HANDLE DwgHandle * , AD_VMADDR pEntityList * , PAD_ENT_HDR pEntityHeader * , PAD_ENT pEntity * , CacadLayerEntitySet* pLESet * , AD_SHPTB* pStyle * , const CePoint& pt ) const { * * // Skip if there is no AutoCad layer for the specified point * // (the annotations will be going onto the same layer). * AD_OBJHANDLE* pLayerHandle = pLESet->GetpLayerHandle(&pt, * m_ContinuousLineTypeHandle,TRUE); * if ( !pLayerHandle ) return FALSE; * * // Get the point to create a set of miscellaneous text * // objects. * CPtrList text; * UINT4 nAngle = pt.CreateAngleText(text,FALSE); * if ( nAngle==0 ) return FALSE; * * // Export each item of text (deleting each item as we go). * POSITION pos = text.GetHeadPosition(); * while ( pos ) { * CeMiscText* pText = (CeMiscText*)text.GetNext(pos); * * // What's the actual text string? * CString text; * pText->GetText(text); * * // If the text position is to the west of the point, * // align it on the right. * FLOAT8 xt = pText->GetEasting(); * FLOAT8 yt = pText->GetNorthing(); * INT4 halign = AD_TEXT_JUST_LEFT; * * // Take special care with vertical text (allow up to 1mm * // of roundoff). * if ( (xt+0.001) < pt.GetEasting() ) halign = AD_TEXT_JUST_RIGHT; * * // Pull out values for function call below. * CeVertex posn(xt,yt); * FLOAT8 grheight = pText->GetHeight(); * FLOAT8 rotation = pText->GetRotation(); * * CacadText AcadText(DwgHandle,pEntityList,pEntityHeader,pEntity); * AcadText.ExportAngleDistText(pStyle,pLayerHandle,pText,text,posn * ,grheight,rotation * ,halign,AD_TEXT_VALIGN_MIDDLE); * * delete pText; * } * * // Ensure pointer to the text have been removed too. * text.RemoveAll(); * * return TRUE; */ bool WriteLine(ISpatialObject item) { LineFeature line = (LineFeature)item; WriteLineGeometry(line.LineGeometry); return(true); }
/// <summary> /// Delegate that's called whenever the index finds text with a window that overlaps the query window /// </summary> /// <param name="item">The item to process (expected to be some sort of <c>TextFeature</c>)</param> /// <returns>True (always), indicating that the query should continue.</returns> private bool OnTextFound(ISpatialObject item) { // Ignore test that's already been built TextFeature text = (TextFeature)item; if (text.IsBuilt) { return(true); } if (text.IsTopological) { // Get the label's reference position. IPointGeometry posn = text.GetPolPosition(); // Try to find enclosing polygon if (m_Polygon.IsEnclosing(posn)) { m_Result = text; return(false); } } return(true); }
/// <summary> /// Delegate called to process each text feature found within the build window. /// Called by <see cref="BuildLabels"/>. /// </summary> /// <param name="o">An item found in the spatial index.</param> /// <returns>True (always), indicating that the spatial query should keep going.</returns> bool ProcessLabel(ISpatialObject o) { Debug.Assert(o is TextFeature); TextFeature f = (TextFeature)o; f.SetPolygon(); return(true); }
/// <summary> /// Adds a spatial object to this selection, given that it is not already /// part of the selection. /// </summary> /// <param name="so">The object to remember as part of this selection (not null)</param> /// <exception cref="ArgumentNullException">If the specified object is null</exception> internal void Add(ISpatialObject so) { if (so==null) throw new ArgumentNullException(); if (!m_Items.Contains(so)) m_Items.Add(so); }
internal void SetSelectedObject(ISpatialObject so) { try { editButton.Visible = false; string oldLastPage = m_LastPageName; // Grab the attributes we'll be displaying List <Row> rows = GetRows(so); // Require a page for each attribute, plus 1 for standard properties. // If we have an excess number of property pages, get rid of the redundant ones while (tabControl.TabCount > (1 + rows.Count)) { tabControl.TabPages.RemoveAt(1); } // Reuse any remaining PropertyPages, add any additional pages int toReuse = (tabControl.TabCount - 1); foreach (Row r in rows) { if (toReuse > 0) { PropertyPage pp = (tabControl.TabPages[toReuse] as PropertyPage); Debug.Assert(pp != null); pp.SetRow(r); toReuse--; } else { tabControl.TabPages.Add(new PropertyPage(r)); } } propertyGrid1.SelectedObject = so; // If a non-standard tab was previously on top, and we still have // a page with the same tab text, ensure it's on top. Failing // that, go for the first tab that shows any database attributes // (since that info will likely have more relevance to the user). if (!SelectPage(oldLastPage)) { if (tabControl.TabCount > 1) { tabControl.SelectedIndex = 1; } } } catch { propertyGrid1.SelectedObject = null; } propertyGrid1.Refresh(); }
bool DefaultVisibilityPredicate(ISpatialObject obj) { if (m_Settings.UseCulling) { return(m_Culling.IsVisible(obj)); } m_Bounds.SetMinMax(obj.Min, obj.Max); return(m_Bounds.SqrDistance(m_CamPos) < m_VisibilitySqrDist); }
/// <summary> /// Creates a new <c>SpatialSelection</c> that contains a single item (or nothing). /// </summary> /// <param name="so">The object to remember as part of this selection (if null, it /// will not be added to the selection)</param> public SpatialSelection(ISpatialObject so) { if (so==null) m_Items = new List<ISpatialObject>(); else { m_Items = new List<ISpatialObject>(1); m_Items.Add(so); } }
/// <summary> /// Checks whether this selection refers to one specific spatial object. /// </summary> /// <param name="so">The object to compare with</param> /// <returns>True if this selection refers to a single item that corresponds /// to the specified spatial object</returns> public bool Equals(ISpatialObject so) { if (so==null) return false; if (this.Count!=1) return false; return Object.ReferenceEquals(so, m_Items[0]); }
bool CheckIntersectRay(ISpatialObject obj) { m_Bounds.SetMinMax(obj.Min, obj.Max); if (!m_Bounds.IntersectRay(m_SelectionRay, out var distance)) { return(false); } obj.Priority = distance; return(true); }
/// <summary> /// Delegate that's called whenever the index finds an object with an extent that /// overlaps the query window. /// </summary> /// <param name="item">The item to process</param> /// <returns>True (always), meaning the query should continue.</returns> bool OnQueryHit(ISpatialObject item) { if (m_DoPaint) { m_DoPaint = false; m_Display.PaintNow(); } item.Render(m_Display, m_Style); return(true); }
void AddOrRemoveFromSelection(ISpatialObject so) { Selection sel = new Selection(this.SpatialSelection.Items); if (!sel.Remove(so)) { sel.Add(so); } SetSelection(sel); }
/// <summary> /// Delegate that's called whenever the index finds a point that's inside the query window /// </summary> /// <param name="item">The item to process (expected to be some sort of <c>PointFeature</c>)</param> /// <returns>True (always), indicating that the query should continue.</returns> private bool OnPointFound(ISpatialObject item) { PointFeature p = (PointFeature)item; if (m_ClosedShape.IsOverlap(p)) { m_Points.Add(p); } return(true); }
public bool IsVisible(ISpatialObject obj) { m_BoundsMin = obj.Min; m_BoundsMax = obj.Max; if (m_Settings.UseDistanceCullingAvoidance) { m_Bounds.SetMinMax(m_BoundsMin, m_BoundsMax); if (m_Bounds.SqrDistance(m_CamPos) < m_AvoidCullingWithinSqrDistance) { return(true); } } if (m_UseShadowCullingAvoidance) // use member because we check if shadows are enabled in QualitySettings { // expand bounds to include potential shadow casting area m_Distance = m_Settings.ShadowDistanceFactor * Mathf.Max(m_BoundsMax.x - m_BoundsMin.x, m_BoundsMax.y - m_BoundsMin.y, m_BoundsMax.z - m_BoundsMin.z); m_DirectionalLightForwardOffset = m_DirectionalLightForward * m_Distance; m_BoundsMin = Vector3.Min(m_BoundsMin, m_BoundsMin + m_DirectionalLightForwardOffset); m_BoundsMax = Vector3.Max(m_BoundsMax, m_BoundsMax + m_DirectionalLightForwardOffset); } // do the frustum check, necessary for size and depth culling since both techniques are based on the screen projection if (!IsInCameraFrustum(m_BoundsMin, m_BoundsMax)) { return(false); } // early exit before screen projection if it won't be used if (!m_Settings.UseSizeCulling && !m_Settings.UseDepthCulling) { return(true); } // if screen rect is invalid, safer to assume object is visible if (!TryCalculateScreenRect(m_BoundsMin, m_BoundsMax, out m_ScreenMin, out m_ScreenMax)) { return(true); } if (m_Settings.UseSizeCulling) { m_ScreenAreaRatio = (m_ScreenMax.x - m_ScreenMin.x) * (m_ScreenMax.y - m_ScreenMin.y); if (m_ScreenAreaRatio < m_MinScreenAreaRatioMesh) { return(false); } } return(!m_Settings.UseDepthCulling || !IsDepthOccluded(m_ScreenMin, m_ScreenMax)); }
/// <summary> /// Creates a new <c>SpatialSelection</c> that contains a single item (or nothing). /// </summary> /// <param name="so">The object to remember as part of this selection (if null, it /// will not be added to the selection)</param> public SpatialSelection(ISpatialObject so) { if (so == null) { m_Items = new List <ISpatialObject>(); } else { m_Items = new List <ISpatialObject>(1); m_Items.Add(so); } }
/// <summary> /// Attempts to locate the circle closest to a position of interest. /// </summary> /// <param name="p">The search position (on the circumference of the circle)</param> /// <param name="tol">The search tolerance</param> /// <returns>The circle closest to the search position (null if nothing found)</returns> internal Circle QueryClosestCircle(IPosition p, ILength tol) { ISpatialObject so = m_ExtraData.QueryClosest(p, tol, SpatialType.Line); if (so == null) { return(null); } Debug.Assert(so is Circle); return(so as Circle); }
internal void SetSelectedObject(ISpatialObject so) { try { editButton.Visible = false; string oldLastPage = m_LastPageName; // Grab the attributes we'll be displaying List<Row> rows = GetRows(so); // Require a page for each attribute, plus 1 for standard properties. // If we have an excess number of property pages, get rid of the redundant ones while (tabControl.TabCount > (1+rows.Count)) tabControl.TabPages.RemoveAt(1); // Reuse any remaining PropertyPages, add any additional pages int toReuse = (tabControl.TabCount - 1); foreach (Row r in rows) { if (toReuse > 0) { PropertyPage pp = (tabControl.TabPages[toReuse] as PropertyPage); Debug.Assert(pp!=null); pp.SetRow(r); toReuse--; } else { tabControl.TabPages.Add(new PropertyPage(r)); } } propertyGrid1.SelectedObject = so; // If a non-standard tab was previously on top, and we still have // a page with the same tab text, ensure it's on top. Failing // that, go for the first tab that shows any database attributes // (since that info will likely have more relevance to the user). if (!SelectPage(oldLastPage)) { if (tabControl.TabCount > 1) tabControl.SelectedIndex = 1; } } catch { propertyGrid1.SelectedObject = null; } propertyGrid1.Refresh(); }
bool CheckColliderDistance(ISpatialObject obj) { m_Bounds.SetMinMax(obj.Min, obj.Max); var distance = m_Bounds.SqrDistance(m_Camera.transform.position); if (distance > m_Settings.ColliderObjectsMaxDistance) { return(false); } obj.Priority = distance; return(true); }
public override void Select(ISpatialDisplay display, IPosition p, SpatialType spatialType) { ISpatialObject so = SelectObject(display, p, spatialType); if (so != null) { SetSelection(new Selection(so, p)); } else { SetSelection(null); } }
/// <summary> /// Delegate that's called whenever the index finds an object with an extent that /// overlaps the query window. /// </summary> /// <param name="item">The item to process (expected to be some sort of <c>Feature</c>)</param> /// <returns>True if the query should continue. False if the item is exactly coincident with /// the query position.</returns> bool OnQueryHit(ISpatialObject item) { double d = item.Distance(m_Position).Meters; if (d <= m_Distance) { m_Distance = d; m_Result = item; return(m_Distance > Double.Epsilon); } return(true); }
/// <summary> /// Delegate that's called whenever the index finds a polygon /// </summary> /// <param name="item">The item to process</param> /// <returns>True (always), indicating that the query should continue.</returns> private bool CleanupPolygon(ISpatialObject item) { Debug.Assert(item is Ring); Ring r = (Ring)item; if (r.IsDeleted) { m_Deletions.Add(r); } r.Clean(); return(true); }
/// <summary> /// Delegate that's called whenever the index finds an object with an extent that /// overlaps the query window. /// </summary> /// <param name="item">The item to process (expected to be some sort of <c>PointFeature</c>)</param> /// <returns>True if the query should continue. False if a coincident point has been found.</returns> private bool OnQueryHit(ISpatialObject item) { Debug.Assert(item is PointFeature); PointFeature p = (PointFeature)item; if (p.Geometry.IsCoincident(m_Point)) { m_Result = p; return false; } return true; }
/// <summary> /// Delegate that's called whenever the index finds an object with an extent that /// overlaps the query window. /// </summary> /// <param name="item">The item to process (expected to be some sort of <c>PointFeature</c>)</param> /// <returns>True if the query should continue. False if a matching point has been found.</returns> private bool OnQueryHit(ISpatialObject item) { Debug.Assert(item is PointFeature); PointFeature p = (PointFeature)item; if (p.FormattedKey == m_Key) { m_Result = p; return false; } return true; }
/// <summary> /// Delegate that's called whenever the index finds an object with an extent that /// overlaps the query window. /// </summary> /// <param name="item">The item to process (expected to be some sort of <c>Ring</c>)</param> /// <returns>True if the query should continue. False if the enclosing polygon has been found.</returns> private bool OnQueryHit(ISpatialObject item) { // We're only interested in real polygons (not islands) if (!(item is Polygon)) { return(true); } // The area of the polygon MUST be bigger than the area of the island. Polygon p = (Polygon)item; if (p.Area < m_Island.Area) { return(true); } // Skip if the window does not actually overlap the search point. if (!p.Extent.IsOverlap(m_EastPoint)) { return(true); } // The window of the island must be ENTIRELY within the window // of the candidate polygon. if (!m_Island.Extent.IsEnclosedBy(p.Extent)) { return(true); } // Skip if the polygon doesn't enclose the east point. if (!p.IsRingEnclosing(m_EastPoint)) { return(true); } // Skip if we previously found something, and the area of the candidate // polygon is bigger. Take care here - the polygons may not yet know about // all their islands (which might lead to an incorrect enclosing polygon), // so this test should EXCLUDE the area of any islands that they already // know about). if (m_Result != null && p.AreaExcludingIslands > m_Result.AreaExcludingIslands) { return(true); } m_Result = p; // Keep going after finding a result, since a different (smaller) polygon // may be found further on in the search. return(true); }
public virtual void Select(ISpatialDisplay display, IPosition p, SpatialType spatialType) { if (m_Data == null) { return; } // Use a tolerance of 2mm at the map scale of the supplied display ILength size = new Length(0.002 * display.MapScale); ISpatialObject so = m_Data.QueryClosest(p, size, spatialType); SetSelection(new SpatialSelection(so)); }
/// <summary> /// Something that processes an item in the index (for use with implementations /// of the <c>ISpatialIndex.QueryWindow</c> method). /// </summary> /// <param name="item">An object associated with the spatial index</param> /// <returns>True if the query should be continued. False if the query should be /// terminated (e.g. a result may have been obtained).</returns> public bool ExportFeature(ISpatialObject item) { // Islands only get exported in the context of their enclosing polygon if (item is Island) return true; if (item.SpatialType == SpatialType.Point) ExportPoint((PointFeature)item); else if (item.SpatialType == SpatialType.Polygon) //ExportCurvePolygon((Polygon)item); ExportPolygon((Polygon)item); else throw new NotSupportedException("Unexpected spatial type: " + item.SpatialType); return true; }
bool WriteText(ISpatialObject item) { TextFeature text = (item as TextFeature); if (this.IsTopological) { ExportKey(text); } else { } // Skip if the AutoCad layer cannot be determined Layer layer = m_Layers.GetLayer(text, m_ContinuousLineType, this.IsTopological); if (layer != null) { TextGeometry geom = text.TextGeometry; Text acText = new Text(geom.Text, GetVector(geom.Position), geom.Height); acText.Rotation = (float)geom.Rotation.Degrees; acText.Layer = layer; m_Dxf.AddEntity(acText); } return true; }
public void Explore(ISpatialObject spatial, ExploreDelegate exploreDelegate, Type agentType = null) { IEnumerable<ISpatialEntity> res; var entity = spatial; if (gpuActive) gpuActiveWait.WaitOne(); Interlocked.Increment(ref m_ActiveOperationCount); int objId = Interlocked.Increment(ref exploreIdGenBase); long objData = objId | FLAG_EXLORE; objIdList.Add(objId); /*spatialObjIdMap.Add(entity, objId); objIdSpatialMap.Add(objId, entity); */ clShapeObject act; clPoint center; center.x = (float)entity.Shape.Bounds.Position.X; center.y = (float)entity.Shape.Bounds.Position.Y; center.z = (float)entity.Shape.Bounds.Position.Z; clPoint front; front.x = (float)entity.Shape.Bounds.LeftBottomFront.X; front.y = (float)entity.Shape.Bounds.LeftBottomFront.Y; front.z = (float)entity.Shape.Bounds.LeftBottomFront.Z; clPoint rear; rear.x = (float)entity.Shape.Bounds.RightTopRear.X; rear.y = (float)entity.Shape.Bounds.RightTopRear.Y; rear.z = (float)entity.Shape.Bounds.RightTopRear.Z; act.center = center; act.leftBottomFront = front; act.rigthTopRear = rear; envExploreObjs.Add(objData, act); /* shapeList.Add(act); objIdClShapeMap.Add(objId, act); */ Interlocked.Decrement(ref m_ActiveOperationCount); }
/// <summary> /// Creates new <c>SimpleCommandUI</c> that isn't an update. /// </summary> /// <param name="cc">The container that may be used to display any sort of /// user dialog (null if no dialog is involved)</param> /// <param name="cmdId">The item used to invoke the command.</param> /// <param name="update">The object (if any) that was selected for update</param> /// <param name="recall">An operation that is being recalled (null if this is an update).</param> protected SimpleCommandUI(IControlContainer cc, IUserAction cmdId, ISpatialObject update, Operation recall) : base(cc, cmdId, update, recall) { }
/// <summary> /// Delegate that's called whenever the index finds an object with an extent that /// overlaps the query window. /// </summary> /// <param name="item">The item to process (expected to be some sort of <c>LineFeature</c>)</param> /// <returns>True (always), indicating that the query should continue.</returns> private bool OnQueryHit(ISpatialObject item) { Debug.Assert(item is LineFeature); // Ignore if we're intersecting a line feature & the line we've found is that line LineFeature f = (LineFeature)item; if (Object.ReferenceEquals(m_Feature, f)) return true; // Ignore lines that don't have any topology Topology t = f.Topology; if (t == null) return true; Debug.Assert(f.IsTopological); // Ignore lines that are marked as "moved" if (f.IsMoved) return true; // Intersect each divider foreach (IDivider d in t) { // Ignore divider overlaps (regarded as non-topological) if (d.IsOverlap) continue; // Search for intersections IntersectionResult other = new IntersectionResult(d); m_Geom.Intersect(other); if (other.IntersectCount>0) { // Determine the context of each intersection. other.SetContext(m_Geom); // If end-to-end simple intersections are not required, weed them out. if (!m_WantEndEnd) other.CutEndEnd(); if (other.IntersectCount>0) m_Result.Add(other); } } return true; }
/// <summary> /// Delegate called to process each polygon found within the build window. /// Called by <c>BuildIslands</c> /// </summary> /// <param name="o">An item found in the spatial index.</param> /// <returns>True (always), indicating that the spatial query should keep going.</returns> bool ProcessPolygon(ISpatialObject o) { if (!(o is Island)) return true; // Just return if the enclosing polygon is already known Island pol = (Island)o; if (pol.Container!=null) return true; // If the island is marked as floating, and it has a window // that encloses the build window, mark it as not floating. // This covers situations where a previously floating island // is now enclosed by something. if (pol.IsFloating && pol.Extent.IsOverlap(m_NewPolygonExtent)) pol.IsFloating = false; pol.SetContainer(); return true; }
/// <summary> /// Delegate that's called whenever the index finds a polygon /// </summary> /// <param name="item">The item to process</param> /// <returns>True (always), indicating that the query should continue.</returns> private bool CleanupPolygon(ISpatialObject item) { Debug.Assert(item is Ring); Ring r = (Ring)item; if (r.IsDeleted) m_Deletions.Add(r); r.Clean(); return true; }
/// <summary> /// Delegate called to process each text feature found within the build window. /// Called by <see cref="BuildLabels"/>. /// </summary> /// <param name="o">An item found in the spatial index.</param> /// <returns>True (always), indicating that the spatial query should keep going.</returns> bool ProcessLabel(ISpatialObject o) { Debug.Assert(o is TextFeature); TextFeature f = (TextFeature)o; f.SetPolygon(); return true; }
/// <summary> /// Delegate that's called whenever the index finds an object with an extent that /// overlaps the query window. /// </summary> /// <param name="item">The item to process (expected to be some sort of <c>PointFeature</c>)</param> /// <returns>True (always), indicating that the query should continue.</returns> private bool OnQueryHit(ISpatialObject item) { Debug.Assert(item is PointFeature); PointFeature p = (PointFeature)item; if (m_Line.Distance(p).Meters > m_Tolerance) return true; if (!m_WantEnds && (m_Line.Start.IsCoincident(p) || m_Line.End.IsCoincident(p))) return true; m_Result.Add(p); return true; }
/// <summary> /// Delegate that's called whenever the index finds an object with an extent that /// overlaps the query window. /// </summary> /// <param name="item">The item to process (expected to be some sort of <c>Feature</c>)</param> /// <returns>True if the query should continue. False if the item is exactly coincident with /// the query position.</returns> bool OnQueryHit(ISpatialObject item) { double d = item.Distance(m_Position).Meters; if (d<=m_Distance) { m_Distance = d; m_Result = item; return (m_Distance > Double.Epsilon); } return true; }
/// <summary> /// Delegate that's called whenever the index finds a feature /// </summary> /// <param name="item">The item to process</param> /// <returns>True (always), indicating that the query should continue.</returns> private bool CleanupFeature(ISpatialObject item) { Debug.Assert(item is Feature); Feature f = (Feature)item; if (f.IsInactive) m_Deletions.Add(f); else if (f.IsMoved) m_Moves.Add(f); f.Clean(); return true; }
/// <summary> /// Delegate that's called whenever the index finds an object with an extent that /// overlaps the query window. /// </summary> /// <param name="item">The item to process (expected to be some sort of <c>Ring</c>)</param> /// <returns>True if the query should continue. False if the enclosing polygon has been found.</returns> private bool OnQueryHit(ISpatialObject item) { // We're only interested in real polygons (not islands) if (!(item is Polygon)) return true; // The window of the polygon has to overlap. Polygon p = (Polygon)item; if (!p.Extent.IsOverlap(m_Point)) return true; // Skip if it doesn't enclose the search position if (!p.IsRingEnclosing(m_Point)) return true; // If the polygon contains any islands, remember the polygon // for a further look. Things like an unclosed street network // can have MANY islands, so checking whether the position falls // inside any of them is a bit laborious. We'll comes back to // this polygon if we can't find an easy match. if (p.HasAnyIslands) { if (m_Candidates==null) m_Candidates = new List<Polygon>(1); m_Candidates.Add(p); return true; } m_Result = p; return false; }
/// <summary> /// Creates a new <c>FindClosestQuery</c> (and executes it). The result of the query /// can then be obtained through the <c>Result</c> property. /// </summary> /// <param name="index">The spatial index to search</param> /// <param name="p">The search position.</param> /// <param name="radius">The search tolerance (expected to be greater than zero).</param> /// <param name="types">The type of objects to look for.</param> internal FindClosestQuery(ISpatialIndex index, IPosition p, ILength radius, SpatialType types) { if (types==0) throw new ArgumentNullException("Spatial type(s) not specified"); // If the user hasn't been specific, ensure we don't search for polygons! SpatialType useTypes = (types==SpatialType.All ? SpatialType.Feature : types); Debug.Assert((useTypes & SpatialType.Polygon)==0); // It's important to round off to the nearest micron. Otherwise you might not // get the desired results in situations where the search radius is zero. m_Position = PositionGeometry.Create(p); m_Radius = radius; m_Types = types; m_Result = null; m_Distance = m_Radius.Meters; // The query will actually involve a square window, not a circle. IWindow x = new Window(m_Position, radius.Meters * 2.0); index.QueryWindow(x, useTypes, OnQueryHit); }
/// <summary> /// Checks if an object is acceptable for trimming. /// </summary> /// <param name="thing">The candidate object.</param> /// <returns>The supplied candidate, cast to a line (given that the candidate is /// suitable for trimming). Null if the candidate is not a line, or not suitable /// for trimming.</returns> static LineFeature PreCheck(ISpatialObject thing) { // It has no be a line LineFeature line = (thing as LineFeature); if (line==null) return null; // It has to be topological Topology t = line.Topology; if (t==null) return null; // The line should have system-defined topological line // sections (if it doesn't that would mean that the complete // line dangles). SectionTopologyList sectionList = (t as SectionTopologyList); if (sectionList==null) return null; if (sectionList.CanTrim()) return line; return null; }
/// <summary> /// Delegate called to process every polygon in the map. /// Called by <see cref="BuildLabels"/>. /// </summary> /// <param name="o">A polygon ring in the spatial index</param> /// <returns>True (always), to force examination of the entire spatial index</returns> bool FindLabelForPolygon(ISpatialObject o) { Debug.Assert(o is Ring); if (o is Polygon) { // Only process polygons that don't already have a label, and which // don't contain any islands (polygons with islands tend to cover // much larget areas, so trying to find the label this way will // probably not be very efficient). Polygon p = (Polygon)o; if (p.Label == null && !p.HasAnyIslands) { TextFeature label = new FindPolygonLabelQuery(m_Model.Index, p).Result; if (label != null) { p.ClaimLabel(label); label.SetBuilt(true); } } } return true; }
/// <summary> /// Delegate that's called whenever the index finds an object with an extent that /// overlaps the query window. /// </summary> /// <param name="item">The item to process</param> /// <returns>True (always), meaning the query should continue.</returns> bool OnQueryHit(ISpatialObject item) { if (m_DoPaint) { m_DoPaint = false; m_Display.PaintNow(); } item.Render(m_Display, m_Style); return true; }
/// <summary> /// Delegate called to process every line feature in the model. /// Called by <c>Build</c> /// </summary> /// <param name="o">An item found in the spatial index.</param> /// <returns>True (always), indicating that the spatial query should keep going.</returns> /// <exception cref="Exception">If an error occurred building a polygon.</exception> bool ProcessLine(ISpatialObject o) { Debug.Assert(o is LineFeature); LineFeature line = (LineFeature)o; try { line.BuildPolygons(m_NewPolygonExtent, m_Index); return true; } catch (Exception e) { string msg = String.Format("Error building polygon starting at line {0} ({1})", line.ToString(), e.Message); throw new Exception(msg); } }
/// <summary> /// Displays properties of currently selected spatial object (so long as /// the properties grid is shown). /// </summary> /// <param name="o"></param> internal void SetSelection(ISpatialObject o) { /* // TEST... Polygon p = (o as Polygon); if (p != null) { IPosition[] edge = p.GetOutline(new Length(0.001)); double ga1 = CadastralMapModel.Current.SpatialSystem.GetGroundArea(edge); double ga2 = CadastralMapModel.Current.CS.GetGroundArea(edge); MessageBox.Show(String.Format("ground area: {0:0.000000} vs {1:0.000000} - diff = {2:0.000000}", ga1, ga2, ga1 - ga2)); } */ if (vSplitContainer.Panel2Collapsed) return; propertyDisplay.SetSelectedObject(o); }
/// <summary> /// Creates new <c>CommandUI</c> that isn't an update. /// </summary> /// <param name="cc">The container that may be used to display any sort of /// user dialog (null if no dialog is involved)</param> /// <param name="cmdId">The item used to invoke the command.</param> /// <param name="update">The object (if any) that was selected for update</param> /// <param name="recall">An operation that is being recalled (null if this is an update).</param> protected CommandUI(IControlContainer cc, IUserAction cmdId, ISpatialObject update, Operation recall) { m_Container = cc; m_Draw = EditingController.Current.ActiveDisplay; //m_Update = update; m_UpdCmd = null; m_Recall = recall; if (cmdId is EditingAction) m_EditId = (cmdId as EditingAction).EditId; else m_EditId = EditingActionId.Null; if (cmdId is RecalledEditingAction) m_Recall = (cmdId as RecalledEditingAction).RecalledEdit; Debug.Assert(m_Draw!=null); }
/// <summary> /// Delegate that's called whenever the index finds a line with a window that overlaps the query window /// </summary> /// <param name="item">The item to process (expected to be some sort of <c>LineFeature</c>)</param> /// <returns>True (always), indicating that the query should continue.</returns> private bool OnLineFound(ISpatialObject item) { LineFeature line = (LineFeature)item; // If either line end point is in the list of selected points, just accept the line. // Otherwise check whether the closed shape overlaps (or intersects) the line. if (m_Points.Contains(line.StartPoint) || m_Points.Contains(line.EndPoint) || m_ClosedShape.IsOverlap(line.LineGeometry)) m_Result.Add(line); return true; }
void AddOrRemoveFromSelection(ISpatialObject so) { Selection sel = new Selection(this.SpatialSelection.Items); if (!sel.Remove(so)) sel.Add(so); SetSelection(sel); }
/// <summary> /// Delegate that's called whenever the index finds a point that's inside the query window /// </summary> /// <param name="item">The item to process (expected to be some sort of <c>PointFeature</c>)</param> /// <returns>True (always), indicating that the query should continue.</returns> private bool OnPointFound(ISpatialObject item) { PointFeature p = (PointFeature)item; if (m_ClosedShape.IsOverlap(p)) m_Points.Add(p); return true; }
/// <summary> /// Starts some sort of update. If the selected item is a polygon that has associated /// database attributes, a dialog will be displayed to let the user change the attributes. /// For any other spatial feature, the dialog for updating an editing operation will be /// displayed. /// </summary> /// <param name="so">The item selected for update</param> internal void RunUpdate(IUserAction action, ISpatialObject so) { if (so==null) return; // There can't be any command currently running. if (m_Command != null) return; // If we're currently auto-highlighting, get rid of it. AutoSelect = false; // If a polygon has been selected, invoke the attribute update dialog. Otherwise // start an update command. if (so.SpatialType == SpatialType.Polygon) { m_Main.UpdatePolygon((Polygon)so); } else { ClearSelection(); UpdateUI upui = new UpdateUI(action); m_Command = upui; // We will have a DividerObject if the user selected a line // that has been intersected against other lines. In that case, // run the update using the underlying line. if (so is DividerObject) upui.Run((so as DividerObject).Divider.Line); else upui.Run((Feature)so); } }
/// <summary> /// Delegate that's called whenever the index finds text with a window that overlaps the query window /// </summary> /// <param name="item">The item to process (expected to be some sort of <c>TextFeature</c>)</param> /// <returns>True (always), indicating that the query should continue.</returns> private bool OnTextFound(ISpatialObject item) { TextFeature text = (TextFeature)item; // Get the outline for the text IPosition[] outline = text.TextGeometry.Outline; // If any corner of the text outline is inside the closed shape (or any edge of // the outline intersects), remember the text in the results ClosedShape cs = new ClosedShape(outline); if (cs.IsOverlap(m_ClosedShape)) m_Result.Add(text); return true; }
/// <summary> /// Obtains any miscellaneous attribute data for a specific spatial object /// </summary> /// <param name="so">The object of interest</param> /// <returns>Any attributes for the spatial object (never null, but may be an empty list)</returns> List<Row> GetRows(ISpatialObject so) { List<Row> result = new List<Row>(); Feature f = (so as Feature); if (f == null && so is Polygon) f = (so as Polygon).Label; if (f != null && f.FeatureId != null) { FeatureId fid = f.FeatureId; IPossibleList<Row> rows = fid.Rows; if (rows != null) { foreach (Row r in rows) result.Add(r); } } return result; }