Revit API Forum
Welcome to Autodesk’s Revit API Forums. Share your knowledge, ask questions, and explore popular Revit API topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Room color scheme

2 REPLIES 2
SOLVED
Reply
Message 1 of 3
Anonymous
1449 Views, 2 Replies

Room color scheme

Anonymous
Not applicable

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 !

0 Likes

Room color scheme

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 !

2 REPLIES 2
Message 2 of 3
FAIR59
in reply to: Anonymous

FAIR59
Advisor
Advisor
Accepted 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:

  1. isolate (and deselect) a room
  2. zoom to fit
  3. find a point in the room
  4. find the screen coordinate of that point
  5. get the color using the windows functions of user32.dll.
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:

  1. isolate (and deselect) a room
  2. zoom to fit
  3. find a point in the room
  4. find the screen coordinate of that point
  5. get the color using the windows functions of user32.dll.
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

Message 3 of 3
Anonymous
in reply to: FAIR59

Anonymous
Not applicable

Very impressive,

Thank you !

0 Likes

Very impressive,

Thank you !

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report