Hi !
I'm trying to get the Color of a Room inside a specific ViewPlan (The color come from a Color Scheme).
I know the API does not currently provide any access to this feature even if the community asks it since a long time.
But did you guys found some weird magic voodoo workaround to get this color ?
Any help is welcome !
Thanks !
Solved! Go to Solution.
Hi !
I'm trying to get the Color of a Room inside a specific ViewPlan (The color come from a Color Scheme).
I know the API does not currently provide any access to this feature even if the community asks it since a long time.
But did you guys found some weird magic voodoo workaround to get this color ?
Any help is welcome !
Thanks !
Solved! Go to Solution.
Solved by FAIR59. Go to Solution.
As you said, Revit doesn't expose the color scheme of a view. There is another "program" that "knows" the color of a Room, namely the computer / the screen. This means that you can find the color of the rooms visible in the active view.
Steps:
using System;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
using Autodesk.Revit.UI.Selection;
using System.Collections.Generic;
using System.IO;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Automation;
Room r; Document doc; UIDocument uiapp;
StringBuilder sb = new StringBuilder(); View activeView = doc.ActiveView; uiapp.Selection.SetElementIds(new List<ElementId>()); Category roomCat = doc.Settings.Categories.get_Item("Rooms"); Category colorfill = roomCat.SubCategories.get_Item("Color Fill"); if (!activeView.GetVisibility(colorfill)) { TaskDialog.Show("warning","room colorfill is not visible"); return; } using (TransactionGroup tg = new TransactionGroup(doc, "GetRoomColor")) { tg.Start(); using (Transaction t = new Transaction(doc, "isolate room")) { t.Start(); doc.ActiveView.IsolateElementTemporary(r.Id); uiapp.ShowElements( r.Id); uiapp.RefreshActiveView(); t.Commit(); } using (Transaction t = new Transaction(doc, "regenerate")) { t.Start(); doc.Regenerate(); uiapp.RefreshActiveView(); t.Commit(); }
// find outer boundary points List<XYZ> boundaryPoints = new List<XYZ>(); SpatialElementBoundaryOptions opt = new SpatialElementBoundaryOptions(); opt.SpatialElementBoundaryLocation = SpatialElementBoundaryLocation.Finish; opt.StoreFreeBoundaryFaces = true; foreach(var segmList in r.GetBoundarySegments(opt)) { foreach(var _boundarySegment in segmList) { boundaryPoints.AddRange(_boundarySegment.GetCurve().Tessellate()); boundaryPoints.Remove(boundaryPoints.Last()); } break; // consider only outer boundary } XYZ pointinRoom = boundaryPoints[0].Add(boundaryPoints[2]).Multiply(0.5); // corner of 180 degrees will fail!!!
XYZ corner = boundaryPoints[1]; while (!r.IsPointInRoom(pointinRoom)) { pointinRoom = pointinRoom.Add(corner).Multiply(0.5); } List<UIView> uiViewsWithActiveView = new List<UIView>(); foreach (UIView uiv in uiapp.GetOpenUIViews()) { if (uiv.ViewId.IntegerValue == activeView.Id.IntegerValue) uiViewsWithActiveView.Add(uiv); } UIView ActiveUIView = uiViewsWithActiveView.FirstOrDefault(); if (uiViewsWithActiveView.Count>1) { // 2 or more windows showing the same view // use Automation to find the active window IntPtr revitHandle = System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle; AutomationElement root = AutomationElement.FromHandle(revitHandle); // find the container control for the open views PropertyCondition workSpaceCondition = new PropertyCondition( AutomationElement.ClassNameProperty, "MDIClient"); AutomationElement workspace = root.FindFirst(TreeScope.Descendants,workSpaceCondition); //find the active window in the workspace == first childwindow AutomationElement firstviewWindow = workspace.FindFirst(TreeScope.Children,Condition.TrueCondition); PropertyCondition classCondition = new PropertyCondition( AutomationElement.ClassNameProperty, "AfxFrameOrView110u"); //get clientrectangle AutomationElement viewPane = firstviewWindow.FindFirst(TreeScope.Children,classCondition); System.Windows.Rect boundingRect1; object boundingRectNoDefault = viewPane.GetCurrentPropertyValue(AutomationElement.BoundingRectangleProperty, true); //select uiview with identical clientrectangle boundingRect1 = (System.Windows.Rect)boundingRectNoDefault; foreach(UIView uiv in uiViewsWithActiveView) { Rectangle r1 = uiv.GetWindowRectangle(); if( r1.Left == boundingRect1.Left && r1.Top==boundingRect1.Top && r1.Right == boundingRect1.Right && r1.Bottom == boundingRect1.Bottom) { ActiveUIView = uiv; break; } } } if (ActiveUIView==null) return; // get screen coordinates of active view Rectangle rect = ActiveUIView.GetWindowRectangle(); // get cornerpoints of active view IList<XYZ> corners = ActiveUIView.GetZoomCorners(); XYZ p = corners[0]; XYZ q = corners[1]; // find screencoordinate of pointinRoom double dX = activeView.RightDirection.DotProduct(pointinRoom.Subtract(p))/activeView.RightDirection.DotProduct(q.Subtract(p)); double dY = activeView.UpDirection.DotProduct(pointinRoom.Subtract(p))/activeView.UpDirection.DotProduct(q.Subtract(p)); int screenX = (int) (rect.Left + dX*(rect.Right-rect.Left)); int screenY = (int) (rect.Top + dY*(rect.Bottom-rect.Top)); sb.AppendLine(string.Format("screencoordinates: {0}, {1}",screenX,screenY)); // getcolor System.Drawing.Color color = WindowHelper.GetPixelColor(screenX,screenY); sb.AppendLine("RoomColor = "+ WindowHelper.ToRGBString( WindowHelper.ToRevitColor( color))); tg.RollBack(); } TaskDialog.Show("debug", sb.ToString());
using this helper class
public class WindowHelper { // ****************************************************************** [DllImport("user32.dll")] static extern IntPtr GetDC(IntPtr hwnd); [DllImport("user32.dll")] static extern Int32 ReleaseDC(IntPtr hwnd, IntPtr hdc); [DllImport("gdi32.dll")] static extern uint GetPixel(IntPtr hdc, int nXPos, int nYPos); static public System.Drawing.Color GetPixelColor(int x, int y ) { IntPtr hdc = GetDC(IntPtr.Zero); uint value2 = GetPixel(hdc,x,y); uint pixel =GetPixel(hdc,x,y); bool condition = pixel.Equals(value2); int aant=0; while (!condition && aant<1000) { aant++; value2 = pixel; pixel = GetPixel(hdc,x,y); condition = pixel.Equals(value2); } ReleaseDC(IntPtr.Zero, hdc); System.Drawing.Color color = System.Drawing.Color.FromArgb( (byte)(pixel & 0x000000FF), (byte)((pixel & 0x0000FF00) >> 8), (byte)((pixel & 0x00FF0000) >> 16)); return color; }
Add References:
System.Windows.Forms
UIAutomationClient
UIAutomationTypes
WindowBase
As you said, Revit doesn't expose the color scheme of a view. There is another "program" that "knows" the color of a Room, namely the computer / the screen. This means that you can find the color of the rooms visible in the active view.
Steps:
using System;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Architecture;
using Autodesk.Revit.UI.Selection;
using System.Collections.Generic;
using System.IO;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Automation;
Room r; Document doc; UIDocument uiapp;
StringBuilder sb = new StringBuilder(); View activeView = doc.ActiveView; uiapp.Selection.SetElementIds(new List<ElementId>()); Category roomCat = doc.Settings.Categories.get_Item("Rooms"); Category colorfill = roomCat.SubCategories.get_Item("Color Fill"); if (!activeView.GetVisibility(colorfill)) { TaskDialog.Show("warning","room colorfill is not visible"); return; } using (TransactionGroup tg = new TransactionGroup(doc, "GetRoomColor")) { tg.Start(); using (Transaction t = new Transaction(doc, "isolate room")) { t.Start(); doc.ActiveView.IsolateElementTemporary(r.Id); uiapp.ShowElements( r.Id); uiapp.RefreshActiveView(); t.Commit(); } using (Transaction t = new Transaction(doc, "regenerate")) { t.Start(); doc.Regenerate(); uiapp.RefreshActiveView(); t.Commit(); }
// find outer boundary points List<XYZ> boundaryPoints = new List<XYZ>(); SpatialElementBoundaryOptions opt = new SpatialElementBoundaryOptions(); opt.SpatialElementBoundaryLocation = SpatialElementBoundaryLocation.Finish; opt.StoreFreeBoundaryFaces = true; foreach(var segmList in r.GetBoundarySegments(opt)) { foreach(var _boundarySegment in segmList) { boundaryPoints.AddRange(_boundarySegment.GetCurve().Tessellate()); boundaryPoints.Remove(boundaryPoints.Last()); } break; // consider only outer boundary } XYZ pointinRoom = boundaryPoints[0].Add(boundaryPoints[2]).Multiply(0.5); // corner of 180 degrees will fail!!!
XYZ corner = boundaryPoints[1]; while (!r.IsPointInRoom(pointinRoom)) { pointinRoom = pointinRoom.Add(corner).Multiply(0.5); } List<UIView> uiViewsWithActiveView = new List<UIView>(); foreach (UIView uiv in uiapp.GetOpenUIViews()) { if (uiv.ViewId.IntegerValue == activeView.Id.IntegerValue) uiViewsWithActiveView.Add(uiv); } UIView ActiveUIView = uiViewsWithActiveView.FirstOrDefault(); if (uiViewsWithActiveView.Count>1) { // 2 or more windows showing the same view // use Automation to find the active window IntPtr revitHandle = System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle; AutomationElement root = AutomationElement.FromHandle(revitHandle); // find the container control for the open views PropertyCondition workSpaceCondition = new PropertyCondition( AutomationElement.ClassNameProperty, "MDIClient"); AutomationElement workspace = root.FindFirst(TreeScope.Descendants,workSpaceCondition); //find the active window in the workspace == first childwindow AutomationElement firstviewWindow = workspace.FindFirst(TreeScope.Children,Condition.TrueCondition); PropertyCondition classCondition = new PropertyCondition( AutomationElement.ClassNameProperty, "AfxFrameOrView110u"); //get clientrectangle AutomationElement viewPane = firstviewWindow.FindFirst(TreeScope.Children,classCondition); System.Windows.Rect boundingRect1; object boundingRectNoDefault = viewPane.GetCurrentPropertyValue(AutomationElement.BoundingRectangleProperty, true); //select uiview with identical clientrectangle boundingRect1 = (System.Windows.Rect)boundingRectNoDefault; foreach(UIView uiv in uiViewsWithActiveView) { Rectangle r1 = uiv.GetWindowRectangle(); if( r1.Left == boundingRect1.Left && r1.Top==boundingRect1.Top && r1.Right == boundingRect1.Right && r1.Bottom == boundingRect1.Bottom) { ActiveUIView = uiv; break; } } } if (ActiveUIView==null) return; // get screen coordinates of active view Rectangle rect = ActiveUIView.GetWindowRectangle(); // get cornerpoints of active view IList<XYZ> corners = ActiveUIView.GetZoomCorners(); XYZ p = corners[0]; XYZ q = corners[1]; // find screencoordinate of pointinRoom double dX = activeView.RightDirection.DotProduct(pointinRoom.Subtract(p))/activeView.RightDirection.DotProduct(q.Subtract(p)); double dY = activeView.UpDirection.DotProduct(pointinRoom.Subtract(p))/activeView.UpDirection.DotProduct(q.Subtract(p)); int screenX = (int) (rect.Left + dX*(rect.Right-rect.Left)); int screenY = (int) (rect.Top + dY*(rect.Bottom-rect.Top)); sb.AppendLine(string.Format("screencoordinates: {0}, {1}",screenX,screenY)); // getcolor System.Drawing.Color color = WindowHelper.GetPixelColor(screenX,screenY); sb.AppendLine("RoomColor = "+ WindowHelper.ToRGBString( WindowHelper.ToRevitColor( color))); tg.RollBack(); } TaskDialog.Show("debug", sb.ToString());
using this helper class
public class WindowHelper { // ****************************************************************** [DllImport("user32.dll")] static extern IntPtr GetDC(IntPtr hwnd); [DllImport("user32.dll")] static extern Int32 ReleaseDC(IntPtr hwnd, IntPtr hdc); [DllImport("gdi32.dll")] static extern uint GetPixel(IntPtr hdc, int nXPos, int nYPos); static public System.Drawing.Color GetPixelColor(int x, int y ) { IntPtr hdc = GetDC(IntPtr.Zero); uint value2 = GetPixel(hdc,x,y); uint pixel =GetPixel(hdc,x,y); bool condition = pixel.Equals(value2); int aant=0; while (!condition && aant<1000) { aant++; value2 = pixel; pixel = GetPixel(hdc,x,y); condition = pixel.Equals(value2); } ReleaseDC(IntPtr.Zero, hdc); System.Drawing.Color color = System.Drawing.Color.FromArgb( (byte)(pixel & 0x000000FF), (byte)((pixel & 0x0000FF00) >> 8), (byte)((pixel & 0x00FF0000) >> 16)); return color; }
Add References:
System.Windows.Forms
UIAutomationClient
UIAutomationTypes
WindowBase
Very impressive,
Thank you !
Very impressive,
Thank you !
Can't find what you're looking for? Ask the community or share your knowledge.