private Dictionary <int, LinkedInstanceData> GetLinkedInstancesInfo()
        {
            Dictionary <int, LinkedInstanceData> linkedInstances = new Dictionary <int, LinkedInstanceData>();

            try
            {
                FilteredElementCollector collector          = new FilteredElementCollector(m_doc);
                List <RevitLinkInstance> revitLinkInstances = collector.OfCategory(BuiltInCategory.OST_RvtLinks).WhereElementIsNotElementType().Cast <RevitLinkInstance>().ToList();

                foreach (RevitLinkInstance instance in revitLinkInstances)
                {
                    if (null != instance.Document)
                    {
                        LinkedInstanceData lid = new LinkedInstanceData(instance);
                        if (!linkedInstances.ContainsKey(lid.InstanceId))
                        {
                            linkedInstances.Add(lid.InstanceId, lid);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Failed to get the information of linked instances.\n" + ex.Message, "Find Linked Instances", MessageBoxButton.OK, MessageBoxImage.Warning);
            }

            return(linkedInstances);
        }
        private bool CheckVisibilityByMaterial(ReferenceIntersector intersector, XYZ pointOrigin, List <XYZ> viewPoints)
        {
            bool visible = false;

            try
            {
                foreach (XYZ vPt in viewPoints)
                {
                    XYZ direction = vPt - pointOrigin;
                    IList <ReferenceWithContext> contexts = intersector.Find(pointOrigin, direction);

                    if (null != contexts)
                    {
                        var filteredContexts = from context in contexts where context.Proximity > epsilon select context;
                        filteredContexts = filteredContexts.OrderBy(x => x.Proximity).ToList();

                        if (filteredContexts.Count() > 0)
                        {
                            visible = true;
                            foreach (ReferenceWithContext context in filteredContexts)
                            {
                                Reference reference = context.GetReference();
                                Element   element   = null;
                                Transform transform = Transform.Identity;

                                if (reference.LinkedElementId != ElementId.InvalidElementId)
                                {
                                    //element from linked models
                                    if (linkedInstances.ContainsKey(reference.ElementId.IntegerValue))
                                    {
                                        LinkedInstanceData lid = linkedInstances[reference.ElementId.IntegerValue];
                                        element   = lid.LinkedDocument.GetElement(reference.LinkedElementId);
                                        transform = lid.TransformValue;
                                    }
                                }
                                else
                                {
                                    //element from host
                                    element = m_doc.GetElement(reference.ElementId);
                                }

                                if (null != element)
                                {
                                    int categoryId = element.Category.Id.IntegerValue;
                                    if (categoryId == (int)BuiltInCategory.OST_Walls)
                                    {
                                        Wall wall = element as Wall;
                                        if (null != wall)
                                        {
                                            if (wall.WallType.Kind != WallKind.Curtain)
                                            {
                                                visible = false; break;
                                            }
                                            else
                                            {
                                                var exteriorWalls = from exWall in exteriorElementIds
                                                                    where exWall.LinkInstanceId == reference.ElementId && (exWall.HostElementId == reference.LinkedElementId || exWall.LinkedElementId == reference.LinkedElementId)
                                                                    select exWall;
                                                if (exteriorWalls.Count() > 0)
                                                {
                                                    break; //exterior curtain walls
                                                }
                                            }
                                        }
                                        else
                                        {
                                            //family instance of wall
                                            visible = false; break;
                                        }
                                    }
                                    else if (categoryId == (int)BuiltInCategory.OST_StructuralColumns)
                                    {
                                        visible = false; break;
                                    }
                                    else if (categoryId == (int)BuiltInCategory.OST_Windows || categoryId == (int)BuiltInCategory.OST_Doors || categoryId == (int)BuiltInCategory.OST_CurtainWallPanels)
                                    {
                                        Face face = FindFaceByReference(element, reference, transform);
                                        if (null != face)
                                        {
                                            if (face.MaterialElementId != ElementId.InvalidElementId)
                                            {
                                                Material material = element.Document.GetElement(face.MaterialElementId) as Material;
                                                if (material.Transparency < minTransparency)
                                                {
                                                    visible = false; break;
                                                }
                                            }
                                        }

                                        FamilyInstance instance = element as FamilyInstance;
                                        if (null != instance)
                                        {
                                            if (null != instance.Host)
                                            {
                                                ElementId wallId        = instance.Host.Id;
                                                var       exteriorWalls = from exWall in exteriorElementIds
                                                                          where exWall.LinkInstanceId == reference.ElementId && (exWall.HostElementId == wallId || exWall.LinkedElementId == wallId)
                                                                          select exWall;
                                                if (exteriorWalls.Count() > 0)
                                                {
                                                    break; //exterior curtain walls
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                            if (visible)
                            {
                                break; //at least one direction should be visible
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                string message = ex.Message;
            }
            return(visible);
        }