public DOEgbXMLPhase2Report Copy()
        {
            DOEgbXMLPhase2Report report = new DOEgbXMLPhase2Report();

            report.standResult    = new List <string>(this.standResult);
            report.testResult     = new List <string>(this.testResult);
            report.idList         = new List <string>(this.idList);
            report.TestPassedDict = new Dictionary <string, bool>(this.TestPassedDict);
            report.OutputTypeDict = new Dictionary <string, OutPutEnum>(this.OutputTypeDict);
            report.MessageDict    = new Dictionary <string, string>(this.MessageDict);
            report.MessageList    = new Dictionary <string, List <string> >(this.MessageList);
            //  if (this.MatchedSurfaceIds != null)
            //      report.MatchedSurfaceIds = new Dictionary<string, List<string>>(this.MatchedSurfaceIds);


            report.tolerance    = this.tolerance;
            report.testType     = this.testType;
            report.outputType   = this.outputType;
            report.subTestIndex = this.subTestIndex;
            report.unit         = this.unit;
            report.passOrFail   = this.passOrFail;
            report.longMsg      = this.longMsg;

            report.testSummary = this.testSummary;

            return(report);
        }
        public static DOEgbXMLPhase2Report SurfaceAdjSpaceIdTest(List<string> surfaceIds, List<SurfaceDefinitions> surfaces, DOEgbXMLPhase2Report report)
        {
            report.testSummary = "This test ensures that each surface adjacent space id is not assigned to any random or undeclared space id.";
            try
            {
                foreach (SurfaceDefinitions s in surfaces)
                {
                    List<string> ml = new List<string>();
                    ml.Add(s.SurfaceId + " testing begins to ensure adjacent space ids match Space ids.");
                    //test each surface
                    foreach (string ajid in s.AdjSpaceId)
                    {
                        if(surfaceIds.Contains(ajid))
                        {
                            //good
                            ml.Add("PASS: "******" match has been found for :" + s.SurfaceId);
                            report.TestPassedDict[s.SurfaceId] = true;
                        }
                        else
                        {
                            //bad
                            ml.Add("FAIL: There is not Space id called: " + ajid);
                            report.TestPassedDict[s.SurfaceId] = false;
                        }

                    }
                    report.MessageList[s.SurfaceId] = ml;
                }
            }
            catch (Exception e)
            {
                report.longMsg = ("SORRY, we have run into an unexpected issue:" + e.ToString());
                report.passOrFail = false;
                return report;
            }

            if (report.TestPassedDict.ContainsValue(false))
            {
                report.longMsg = "TEST FAILED: Surfaces have adjacent space ids that are not declared at the Space level.";
                report.passOrFail = false;
                
            }
            else
            {
                report.longMsg = "TEST PASSED: All Surfaces have adjacent space ids that match to a Space id already described.";
                report.passOrFail = true;
                
            }
            return report;
        }
        public static DOEgbXMLPhase2Report SurfaceCCTest(Dictionary<string,List<SurfaceDefinitions>> enclosure, DOEgbXMLPhase2Report report)
        {
            //this summary is text that describes to a lay user what this test does, and how it works functionally.  The user should have some familiarity with the basic knowledge of gbXML 
            //added Feb 17 2014
            report.testSummary = "This test ensures that each Surface has PolyLoop coordinate descriptions that wind in a counter clockwise order.";
            
            report.TestPassedDict = new Dictionary<string, bool>();
            try
            {
                
                foreach (KeyValuePair<string,List<SurfaceDefinitions>> kp in enclosure)
                {
                    List<string> ml = new List<string>();
                    

                    //this fakespacecount is a dummy because NamedSurfaceCCTest requires an integer.
                    int fakespacecount = 0;
                    Dictionary<string,List<Vector.MemorySafe_CartCoord>> sbcc = new Dictionary<string,List<Vector.MemorySafe_CartCoord>>();
                    foreach (SurfaceDefinitions s in kp.Value)
                    {
                        List<Vector.MemorySafe_CartCoord> pl = new List<Vector.MemorySafe_CartCoord>();
                        //different conditions if interior or exterior
                        if (s.AdjSpaceId.Count() == 1)
                        {
                            foreach (Vector.MemorySafe_CartCoord p in s.PlCoords)
                            {
                                Vector.MemorySafe_CartCoord msp = new Vector.MemorySafe_CartCoord(p.X, p.Y, p.Z);
                                pl.Add(msp);
                            }
                            sbcc[s.SurfaceId] = pl;
                            continue;
                        }
                        //implied that the count is equal to 2
                        else
                        {
                            for (int i = 0; i < s.AdjSpaceId.Count(); i++)
                            {
                                if (s.AdjSpaceId[i] == s.AdjSpaceId[i + 1])
                                {
                                    //slab on grade
                                    //treat normally
                                    foreach (Vector.MemorySafe_CartCoord p in s.PlCoords)
                                    {
                                        Vector.MemorySafe_CartCoord msp = new Vector.MemorySafe_CartCoord(p.X, p.Y, p.Z);
                                        pl.Add(msp);
                                    }
                                    sbcc[s.SurfaceId] = pl;
                                    break;
                                }
                                else
                                {
                                    //some other sort of typical interior surface.  outward normal points away from first, toward second.
                                    //if the adj id value of first is equal to space id, leave alone
                                    //otherwise reverse
                                    if (s.AdjSpaceId[i] == kp.Key)
                                    {
                                        foreach (Vector.MemorySafe_CartCoord p in s.PlCoords)
                                        {
                                            Vector.MemorySafe_CartCoord msp = new Vector.MemorySafe_CartCoord(p.X, p.Y, p.Z);
                                            pl.Add(msp);
                                        }
                                        sbcc[s.SurfaceId] = pl;
                                        break;
                                    }
                                    else
                                    {
                                        s.PlCoords.Reverse();
                                        foreach (Vector.MemorySafe_CartCoord p in s.PlCoords)
                                        {
                                            Vector.MemorySafe_CartCoord msp = new Vector.MemorySafe_CartCoord(p.X, p.Y, p.Z);
                                            pl.Add(msp);
                                        }
                                        sbcc[s.SurfaceId] = pl;
                                        s.PlCoords.Reverse();
                                        break;

                                    }
                                }
                            }
                        }
                    }
                    
                    Vector.MemorySafe_CartCoord sbcentroid = Vector.FindVolumetricCentroid(sbcc);
                    Dictionary<string, bool> surfres = Vector.NamedSurfacesCCWound(sbcentroid, sbcc,fakespacecount,false);

                    
                    foreach (KeyValuePair<string, bool> surfkp in surfres)
                    {
                        //since I have already checked to see if the names of the ids are unique, there is no reason to re-check something that has been checked.
                        //I could alternatively stry and store things at the Space level, but this doesn't really make sense, since this is specifically a Surface test
                        if(report.TestPassedDict.ContainsKey(surfkp.Key)) continue;
                        if (surfkp.Value == true)
                        {
                            ml.Add("PASS: Surface Boundary with id " + surfkp.Key + " is wound in a counterclockwise order.");
                        }
                        else
                        {
                            ml.Add("FAIL: Surface Boundary with id " + surfkp.Key + " is wound in a clockwise order.");
                        }
                    }
                    report.MessageList[kp.Key] = ml;

                }
        
            }
            catch (Exception e)
            {
                report.longMsg = ("SORRY, we have run into an unexpected issue:" + e.ToString());
                report.passOrFail = false;
                return report;
            }
            //if we have made it this far, that is good.
            if (report.TestPassedDict.ContainsValue(false))
            {
                report.longMsg = "TEST FAILED: Surfaces have been detected with clockwise winding orders.  We suggest reviewing if these errors have occurred on interior ";
                report.longMsg += " or exterior surfaces.  If interior surfaces, likely this will not be a problem unless the order of insulation materials for your interior";
                report.longMsg += " surface is important.  Exterior surfaces pointing with incorrect orientation is a problem.  In either case, we suggest you contact your BIM authoring tool ";
                report.longMsg += " to let them know there is an error.";
                report.passOrFail = false;
                return report;
            }
            else
            {
                report.longMsg = "TEST PASSED: All Surfaces have counter-clockwise winding orders.";
                report.passOrFail = true;
                return report;
            }
        }
        public static DOEgbXMLPhase2Report SurfaceMatchesSpaceBoundary(XmlDocument gbXMLDoc, XmlNamespaceManager gbXMLnsm, DOEgbXMLPhase2Report report)
        {
            report.testSummary = "Testing whether the Surface Elements and Space Boundary have matching PolyLoops and ID attributes";
            report.testSummary += "  It is a requirement that Surface ID and Space Boundary surfaceIdRef have the same value.";

            report.TestPassedDict = new Dictionary<string, bool>();
            //pass or fail attribute should always be set to false
            //Feb 5, 2014 - This test ensures that the Surface element definition matches the Space Boundary Definition.  They should be equal
            
            try
            {
                List<SurfaceDefinitions> surfList = DOEgbXML.XMLParser.GetFileSurfaceDefs(gbXMLDoc, gbXMLnsm);
                List<gbXMLSpaces.SpaceBoundary> sbList = gbXMLSpaces.GetSpaceBoundaryList(gbXMLDoc, gbXMLnsm);
                

                foreach (gbXMLSpaces.SpaceBoundary sb in sbList)
                {
                    List<string> ml = new List<string>();
                    //surfaceID for reporting
                    string sbId = sb.surfaceIdRef;
                    List<Vector.MemorySafe_CartCoord> sbCoords = sb.sbplane.pl.plcoords;
                    //we have to make this assumption
                    string surfaceID = sbId;
                    List<Vector.CartCoord> surfaceCoords = new List<Vector.CartCoord>();
                    int matchedCoordCount = 0;
                    for (int surfnum = 0; surfnum < surfList.Count; surfnum++)
                    {
                        if (surfList[surfnum].SurfaceId == surfaceID)
                        {
                            matchedCoordCount = 0;
                            for (int sbct = 0; sbct < sbCoords.Count; sbct++)
                            {
                                Vector.MemorySafe_CartCoord sbcoord = sbCoords[sbct];
                                for (int i = 0; i < surfList[surfnum].PlCoords.Count; i++)
                                {
                                    Vector.MemorySafe_CartCoord surfcoord = surfList[surfnum].PlCoords[i];
                                    //find a vertex match.  They should match exactly!  No tolerances.  No duplicate vertexes allowed!
                                    if (surfcoord.X == sbcoord.X && surfcoord.Y == sbcoord.Y && surfcoord.Z == sbcoord.Z)
                                    {
                                        ml.Add("PERFECT MATCH:  Surface coordinate perfect match, for coordinate: (" + surfcoord.X + "," + surfcoord.Y + "," + surfcoord.Z + ")");
                                        matchedCoordCount++;
                                        break;
                                    }
                                    else if (Math.Abs(surfcoord.X - sbcoord.X) < report.tolerance && Math.Abs(surfcoord.Y - sbcoord.Y) < report.tolerance && Math.Abs(surfcoord.Z - sbcoord.Z) < report.tolerance)
                                    {
                                        ml.Add("MATCH:  Surface coordinates match within allowable tolerance, for coordinate: (" + surfcoord.X + "," + surfcoord.Y + "," + surfcoord.Z + ")");
                                        matchedCoordCount++;
                                        break;
                                    }
                                }
                            }
                        }
                        else
                        {
                            if (surfnum == surfList.Count - 1)
                            {
                                ml.Add("FAILURE: Could not find a match of Ids between Surface and Space Boundary for Surface ID: " + sbId);
                                report.TestPassedDict.Add(sbId, false);
                                //for now we want to continue and just report that this did not work, in the future, this could be a hard fail.
                                continue;
                            }
                            else
                            {
                                //try to find in the next loop around
                                continue;
                            }
                        }
                        //we are done
                        if (matchedCoordCount == sbCoords.Count)
                        {
                            ml.Add("PASS: Surface has matched all coordinates with the SurfaceBoundary Coordinates.");
                            if(report.TestPassedDict.ContainsKey(sbId))
                            {
                                //this is my special way of allowing a surface boundary to be represented twice
                                report.TestPassedDict.Add(sbId+"-2", true);
                                report.MessageList[sbId+"-2"] = ml;
                            }
                            else
                            {
                                report.TestPassedDict.Add(sbId, true);
                                report.MessageList[sbId] = ml;
                            }
                            break;
                        }
                        else
                        {
                            //could not match the coordinates in any way shape or form
                            ml.Add("FAIL:  Surface could not match its coordinates with the SpaceBoundary Coordinates.");
                            if (report.TestPassedDict.ContainsKey(sbId))
                            {
                                report.TestPassedDict.Add(sbId+"-2", false);
                                report.MessageList[sbId+"-2"] = ml;
                            }
                            else
                            {
                                report.TestPassedDict.Add(sbId, false);
                                report.MessageList[sbId] = ml;
                            }
                            //for now we want to continue and just report that this did not work, in the future, this could be a hard fail.
                            break;
                        }
                    }
                    
                }
            }
            catch (Exception e)
            {
                report.longMsg = ("SORRY, we have run into an unexpected issue:" + e.ToString());
                report.passOrFail = false;
                return report;
            }
            //if we have made it here, we've passed all the tests and should have made it through.
            if (report.TestPassedDict.ContainsValue(false))
            {
                report.longMsg = "TEST FAIL:  There were some errors found when matching the Surface and Space Boundaries coordinates.";
                report.passOrFail = false;
                return report;
            }
            else
            {
                report.longMsg = "TEST PASSED:  All Surfaces found a SpaceBoundary counterpart.";
                report.passOrFail = true;
                return report;
            }
        }
        public DOEgbXMLPhase2Report Copy()
        {
            DOEgbXMLPhase2Report report = new DOEgbXMLPhase2Report();

            report.standResult = new List<string>(this.standResult);
            report.testResult = new List<string>(this.testResult);
            report.idList = new List<string>(this.idList);
            report.TestPassedDict = new Dictionary<string, bool>(this.TestPassedDict);
            report.MessageList = new Dictionary<string,List<string>>(this.MessageList);
            //  if (this.MatchedSurfaceIds != null)
            //      report.MatchedSurfaceIds = new Dictionary<string, List<string>>(this.MatchedSurfaceIds);


            report.tolerance = this.tolerance;
            report.testType = this.testType;
            report.subTestIndex = this.subTestIndex;
            report.unit = this.unit;
            report.passOrFail = this.passOrFail;
            report.longMsg = this.longMsg;

            report.testSummary = this.testSummary;

            return report;
        }
        private void ProcessValidXML(XMLParser parser, XmlReader xmlreader2)
        {
            // Phase 2 Testing
            XmlDocument myxml = new XmlDocument();
            myxml.Load(xmlreader2);
            //3-get the namespace
            XmlNamespaceManager nsm = parser.getnsmanager(myxml);
            //figure out if metric or USIP (we have not found a reason to use this yet)
            parser.getunits(nsm, myxml);

            /* Begin Parsing the XML and reporting on it----------------------------------------------------------*/

            //make a reporting object
            DOEgbXMLPhase2Report report = new DOEgbXMLPhase2Report();

            /* Basic Uniqueness Constraints check-------------------------------------------------*/

            //Basic requirements check

            // Setup the results view for the log and web.
            log = "";
            TestResultPanel.Controls.Add(new LiteralControl("<div class='well-lg'><h3>Test Sections</h3><table class='table table-bordered'><tr class='info'><td>Test Section Name</td><td>Tolerances</td><td>Pass/Fail</td></tr>"));

            //first create a list of lists that is indexed identically to the drop down list the user selects
            TestDetail = new DOEgbXMLTestDetail();
            //then populate the list of lists.  All indexing is done "by hand" in InitializeTestResultStrings()
            TestDetail.InitializeTestResultStrings();                        //Set up the Global Pass/Fail criteria for the test case file
            TestCriteria = new DOEgbXMLTestCriteriaObject();
            TestCriteria.InitializeTestCriteriaWithTestName(TestToRun); // ("Test1");

            // Reports
            //ensure that all names of spaces are unique--------------------------------------------------------------------------------------------------------Unique_Space_ID_Test//
            report.testType = TestType.Unique_Space_ID_Test;
            report = DOEgbXML.gbXMLSpaces.UniqueSpaceIdTest2(myxml, nsm, report);
            ProcessReport(report, true);
            report.Clear();

            //ensure that all space boundary names are unique--------------------------------------------------------------------------------------------------Unique_Space_Boundary//
            XmlNodeList nodes = myxml.SelectNodes("/gbXMLv5:gbXML/gbXMLv5:Campus/gbXMLv5:Building/gbXMLv5:Space/gbXMLv5:SpaceBoundary", nsm);
            if (nodes.Count > 0)
            {
                spaceBoundsPresent = true;
                report.testType = TestType.Unique_Space_Boundary;
                report = DOEgbXML.gbXMLSpaces.UniqueSpaceBoundaryIdTest2(myxml, nsm, report);
                ProcessReport(report, true);
                report.Clear();
            }
            else
            {
                //needs to be included so the report can be processed
                report.testType = TestType.Unique_Space_Boundary;
                report.passOrFail = true;
                report.longMsg = "A test is usually performed here to ensure Space Boundaries have valid naming conventions.  This test was skipped (legally) because your file does not have space boundaries present.  Continuing to next test.";
                ProcessReport(report, true);
                report.Clear();
            }

            //Space Tests
            //make a simplified representation of the spaces
            List<DOEgbXML.gbXMLSpaces> spaces = DOEgbXML.gbXMLSpaces.getSimpleSpaces(myxml, nsm);

            //4-check for self-intersecting polygons
            //report = DOEgbXML.gbXMLSpaces.SpaceSurfacesSelfIntersectionTest(spaces, report);
            //report.Clear();

            //check that all polyloops are in a counterclockwise direction-----------------------------------------------------------------------------------------Space_Surfaces_CC//
            report = DOEgbXML.gbXMLSpaces.SpaceSurfacesCCTest2(spaces, report);
            report.testType = TestType.Space_Surfaces_CC;
            ProcessReport(report, true);
            report.Clear();

            //check for non-planar objects for all Spaces' polyloops-------------------------------------------------------------------------------------------Space_Surfaces_Planar//
            report.coordtol = DOEgbXMLBasics.Tolerances.VectorAngleTolerance;
            report = DOEgbXML.gbXMLSpaces.SpaceSurfacesPlanarTest(spaces, report);
            report.testType = TestType.Space_Surfaces_Planar;
            ProcessReport(report, true);
            report.Clear();

            //valid space enclosure?---------------------------------------------------------------------------------------------------------------------------Check_Space_Enclosure//
            report.tolerance = 0.0001;
            //when we are comparing angles in this function, we are testing the angle between dot products
            report.vectorangletol = DOEgbXMLBasics.Tolerances.dotproducttol;
            report.lengthtol = DOEgbXMLBasics.Tolerances.lengthTolerance;
            //toler
            report.coordtol = DOEgbXMLBasics.Tolerances.coordToleranceIP;
            report = Validator.CheckSpaceEnclosureSG(spaces, report);
            report.testType = TestType.Check_Space_Enclosure;
            ProcessReport(report, true);
            report.Clear();

            /* Surface tests----------------------------------------------------------------------------------*/
            /* Basic Requirements ----------------------------------------------------------------------------*/

            //Are there at least 4 surface definitions?  (see the surface requirements at the campus node)-------------------------------------------------------At_Least_4_Surfaces//
            report.testType = TestType.At_Least_4_Surfaces;
            report = SurfaceDefinitions.AtLeast4Surfaces(myxml, nsm, report);
            ProcessReport(report, true);
            report.Clear();

            //Does the AdjacentSpaceId not exceed the max number allowable?-----------------------------------------------------------------------------------------Two_Adj_Space_Id//
            //this needs to be updated!
            report.testType = TestType.Two_Adj_Space_Id;
            report = SurfaceDefinitions.AtMost2SpaceAdjId(myxml, nsm, report);
            ProcessReport(report, true);
            report.Clear();

            //Are all required elements and attributes in place?---------------------------------------------------------------------------------------------Required_Surface_Fields//
            //report.testType = TestType.Required_Surface_Fields;
            //report = SurfaceDefinitions.RequiredSurfaceFields(myxml, nsm, report);
            //ProcessReport(report, true);
            //report.Clear();

            //ensure that all names of surfaces are unique------------------------------------------------------------------------------------------------------Surface_ID_Uniqueness//
            report.testType = TestType.Surface_ID_Uniqueness;
            report = DOEgbXML.SurfaceDefinitions.SurfaceIDUniquenessTest(myxml, nsm, report);
            ProcessReport(report, true);
            report.Clear();

            //now grab all the surfaceIds and make them available------------------------------------------------------------------------------------------------Surface_Adj_Id_Match//
            List<string> spaceIds = new List<string>();
            foreach (gbXMLSpaces s in spaces)
            {
                spaceIds.Add(s.id);
            }

            List<SurfaceDefinitions> surfaces = DOEgbXML.XMLParser.MakeSurfaceList(myxml, nsm);
            //make sure the surface Adjacent space Id names match only the the space Ids gathered above.  The adjacent space Ids can't have their own special values
            report.testType = TestType.Surface_Adj_Id_Match;
            report = DOEgbXML.SurfaceDefinitions.SurfaceAdjSpaceIdTest(spaceIds, surfaces, report);
            ProcessReport(report, true);
            report.Clear();

            //Surface_ID_SB_Match------------------------------------------------------------------------------------------------------------------------------Surface_ID_SB_Match//
            if (spaceBoundsPresent)
            {
                report.tolerance = DOEgbXMLBasics.Tolerances.coordToleranceIP;
                report.testType = TestType.Surface_ID_SB_Match;
                report = SurfaceDefinitions.SurfaceMatchesSpaceBoundary(myxml, nsm, report);
                ProcessReport(report, true);
                report.Clear();
            }
            else
            {
                report.testType = TestType.Surface_ID_SB_Match;
                report.passOrFail = true;
                report.longMsg = "A test is usually performed here to ensure Space Boundaries and Surfaces share the same ID.  This test was skipped (legally) because your file does not have space boundaries present.  Continuing to next test.";
                ProcessReport(report, true);
                report.Clear();
            }

            //Does the polyloop right hand rule vector form the proper azimuth and tilt? (with and without a CADModelAzimuth)----------------------------------Surface_Tilt_Az_Check//
            report.tolerance = DOEgbXMLBasics.Tolerances.VectorAngleTolerance;
            report.vectorangletol = DOEgbXMLBasics.Tolerances.VectorAngleTolerance;
            report.testType = TestType.Surface_Tilt_Az_Check;
            report = SurfaceDefinitions.SurfaceTiltAndAzCheck(myxml, nsm, report);
            ProcessReport(report, true);
            report.Clear();

            //planar surface test-------------------------------------------------------------------------------------------------------------------------------Surface_Planar_Test//
            report.vectorangletol = DOEgbXMLBasics.Tolerances.VectorAngleTolerance;
            report = SurfaceDefinitions.TestSurfacePlanarTest(surfaces, report);
            report.testType = TestType.Surface_Planar_Test;
            ProcessReport(report, true);
            report.Clear();

            //I must take the surfaces, group them, and rearrange any interior surfaces' coordinates that should be pointed the opposite way
            string searchpath = "/gbXMLv5:gbXML/gbXMLv5:Campus/gbXMLv5:Building/gbXMLv5:Space";
            List<string> spaceids = DOEgbXML.gbXMLSpaces.getSpaceIds(myxml, nsm, searchpath);
            Dictionary<string, List<SurfaceDefinitions>> enclosure = new Dictionary<string, List<SurfaceDefinitions>>();
            foreach (string id in spaceids)
            {
                //find all surfaces with this adjacent space id, get their polyloops, and then match their polyloops
                List<SurfaceDefinitions> surflist = new List<SurfaceDefinitions>();

                foreach (SurfaceDefinitions surf in surfaces)
                {
                    foreach (var adj in surf.AdjSpaceId)
                    {
                        if (adj == id)
                        {
                            surflist.Add(surf);
                            //don't want to add surfaces twice (slab on grade)
                            break;
                        }
                    }
                }
                enclosure[id] = surflist;
            }

            //counter clockwise winding test-------------------------------------------------------------------------------------------------------------------------Surface_CC_Test//
            report.testType = TestType.Surface_CC_Test;
            report = SurfaceDefinitions.SurfaceCCTest(enclosure, report);
            ProcessReport(report, true);
            report.Clear();

            //self intersecting polygon test
            //report = SurfaceDefinitions.SurfaceSelfIntersectionTest(surfaces, report);
            //report.Clear();

            //Is the Lower Left Corner properly defined?

            //surface enclosure tests------------------------------------------------------------------------------------------------------------------------Check_Surface_Enclosure//
            report.tolerance = 0.0001;
            report.vectorangletol = DOEgbXMLBasics.Tolerances.dotproducttol;
            report.lengthtol = DOEgbXMLBasics.Tolerances.lengthTolerance;
            report.coordtol = .01;
            report.testType = TestType.Check_Surface_Enclosure;
            report = Validator.CheckSurfaceEnclosure(enclosure, report);
            ProcessReport(report, true);
            report.Clear();

            TestResultPanel.Controls.Add(new LiteralControl("</table></div>"));
            CreateSummaryTable();
        }
        public static DOEgbXMLPhase2Report RequiredSurfaceFields(XmlDocument gbXMLDoc, XmlNamespaceManager gbXMLnsm, DOEgbXMLPhase2Report report)
        {
            //pass or fail attribute should always be set to false
            //Feb 6 2014 - gbXML XSD version 5.11
            //this test ensures that each surface element has the required attributes and elements, and that all enumerations are properly declared
            report.testSummary = "This test ensures that all required fields are present in every Surface element of your gbXML file.";
            
            try
            {
                XmlNodeList nodes = gbXMLDoc.SelectNodes("/gbXMLv5:gbXML/gbXMLv5:Campus/gbXMLv5:Surface", gbXMLnsm);
                foreach (XmlNode node in nodes)
                {

                    List<string> ml = new List<string>();
                    //surfaceID for reporting
                    string surfaceId = "";
                    if (node.Attributes.GetNamedItem("id") != null)
                    {
                        surfaceId = node.Attributes.GetNamedItem("id").Value;
                        ml.Add("PASS: "******" has the required id attribute.");
                    }
                    else
                    {
                        ml.Add("FAIL: " + surfaceId + " is missing the required id attribute.");
                    }

                    if(node.Attributes.GetNamedItem("surfaceType") != null)
                    {
                        ml.Add("PASS: "******" has the required surfaceType attribute.");
                        string val = node.Attributes.GetNamedItem("surfaceType").Value;
                        if (val == "InteriorWall") { ml.Add("PASS: Valid surfaceType enum:" + val); }
                        else if (val == "ExteriorWall") { ml.Add("PASS: Valid surfaceType enum:" + val); }
                        else if (val == "Roof") { ml.Add("PASS: Valid surfaceType enum:" + val); }
                        else if (val == "InteriorFloor") { ml.Add("PASS: Valid surfaceType enum:" + val); }
                        else if (val == "Shade") { ml.Add("PASS: Valid surfaceType enum:" + val); }
                        else if (val == "UndergroundWall") { ml.Add("PASS: Valid surfaceType enum:" + val); }
                        else if (val == "UndergroundSlab") { ml.Add("PASS: Valid surfaceType enum:" + val); }
                        else if (val == "Ceiling") { ml.Add("PASS: Valid surfaceType enum:" + val); }
                        else if (val == "Air") { ml.Add("PASS: Valid surfaceType enum:" + val); }
                        else if (val == "UndergroundCeiling") { ml.Add("PASS: Valid surfaceType enum:" + val); }
                        else if (val == "RaisedFloor") { ml.Add("PASS: Valid surfaceType enum:" + val); }
                        else if (val == "SlabOnGrade") { ml.Add("PASS: Valid surfaceType enum:" + val); }
                        else if (val == "FreeStandingColumn") { ml.Add("PASS: Valid surfaceType enum:" + val); }
                        else if (val == "EmbeddedColumn") { ml.Add("PASS: Valid surfaceType enum:" + val); }
                        else
                        {
                            ml.Add("FAIL: Invalid surfaceType enumeration:" + val);
                            report.longMsg = "TEST FAILED: For Surface with" +surfaceId+ " an invalid surfaceType enumeration has been declared.  Please review the latest XSD for valid enumerations.";
                            report.passOrFail = false;
                        }
                    }
                    else
                    {
                        ml.Add("FAIL: " + surfaceId + " is missing the required surfaceType attribute.");
                    }

                    XmlNodeList childnodes = node.ChildNodes;
                    foreach (XmlNode child in childnodes)
                    {
                        if (child.Name == "Name") { continue; }
                        if (child.Name == "AdjacentSpaceId") { continue; }
                        Dictionary<string, bool> surfReq = new Dictionary<string, bool>();
                        surfReq.Add("RectangularGeometry", false);
                        surfReq.Add("PlanarGeometry", false);

                        //find RectangularGeometry node (reqiured)
                        if (child["RectangularGeometry"] != null)
                        {
                            ml.Add("PASS: The required RectangularGeometry Element has been located.");

                            //is any of this really needed, doesn't the XSD validation already do this?
                            XmlNodeList rgchilds = child.ChildNodes;
                            Dictionary<string, bool> rgReq = new Dictionary<string, bool>();
                            rgReq.Add("Azimuth", false);
                            rgReq.Add("CartesianPoint", false);
                            rgReq.Add("Tilt", false);
                            rgReq.Add("Height", false);
                            rgReq.Add("Width", false);
                            //rgReq.Add("PolyLoop", false);

                            foreach (XmlNode rgchild in rgchilds)
                            {
                                string elName = rgchild.Name;
                                if (rgchild["Azimuth"] != null)
                                {
                                    ml.Add("PASS: Required Azimuth Element located.");
                                    rgReq["Azimuth"] = true;
                                }
                                else
                                {
                                    ml.Add("FAIL: Required Azimuth Element not found.");
                                    rgReq["Azimuth"] = false;
                                }

                                if (rgchild["CartesianPoint"] != null)
                                {
                                    ml.Add("PASS: Required Cartesian Element located.");
                                    rgReq["CartesianPoint"] = true;
                                }
                                else
                                {
                                    ml.Add("FAIL: Required Cartesian Element not found.");
                                    rgReq["CartesianPoint"] = false;
                                }

                                if (rgchild["Tilt"] != null)
                                {
                                    ml.Add("PASS: Required Tilt Element located.");
                                    rgReq["Tilt"] = true;
                                }
                                else
                                {
                                    ml.Add("FAIL: Required Tilt Element not found.");
                                    rgReq["Tilt"] = false;
                                }

                                if (rgchild["Height"] != null)
                                {
                                    ml.Add("PASS: Required Height Element located.");
                                    rgReq["Height"] = true;

                                }
                                else
                                {
                                    ml.Add("FAIL: Required Height Element not found.");
                                    rgReq["Height"] = false;
                                }

                                if (rgchild["Width"] != null)
                                {
                                    ml.Add("PASS: Required Width Element located.");
                                    rgReq["Width"] = true;
                                }
                                else
                                {
                                    ml.Add("FAIL: Required Width Element not found.");
                                    rgReq["Width"] = false;
                                }
                                if (rgchild["PolyLoop"] != null)
                                {
                                    //this is optional, not sure if we want to report anything here
                                }

                            }

                            if (rgReq.ContainsValue(false))
                            {
                                //failure
                                report.longMsg = "FAIL:  Not all required Rectangular Geometry elements are present.";
                                report.passOrFail = false;
                                return report;
                            }
                            else
                            {
                                ml.Add("PASS:  Rectangular Geometry element has all required elements.");
                                surfReq["RectangularGeometry"] = true;
                            }
                        }
                        //find PlanarGeometry node (required)
                        else
                        {
                            ml.Add("FAIL: The required RectangularGeometry Element cannot be located.");
                        }
                        if (child["PlanarGeometry"] != null)
                        {
                            ml.Add("PASS: The required PlanarGeometry Element has been successfully located.");
                            //April 14, 2014
                            //We have opted not to check the quality of the planar geometry because this is done elsewhere
                        }
                        else
                        {
                            ml.Add("FAIL: The required PlanarGeometry Element has cannot be located.");
                        }
                    }
                    report.MessageList[surfaceId] = ml;
                }
            }
            catch (Exception e)
            {
                report.longMsg = ("SORRY, we have run into an unexpected issue:" + e.ToString());
                report.passOrFail = false;
                return report;
            }
            return report;

        }
        public static DOEgbXMLPhase2Report AtLeast4Surfaces(XmlDocument gbXMLDoc, XmlNamespaceManager gbXMLnsm, DOEgbXMLPhase2Report report)
        {
            //pass or fail attribute should always be set to false
            report.testSummary = "This test ensures that the minimum number of surfaces have been declared in the gbXML file.";
            try
            {
                
                XmlNodeList nodes = gbXMLDoc.SelectNodes("/gbXMLv5:gbXML/gbXMLv5:Campus/gbXMLv5:Surface", gbXMLnsm);
                int count = nodes.Count;
                if (count >= 4)
                {
                    
                    report.longMsg = "TEST PASSED: This gbXML file has the minimum required number of surfaces (4, i.e - a tetrahedra).";
                    report.passOrFail = true;
                }
                else
                {
                    
                    report.longMsg = "TEST FAILED: This gbXML file DOES NOT have the minimum required number of surfaces (4, i.e - a tetrahedra).";
                    report.passOrFail = false;
                }

            }
            catch (Exception e)
            {
                report.longMsg = ("SORRY, we have run into an unexpected issue:" + e.ToString());
                report.passOrFail = false;
                return report;
            }
            return report;
        }
        public static DOEgbXMLPhase2Report TestSurfacePlanarTest(List<SurfaceDefinitions> TestSurfaces, DOEgbXMLPhase2Report report)
        {
            //this summary is text that describes to a lay user what this test does, and how it works functionally.  The user should have some familiarity with the basic knowledge of gbXML 
            //added Feb 17 2014
            report.testSummary = "This test ensures that each Surface has coordinate descriptions that do not violate the principles of planarity.";
            report.TestPassedDict = new Dictionary<string, bool>();
            report.passOrFail = true;
            try
            {
                
                foreach (SurfaceDefinitions ts in TestSurfaces)
                {
                    List<string> ml = new List<string>();
                    ml.Add(ts.SurfaceId + " begin testing planarity of surface polygon definition.");
                    Dictionary<string, List<Vector.CartVect>> surfaceXProducts = new Dictionary<string, List<Vector.CartVect>>();
                    List<Vector.CartVect> xProducts = new List<Vector.CartVect>();
                    for (int i = 0; i < ts.PlCoords.Count - 2; i++)
                    {
                        //Get the Cross Product
                        VectorMath.Vector.CartVect v1 = VectorMath.Vector.CreateVector(ts.PlCoords[i], ts.PlCoords[i + 1]);
                        VectorMath.Vector.CartVect v2 = VectorMath.Vector.CreateVector(ts.PlCoords[i + 1], ts.PlCoords[i + 2]);
                        Vector.CartVect xProd = Vector.CrossProduct(v1, v2);
                        xProd = Vector.UnitVector(xProd);
                        xProducts.Add(xProd);
                    }
                    surfaceXProducts.Add(ts.SurfaceId, xProducts);
                    List<bool> xpbool = new List<bool>();
                    for (int j = 0; j < xProducts.Count - 1; j++)
                    {
                        //parallel and anti parallel
                        if (xProducts[j].X == xProducts[j + 1].X && xProducts[j].Y == xProducts[j + 1].Y && xProducts[j].Z == xProducts[j + 1].Z)
                        {
                            xpbool.Add(true);
                            continue;
                        }
                        //anti-parallel
                        else if (xProducts[j].X == -1 * xProducts[j + 1].X && xProducts[j].Y == -1 * xProducts[j + 1].Y && xProducts[j].Z == -1 * xProducts[j + 1].Z)
                        {
                            xpbool.Add(true);
                            continue;
                        }
                        else if (Math.Abs(xProducts[j].X) - Math.Abs(xProducts[j + 1].X) < report.vectorangletol && Math.Abs(xProducts[j].Y) - Math.Abs(xProducts[j + 1].Y) < report.vectorangletol &&
                            Math.Abs(xProducts[j].Z) - Math.Abs(xProducts[j + 1].Z) < report.vectorangletol)
                        {
                            xpbool.Add(true);
                            continue;
                        }
                        else
                        {
                            
                            xpbool.Add(false);
                        }
                    }
                    if (xpbool.Contains(false))
                    {
                        report.TestPassedDict[ts.SurfaceId] = false;
                        ml.Add("FAIL:  Non-planar surface detected.  Coordinates for this surface do not appear to form a planar surface.");
                        report.passOrFail = false;
                    }
                    else
                    {
                        report.TestPassedDict[ts.SurfaceId] = true;
                        ml.Add("PASS: Coordinates for this surface form a perfectly planar surface.");
                    }
                    report.MessageList[ts.SurfaceId] = ml;
                }
            }
            catch (Exception e)
            {
                report.longMsg = ("SORRY, we have run into an unexpected issue:" + e.ToString());
                report.passOrFail = false;
                return report;
            }

            //if we have made it this far presumably we can test to see if everything is in fact planar
            if (report.TestPassedDict.ContainsValue(false))
            {
                report.longMsg = "FAIL:  Non planar surfaces have been detected.  Please contact your CAD vendor to correct.";
                report.passOrFail = false;
            }
            else
            {
                report.longMsg = "PASS:  All surfaces are planar or nearly planar within allowable tolerances.";
                report.passOrFail = true;
            }
            return report;
        }
Esempio n. 10
0
        public static DOEgbXMLPhase2Report CheckSpaceEnclosureSB(List<gbXMLSpaces> spaces, DOEgbXMLPhase2Report report)
        {
            try
            {
                report.passOrFail = true;
                foreach (gbXMLSpaces space in spaces)
                {
                    List<string> ml = new List<string>();
                    if (space.spacebounds.Count() > 0)
                    {

                        ml.Add("Testing begins for Space Boundary water tightness.");
                        Dictionary<int, Vector.EdgeFamily> uniqueedges = new Dictionary<int, Vector.EdgeFamily>();
                        ml.Add(space.id + ": has SpaceBoundary representation.");
                        ml.Add(space.id + ": START checking space boundary enclosure.");
                        foreach (DOEgbXML.gbXMLSpaces.SpaceBoundary sb in space.spacebounds)
                        {
                            uniqueedges = Vector.GetEdgeFamilies(sb.surfaceIdRef, uniqueedges, sb.sbplane.pl.plcoords, .0001, .0001);
                        }
                        ml.Add("Gathered space boundary edges and neighboring relationships.");
                        //see how well enclosure is formed
                        ml.Add("Validating space boundary edge alignment with one another - water tightness check.");

                        //new function added April 11, 2014
                        report = MatchEdges(uniqueedges, ml, report, space.id);

                    }
                    else
                    {
                        ml.Add(space.id + ": Has no Valid Space Boundaries.  This is not an error.  The validator will continue searching for other enclosed boundaries.");
                    }
                    report.MessageList[space.id] = ml;
                }
            }
            catch (Exception e)
            {
                report.longMsg = ("SORRY, we have run into an unexpected issue:" + e.ToString());
                report.passOrFail = false;
                return report;
            }
            return report;
        }
Esempio n. 11
0
        public static DOEgbXMLPhase2Report UniqueSpaceBoundaryIdTest2(XmlDocument gbXMLDoc, XmlNamespaceManager gbXMLnsm, DOEgbXMLPhase2Report report)
        {
            //this summary is text that describes to a lay user what this test does, and how it works functionally.  The user should have some familiarity with the basic knowledge of gbXML 
            //added Feb 13 2013
            report.testSummary = "This test reviews the values if all SpaceBoundary surfaceIdRef attributes, and ensures each Space has at most one unique Space Boundary id.  ";
            report.testSummary += "If there are any duplicate SpaceBoundary surfaceIdRef values, then this test will fail.  If there are duplicates, the remainder of the tests in the testbed are not executed and the test will end here until the test file is properly updated.  Each SpaceBoundary surfaceIdRef should be unique in valid gbXML.  If this test has failed, you may take the following actions.";
            report.testSummary += "  Repair the names of the SpaceBoundary id so they are all unique.";
            
            report.MessageList = new Dictionary<string,List<string>>();
            report.TestPassedDict = new Dictionary<string, bool>();
            report.standResult = new List<string>();
            report.testResult = new List<string>();
            report.idList = new List<string>();
            // report.testType = "UniqueId";
            report.passOrFail = true;
            try
            {
                //get spaces, then get the Space Boundaries for each Space
                XmlNodeList spaces = gbXMLDoc.SelectNodes("/gbXMLv5:gbXML/gbXMLv5:Campus/gbXMLv5:Building/gbXMLv5:Space", gbXMLnsm);
                foreach (XmlNode space in spaces)
                {
                    string spaceId;
                    List<string> returnlist = new List<string>();
                    spaceId = space.Attributes[0].Value.ToString();
                    List<string> sbIdList = new List<string>();
                    XmlNodeList spacechilds = space.ChildNodes;
                    foreach (XmlNode child in spacechilds)
                    {
                        
                        if (child.Name == "SpaceBoundary")
                        {
                            string spaceboundaryId;
                            spaceboundaryId = child.Attributes[0].Value.ToString();
                            
                            if (sbIdList.Contains(spaceboundaryId))
                            {
                                //not unique
                                returnlist.Add("SpaceBoundary surfaceIdRef: " + spaceboundaryId + " is not unique.");
                                report.longMsg = "This test for unique SpaceBoundary surfaceIdRef attributes has failed.  All SpaceBoundary surfaceIdRef for a given Space must be unique.";
                                report.passOrFail = false;
                                
                            }
                            sbIdList.Add(spaceboundaryId);
                            returnlist.Add("SpaceBoundary surfaceIdRef: " + spaceboundaryId + " is unique.");
                        }
                    }
                    report.MessageList[spaceId] = returnlist;
                }
                if (report.passOrFail)
                {
                    report.longMsg = "TEST PASSED: For every Space in the gbXML file, each SpaceBoundary surfaceIdRefs attributes have unique values.";
                    report.passOrFail = true;
                }
                else
                {
                    report.longMsg = "TEST FAILED: SpaceBoundary surfaceIdRefs attributes are not all unique.";
                    report.passOrFail = false;
                }

            }
            catch (Exception e)
            {
                report.longMsg = e.ToString();
                List<string> l = new List<string>();

                l.Add("This test unexpectedly failed.");
                report.MessageList["ERROR"] = l;
                report.passOrFail = false;
                return report;
            }
            return report;
        }
Esempio n. 12
0
        public static DOEgbXMLPhase2Report UniqueSpaceIdTest2(XmlDocument gbXMLDoc, XmlNamespaceManager gbXMLnsm, DOEgbXMLPhase2Report report)
        {
            //this summary is text that describes to a lay user what this test does, and how it works functionally.  The user should have some familiarity with the basic knowledge of gbXML 
            //added Feb 13 2013
            report.testSummary = "This test reviews the values if all Space id attributes, and ensures that they are all unique.  ";
            report.testSummary += "If there are any duplicate Space id values, then this test will fail.  If there are duplicates, the remainder of the tests in the testbed are not executed and the test will end here until the test file is properly updated.  Each Space id should be unique in valid gbXML.  If this test has failed, you may take the following actions.";
            report.testSummary += "  Correct the names of the Space id attribute so they are all unique.";

            report.MessageList = new Dictionary<string,List<string>>();
            report.TestPassedDict = new Dictionary<string, bool>();
            List<string> spaceIdList = new List<string>();
            report.standResult = new List<string>();
            report.testResult = new List<string>();
            report.idList = new List<string>();
            // report.testType = "UniqueId";
            report.passOrFail = true;
            try
            {
                XmlNodeList nodes = gbXMLDoc.SelectNodes("/gbXMLv5:gbXML/gbXMLv5:Campus/gbXMLv5:Building/gbXMLv5:Space", gbXMLnsm);
                foreach (XmlNode node in nodes)
                {
                    //looks to see if the spaceId is already included in the list of space IDs being generated
                    string spaceId;
                    spaceId = node.Attributes[0].Value.ToString();
                    List<string> reportlist = new List<string>();
                    if (spaceIdList.Contains(spaceId))
                    {
                        //not unique
                        reportlist.Add("is not unique.");
                        report.longMsg = "This test for unique space id attributes has failed.  All Space Id attributes should be unique.";
                        report.passOrFail = false;
                        report.MessageList[spaceId] = reportlist;
                    }
                    spaceIdList.Add(spaceId);
                    reportlist.Add("Space Id is unique.");
                    report.MessageList[spaceId] = reportlist;
                }
                if (report.passOrFail)
                {
                    report.longMsg = "TEST PASSED: All spaces have unique id attributes.";
                    report.passOrFail = true;
                }
                else
                {
                    report.longMsg = "TEST FAILED: All spaces do not have unique Ids.";
                }

            }
            catch (Exception e)
            {
                List<string> l = new List<string>();
                report.longMsg = e.ToString();
                l.Add("This test unexpectedly failed.");
                report.MessageList["ERROR: "] = l;
                report.passOrFail = false;
                return report;
            }
            return report;
        }
Esempio n. 13
0
        public static DOEgbXMLPhase2Report SpaceSurfacesCCTest2(List<gbXMLSpaces> spaces, DOEgbXMLPhase2Report report)
        {
            //this summary is text that describes to a lay user what this test does, and how it works functionally.  The user should have some familiarity with the basic knowledge of gbXML 
            //added Feb 17 2014
            report.testSummary = "This test ensures that all surface coordinates are listed in a counterclockwise order.  This is a requirement of all gbXML PolyLoop definitions.";
            report.testSummary += "  It is an important test because it ensures that all surface normals are pointing in the right direction (away from the center of each room).";
            report.testSummary += "  This helps to ensure that each surface is pointed in the correct direction, so that solar gains can properly be taken into account.";
            report.MessageList = new Dictionary<string,List<string>>();
            report.TestPassedDict = new Dictionary<string, bool>();
            report.passOrFail = true;
            try
            {
                int spacecount = 0;
                foreach (DOEgbXML.gbXMLSpaces space in spaces)
                {
                    List<string> retlist = new List<string>();
                    bool spacepassorfail = true;
                    if (space.sg.cs.ploops.Count() > 0)
                    {
                        string spaceid = space.id + " has ShellGeometry PolyLoops.  Conducting tests of ShellGeometry PolyLoops";
                        report.TestPassedDict[spaceid] = true;
                        List<List<Vector.MemorySafe_CartCoord>> cc = new List<List<Vector.MemorySafe_CartCoord>>();
                        for (int sgsurfcount = 0; sgsurfcount < space.sg.cs.ploops.Count; sgsurfcount++)
                        {
                            PolyLoop pl = space.sg.cs.ploops[sgsurfcount];
                            List<Vector.MemorySafe_CartCoord> c = pl.plcoords;
                            cc.Add(c);

                        }
                        Vector.MemorySafe_CartCoord centroid = Vector.FindVolumetricCentroid(cc);
                        Dictionary<string, bool> res = Vector.SurfacesCCWound(centroid, cc, spacecount);
                        foreach (KeyValuePair<string, bool> kp in res)
                        {
                            string pattern = @"\d*#";
                            string repl = "";
                            Regex rx = new Regex(pattern);
                            string surfacename = rx.Replace(kp.Key, repl);
                            if (kp.Value == true)
                            {
                                if (surfacename.Length > 0)
                                {
                                    retlist.Add("PASS: ShellGeometry surface number: " + surfacename + " is wound in a counterclockwise order.");
                                }
                                else
                                {
                                    retlist.Add("PASS: ShellGeometry surface number: " + kp.Key + " is wound in a counterclockwise order.");
                                }
                                
                            }
                            else
                            {
                                if (surfacename.Length > 0)
                                {
                                    retlist.Add("FAIL: ShellGeometry surface number: " + surfacename + " is wound in a clockwise order.");
                                }
                                else
                                {
                                    retlist.Add("FAIL: ShellGeometry surface number: " + (kp.Key) + " is wound in a clockwise order.");
                                    spacepassorfail = false;
                                }
                                
                            }
                        }

                    }
                    else
                    {
                        string spaceid = space.id + " does not have ShellGeometry PolyLoops.  Conducting tests of ShellGeometry PolyLoops";
                        report.TestPassedDict[spaceid] = false;
                    }

                    if (space.spacebounds.Count() > 0)
                    {
                        string spaceid = space.id + " has SpaceBoundary PolyLoops.  Conducting tests of SpaceBoundary PolyLoops";
                        report.TestPassedDict[spaceid] = true;

                        Dictionary<string, List<Vector.MemorySafe_CartCoord>> sbcc = new Dictionary<string, List<Vector.MemorySafe_CartCoord>>();
                        for (int sbsurfcount = 0; sbsurfcount < space.spacebounds.Count(); sbsurfcount++)
                        {
                            PolyLoop sbpl = space.spacebounds[sbsurfcount].sbplane.pl;
                            List<Vector.MemorySafe_CartCoord> sbc = sbpl.plcoords;
                            sbcc[space.spacebounds[sbsurfcount].surfaceIdRef] = (sbc);

                        }
                        Vector.MemorySafe_CartCoord sbcentroid = Vector.FindVolumetricCentroid(sbcc);
                        Dictionary<string, bool> sbres = Vector.NamedSurfacesCCWound(sbcentroid, sbcc,spacecount, true);
                        foreach (KeyValuePair<string, bool> sbkp in sbres)
                        {
                            string pattern = @"\d*#";
                            string repl = "";
                            Regex rx = new Regex(pattern);
                            string surfacename = rx.Replace(sbkp.Key, repl);
                            if (sbkp.Value == true)
                            {
                                if (surfacename.Length > 0)
                                {
                                    retlist.Add("PASS: SurfaceBoundary with id: " + surfacename + " is wound in a counterclockwise order.");
                                }
                                else
                                {
                                    retlist.Add("PASS: SurfaceBoundary with id: " + sbkp.Key + " is wound in a counterclockwise order.");
                                }
                                
                            }
                            else
                            {
                                if (surfacename.Length > 0)
                                {
                                    retlist.Add("FAIL: SurfaceBoundary with id: " + surfacename + " is not wound in a clockwise order.");
                                }
                                else
                                {
                                    retlist.Add("FAIL: SurfaceBoundary with id: " + sbkp.Key + " is not wound in a clockwise order.");
                                } 
                                spacepassorfail = false;
                            }
                        }
                    }
                    else
                    {
                        string spaceid = space.id + " does not have SpaceBoundary PolyLoops.  Conducting tests of SpaceBoundary PolyLoops";
                        report.TestPassedDict[spaceid] = false;
                    }
                    //if (spacepassorfail) { report.TestPassedDict.Add(space.id+ " Passes all CounterClockwise Winding Tests", true); }
                    //else { report.TestPassedDict.Add(space.id+ "Fails all CounterClockwise Winding Tests", false); }
                    report.MessageList[space.id] = retlist;
                    spacecount++;
                }
            }
            catch (Exception e)
            {
                report.longMsg = e.ToString();
                List<string> l = new List<string>();
                l.Add("This test failed unexpectedly.");
                report.MessageList["ERROR"] = l;
                report.passOrFail = false;
                return report;
            }
            if (report.passOrFail==false)
            {
                report.longMsg = "TEST FAILED:  This test found errors in the geometry when testing the winding order of the Space elements surfaces.  All surfaces are not facing in the proper direction";
                
            }
            else
            {
                report.longMsg = "TEST PASSED : This test did not find any errors in the geometry when testing the winding order of the Space elements surfaces.";
                
            }
            return report;
        }
Esempio n. 14
0
        public static DOEgbXMLPhase2Report SpaceSurfacesPlanarTest(List<gbXMLSpaces> Spaces, DOEgbXMLPhase2Report report)
        {
            report.testSummary = "Testing if the PolyLoops of SpaceBoundary and ShellGeometry elements (if they have been defined) are planar or very nearly planar.";
            report.testSummary += "  This test is important because many energy modeling and load calculation tools do not have the ability to simplify a curved surface into ";
            report.testSummary += "a set of planar surfaces.  Without real planar surfaces, some load and energy calculation tools cannot simulate heat transfer and solar";
            report.testSummary += "  penetration properly.  This test ensures that all surfaces that are defined by the PolyLoop element are in fact planar.";
            
            //ensure that each set of RHR tests result in parallel or anti-parallel resultant vectors, or else fail the test
            try
            {
                foreach (gbXMLSpaces s in Spaces)
                {
                    List<string> ml = new List<string>();
                    List<bool> pf = new List<bool>();
                    //by default, this always starts out true
                    bool spacepassorfail = true;
                    
                    //test shell geometry's closed shell polyloop planarity
                    if (s.sg.cs.ploops.Count() > 0)
                    {
                        string spaceid = s.id + " has ShellGeometry PolyLoops.  Conducting tests of ShellGeometry PolyLoops";
                        report.TestPassedDict[s.id] = true;
                        var ploops = s.sg.cs.ploops;
                        Dictionary<string, List<Vector.CartVect>> surfaceXProducts = new Dictionary<string, List<Vector.CartVect>>();

                        int plcount = 1;

                        foreach (var pl in ploops)
                        {
                            List<Vector.CartVect> xProducts = new List<Vector.CartVect>();
                            for (int i = 0; i < pl.plcoords.Count() - 2; i++)
                            {
                                //Get the Cross Product
                                VectorMath.Vector.CartVect v1 = VectorMath.Vector.CreateVector(pl.plcoords[i], pl.plcoords[i + 1]);
                                VectorMath.Vector.CartVect v2 = VectorMath.Vector.CreateVector(pl.plcoords[i + 1], pl.plcoords[i + 2]);
                                Vector.CartVect xProd = Vector.CrossProduct(v1, v2);
                                xProd = Vector.UnitVector(xProd);
                                xProducts.Add(xProd);
                            }
                            //give the polyloops some identifier, since they technically don't contain one
                            string ploopname = "shellgeometry-" + plcount.ToString();
                            surfaceXProducts.Add(ploopname, xProducts);
                            for (int j = 0; j < xProducts.Count - 1; j++)
                            {
                                //parallel and anti parallel
                                if (xProducts[j].X == xProducts[j + 1].X && xProducts[j].Y == xProducts[j + 1].Y && xProducts[j].Z == xProducts[j + 1].Z)
                                {
                                    ml.Add(ploopname+": Coordinates for this surface form a perfectly planar surface.");
                                    pf.Add(true);
                                    continue;
                                }
                                //anti-parallel
                                else if (xProducts[j].X == -1 * xProducts[j + 1].X && xProducts[j].Y == -1 * xProducts[j + 1].Y && xProducts[j].Z == -1 * xProducts[j + 1].Z)
                                {
                                    ml.Add(ploopname + ": Coordinates for this surface form a perfectly planar surface.");
                                    pf.Add(true);
                                    continue;
                                }
                                //I defined these tolerances myself.  Could this be done better?
                                else if (Math.Abs(xProducts[j].X) - Math.Abs(xProducts[j + 1].X) < report.tolerance && Math.Abs(xProducts[j].Y) - Math.Abs(xProducts[j + 1].Y) < report.tolerance &&
                                    Math.Abs(xProducts[j].Z) - Math.Abs(xProducts[j + 1].Z) < report.tolerance)
                                {
                                    ml.Add(ploopname + ": Coordinates for this surface form a nearly planar surface that is within allowable tolerances.");
                                    pf.Add(true);
                                    continue;
                                }
                                else
                                {
                                    ml.Add(ploopname+": Coordinates for this surface do not appear to form a planar surface.");
                                    pf.Add(false);
                                    spacepassorfail = false;
                                }
                            }
                            //next polyloop please
                            plcount++;
                        }
                    }
                    else
                    {
                        string spaceid = s.id + "has no Shell Geometry PolyLoops to test for planarity.  Conducting tests of ShellGeometry PolyLoops";
                        report.TestPassedDict[spaceid] = false;
                    }

                    if (s.spacebounds.Count() > 0)
                    {
                        string spaceid = s.id + "has SpaceBoundary PolyLoops.  Conducting tests of SpaceBoundary PolyLoops";
                        

                        //test the space boundary planarity
                        var sbs = s.spacebounds;
                        Dictionary<string, List<Vector.CartVect>> sbXProducts = new Dictionary<string, List<Vector.CartVect>>();
                        foreach (var sb in sbs)
                        {
                            var ploop = sb.sbplane.pl;
                            List<Vector.CartVect> xProducts = new List<Vector.CartVect>();
                            for (int i = 0; i < ploop.plcoords.Count() - 2; i++)
                            {
                                //Get the Cross Product
                                VectorMath.Vector.CartVect v1 = VectorMath.Vector.CreateVector(ploop.plcoords[i], ploop.plcoords[i + 1]);
                                VectorMath.Vector.CartVect v2 = VectorMath.Vector.CreateVector(ploop.plcoords[i + 1], ploop.plcoords[i + 2]);
                                Vector.CartVect xProd = Vector.CrossProduct(v1, v2);
                                xProd = Vector.UnitVector(xProd);
                                xProducts.Add(xProd);
                            }
                            //a name for the Space Boundary is already contained in the surfaceIdRef
                            sbXProducts.Add(sb.surfaceIdRef, xProducts);
                            for (int j = 0; j < xProducts.Count - 1; j++)
                            {
                                string sbid = sb.surfaceIdRef;
                                //parallel and anti parallel
                                if (xProducts[j].X == xProducts[j + 1].X && xProducts[j].Y == xProducts[j + 1].Y && xProducts[j].Z == xProducts[j + 1].Z)
                                {
                                    ml.Add(sbid+ ": Coordinates for this surface form a perfectly planar surface.");
                                    pf.Add(true);
                                    continue;
                                }
                                //anti-parallel
                                else if (xProducts[j].X == -1 * xProducts[j + 1].X && xProducts[j].Y == -1 * xProducts[j + 1].Y && xProducts[j].Z == -1 * xProducts[j + 1].Z)
                                {
                                    ml.Add(sbid+": Coordinates for this surface form a perfectly planar surface.");
                                    pf.Add(true);
                                    continue;
                                }
                                //I defined these tolerances myself.  Could this be done better?
                                else if (Math.Abs(xProducts[j].X) - Math.Abs(xProducts[j + 1].X) < report.tolerance && Math.Abs(xProducts[j].Y) - Math.Abs(xProducts[j + 1].Y) < report.tolerance &&
                                    Math.Abs(xProducts[j].Z) - Math.Abs(xProducts[j + 1].Z) < report.tolerance)
                                {
                                    ml.Add(sbid+ ": Coordinates for this surface form a nearly planar surface that is within allowable tolerances.");
                                    pf.Add(true);
                                    continue;
                                }
                                else
                                {
                                    ml.Add(sbid+ ": NON PLANAR SURFACE DETECTED:  Coordinates for this surface do not appear to form a planar surface.");
                                    pf.Add(false);
                                    spacepassorfail = false;
                                }
                            }


                        }

                    }
                    else
                    {
                        string spaceid = s.id + "does not have SpaceBoundary PolyLoops.  Conducting tests of SpaceBoundaryPolyLoops";
                        report.TestPassedDict[spaceid] = false;
                    }
                    

                    if (pf.Contains(false))
                    {
                        string rep = s.id +  ": FAIL";
                        report.MessageList[rep] = ml;
                        report.passOrFail = false;
                    }
                    else
                    {
                        string rep = s.id + ": TRUE";
                        report.MessageList[rep] = ml;
                    }
                }


            }
            catch (Exception e)
            {
                //perhaps I want to log this for programmers to look at when they want
            }
            if (report.passOrFail == false)
            {
                report.longMsg = "TEST FAILED: Non-planar PolyLoop descriptions for ShellGeometry and SpaceBoundary elements have been detected!";
            }
            else
            {
                report.longMsg = "TEST PASSED: All of the PolyLoop descriptions for ShellGeometry and SpaceBoundary elements describe a planar or nearly planar surface.";
            }
            return report;

        }
        public static DOEgbXMLPhase2Report SurfaceTiltAndAzCheck(XmlDocument gbXMLDoc, XmlNamespaceManager gbXMLnsm, DOEgbXMLPhase2Report report)
        {
            //pass or fail attribute should always be set to false
            //Feb 6 2014 - gbXML XSD version 5.11
            //this test ensures that each surface element has the required attributes and elements, and that all enumerations are properly declared
            report.testSummary = "This test checks the polygon geometry definition wrapped in each space, and ensures the tilt and azimuth definitions coincide.";
            try
            {
                List<SurfaceDefinitions> surfList = DOEgbXML.XMLParser.GetFileSurfaceDefs(gbXMLDoc, gbXMLnsm);

                foreach (SurfaceDefinitions surface in surfList)
                {
                    bool tiltPassed = false;
                    bool azPassed = false;
                    //calculate azimuth and tilt, without considering the CADModelAzimuth
                    Vector.MemorySafe_CartVect normal = surface.PlRHRVector;
                    double calculatedTilt = DOEgbXMLBasics.FindTilt(normal);
                    double calculatedAzimuth = DOEgbXMLBasics.FindAzimuth(normal);
                    List<string> ml = new List<string>();
                    ml.Add(surface.SurfaceId + " start testing tilt and azimuth matchs to polygon's PolyLoop definition in Rectangular Geometry.");
                    if (calculatedTilt == surface.Tilt)
                    {
                        //perfect
                        ml.Add("SUCCESS: Surface's planar geometry polyloop forms RHR with Tilt: " + calculatedTilt.ToString() + " that is identical to Surface's Tilt Element Text: " + surface.Tilt.ToString());
                        tiltPassed = true;
                    }
                    else if (Math.Abs(calculatedTilt - surface.Tilt) < report.vectorangletol)
                    {
                        //good
                        ml.Add("SUCCESS: Surface's planar geometry polyloop forms RHR with Tilt: " + calculatedTilt.ToString() + " that is within tolerance of the Surface's Tilt Element Text: " + surface.Tilt.ToString());
                        tiltPassed = true;
                    }
                    else
                    {
                        //bad
                        ml.Add("FAIL: Surface's planar geometry polyloop forms RHR with Tilt: " + calculatedTilt.ToString() + " that is not within tolerance of Surface's Tilt Element Text: " + surface.Tilt.ToString());
                        
                        //we stop here, this is the best I can seem to do here for now.
                        continue;
                    }

                    if (calculatedAzimuth == surface.Azimuth)
                    {
                        ml.Add("SUCCESS: Surface's planar geometry polyloop forms RHR with Azimuth: " + calculatedAzimuth.ToString() + " that is identical to Surface's Azimuth Element Text: " + surface.Azimuth.ToString());
                        azPassed = true;
                    }
                    else if (Math.Abs(calculatedAzimuth - surface.Azimuth) < report.tolerance)
                    {
                        //good
                        ml.Add("SUCCESS: Surface's planar geometry polyloop forms RHR with Azimuth: " + calculatedAzimuth.ToString() + " that is within tolerance of the Surface's Tilt Element Text: " + surface.Azimuth.ToString());
                        azPassed = true;
                    }
                    else
                    {
                        //bad
                        ml.Add("FAIL: Surface's planar geometry polyloop forms RHR with Azimuth: " + calculatedAzimuth.ToString() + " that is not within tolerance of Surface's Azimuth Element Text: " + surface.Azimuth.ToString());
                        
                        //we stop here, this is the best I can seem to do here for now.
                        continue;
                    }
                    report.MessageList[surface.SurfaceId] = ml;
                    if (azPassed && tiltPassed)
                    {
                        report.TestPassedDict[surface.SurfaceId] = true;
                    }
                    else
                    {
                        report.TestPassedDict[surface.SurfaceId] = false;
                    }
                }
            }
            catch (Exception e)
            {
                report.longMsg = ("SORRY, we have run into an unexpected issue:" + e.ToString());
                report.passOrFail = false;
                return report;
            }

            //if we made it this far, we did not run into any exceptions
            if (report.TestPassedDict.ContainsValue(false))
            {
                report.longMsg = "TEST FAIL:  There were some errors found when comparing the Surfaces' Planar Geometry Definition and the Surfaces' Tilt and Azimuth.";
                report.passOrFail = false;
                return report;
            }
            else
            {
                report.longMsg = "TEST PASSED:  All Surfaces' Tilt and Azimuth Values appear to coincide with the Planar Geometry Definition Provided.";
                report.passOrFail = true;
                return report;
            }
        }
Esempio n. 16
0
        //April 11, 2014
        //This is the algorithm that attempts to find matches of edges on the enclosure.  It is used by all the Check Enclosure routines.
        //by Chien Harriman - Carmel Software Corporation
        public static DOEgbXMLPhase2Report MatchEdges(Dictionary<int, Vector.EdgeFamily> uniqueedges, List<string> ml, DOEgbXMLPhase2Report report, string spaceid)
        {
            try
            {
                int totaledgect = 0;
                int matchededges = 0;
                string lastedgenm = "";
                int surfedgect = 0;
                foreach (KeyValuePair<int, Vector.EdgeFamily> edgekp in uniqueedges)
                {
                    //a way to count edges
                    if (edgekp.Value.sbdec != lastedgenm)
                    {
                        //reset
                        lastedgenm = edgekp.Value.sbdec;
                        surfedgect = 0;
                    }
                    //here is the easiest case where there is only one related edge
                    //we know this must be a perfect match, or entirely envelopes the edge
                    if (edgekp.Value.relatedEdges.Count() == 1)
                    {
                        Vector.MemorySafe_CartCoord edgestart = edgekp.Value.startendpt[0];
                        Vector.MemorySafe_CartCoord edgeend = edgekp.Value.startendpt[1];
                        Vector.MemorySafe_CartCoord relstart = edgekp.Value.relatedEdges[0].startendpt[0];
                        Vector.MemorySafe_CartCoord relend = edgekp.Value.relatedEdges[0].startendpt[1];
                        //if the lengths are the same, then they should match perfectly.
                        //this is a valid conclusion because we already have identified that they aligh and
                        //are in the same space.
                        double edgeX = edgestart.X - edgeend.X;
                        double edgeY = edgestart.Y - edgeend.Y;
                        double edgeZ = edgestart.Z - edgeend.Z;
                        Vector.MemorySafe_CartVect edgev = new Vector.MemorySafe_CartVect(edgeX, edgeY, edgeZ);
                        double edgemag = Vector.VectorMagnitude(edgev);

                        double relX = relstart.X - relend.X;
                        double relY = relstart.Y - relend.Y;
                        double relZ = relstart.Z - relend.Z;
                        Vector.MemorySafe_CartVect relv = new Vector.MemorySafe_CartVect(relX, relY, relZ);
                        double relmag = Vector.VectorMagnitude(relv);
                        //do the check here to see if the two edges (current and related) are the same length
                        if (Math.Abs(relmag - edgemag) < report.coordtol)
                        {

                            //should match perfectly
                            ml.Add(edgekp.Value.sbdec + " Edge " + surfedgect.ToString() + " should have perfectly matched coordinates.");
                            List<bool> match = new List<bool>();
                            double tol = report.tolerance;
                            for (int i = 0; i < 2; i++)
                            {
                                Vector.MemorySafe_CartCoord p1 = edgekp.Value.relatedEdges[0].startendpt[i];
                                for (int j = 0; j < 2; j++)
                                {
                                    string x = p1.X.ToString();
                                    string y = p1.Y.ToString();
                                    string z = p1.Z.ToString();
                                    string coordstr = "(" + x + "," + y + "," + z + ")";
                                    Vector.MemorySafe_CartCoord p2 = edgekp.Value.startendpt[j];
                                    if (p2.X == p1.X && p2.Y == p1.Y && p2.Z == p1.Z)
                                    {
                                        match.Add(true);
                                        ml.Add("PERFECT MATCH: " + edgekp.Value.sbdec + " Edge " + surfedgect.ToString() + " Coordinate " + coordstr);
                                    }
                                    else if (Math.Abs(p2.X - p1.X) < tol && Math.Abs(p2.Y - p1.Y) < report.coordtol && Math.Abs(p2.Z - p1.Z) < report.coordtol)
                                    {
                                        match.Add(true);
                                        ml.Add("MATCH: " + edgekp.Value.sbdec + " Edge " + surfedgect.ToString() + " Coordinate " + coordstr);
                                        report.passOrFail = false;
                                    }
                                }
                            }
                            if (match.Count() == 2)
                            {
                                ml.Add("PASS: "******" Edge " + surfedgect.ToString() + " forms a tight enclosure with its neighbor.");
                                report.passOrFail = true;
                                //we +2 here because the related edge is not recorded
                                totaledgect += 2;
                                matchededges += 2;
                            }
                            else
                            {
                                ml.Add("FAIL: " + edgekp.Value.sbdec + " Edge " + surfedgect.ToString() + " does not form a tight enclosure with its neighbor.");
                                report.passOrFail = false;
                                //we +2 here because the related edge is not recorded
                                totaledgect += 2;
                                matchededges += 0;
                            }
                        }
                        //April 7 2014
                        //it is safe to conclude that the the two are related, but they overlap.  In this case, since there is only one neighbor
                        //it should be the case that one edge entirely envelops the other edge.
                        //this edge, has to be the one that is enveloped, because it only has one related edge, by convention
                        else
                        {
                            ml.Add(edgekp.Value.sbdec + " Edge " + surfedgect.ToString() + " should be enclosed by its neighboring edge.");
                            //es--------------ee
                            //rs-------------------re
                            if (Math.Abs(edgestart.X - relstart.X) <= report.coordtol && Math.Abs(edgestart.Y - relstart.Y) <= report.coordtol && Math.Abs(edgestart.Z - relstart.Z) <= coordtol)
                            {
                                string x = edgestart.X.ToString();
                                string y = edgestart.Y.ToString();
                                string z = edgestart.Z.ToString();
                                string coordstr = "(" + x + "," + y + "," + z + ")";
                                ml.Add("MATCH: " + edgekp.Value.sbdec + " Edge " + surfedgect.ToString() + " Coordinate " + coordstr);
                                double Cx = edgeend.X - relstart.X;
                                double Cy = edgeend.Y - relstart.Y;
                                double Cz = edgeend.Z - relstart.Z;
                                Vector.MemorySafe_CartVect C = new Vector.MemorySafe_CartVect(Cx, Cy, Cz);

                                double Dx = edgeend.X - relend.X;
                                double Dy = edgeend.Y - relend.Y;
                                double Dz = edgeend.Z - relend.Z;
                                Vector.MemorySafe_CartVect D = new Vector.MemorySafe_CartVect(Dx, Dy, Dz);

                                double dotend = Vector.DotProductMag(C, D);
                                //both of these dot products should point in opposite directions, proving the edge is entirely enveloped
                                if (Math.Abs(dotend) - 1 <= report.vectorangletol)
                                {
                                    ml.Add("PASS" + edgekp.Value.sbdec + " Edge " + surfedgect.ToString() + " overlapping neighbor forms a tight enclosure with its neighbor.");
                                }
                                else
                                {
                                    ml.Add("FAIL" + edgekp.Value.sbdec + " Edge " + surfedgect.ToString() + "overlapping neighbor does not form a tight enclosure with its neighbor.");
                                    report.passOrFail = false;
                                }
                            }
                            //es-----------------ee
                            //re--------------------------rs
                            else if (Math.Abs(edgestart.X - relend.X) <= report.coordtol && Math.Abs(edgestart.Y - relend.Y) <= report.coordtol && Math.Abs(edgestart.Z - relend.Z) <= coordtol)
                            {
                                string x = edgestart.X.ToString();
                                string y = edgestart.Y.ToString();
                                string z = edgestart.Z.ToString();
                                string coordstr = "(" + x + "," + y + "," + z + ")";
                                ml.Add("MATCH: " + edgekp.Value.sbdec + " Edge " + surfedgect.ToString() + " Coordinate " + coordstr);
                                double Cx = edgeend.X - relstart.X;
                                double Cy = edgeend.Y - relstart.Y;
                                double Cz = edgeend.Z - relstart.Z;
                                Vector.MemorySafe_CartVect C = new Vector.MemorySafe_CartVect(Cx, Cy, Cz);

                                double Dx = edgeend.X - relend.X;
                                double Dy = edgeend.Y - relend.Y;
                                double Dz = edgeend.Z - relend.Z;
                                Vector.MemorySafe_CartVect D = new Vector.MemorySafe_CartVect(Dx, Dy, Dz);

                                double dotend = Vector.DotProductMag(C, D);
                                //both of these dot products should point in opposite directions, proving the edge is entirely enveloped
                                if (Math.Abs(dotend) - 1 <= report.vectorangletol)
                                {
                                    ml.Add("PASS" + edgekp.Value.sbdec + " Edge " + surfedgect.ToString() + " overlapping neighbor forms a tight enclosure with its neighbor.");
                                    totaledgect += 1;
                                    matchededges += 1;
                                }
                                else
                                {
                                    ml.Add("FAIL" + edgekp.Value.sbdec + " Edge " + surfedgect.ToString() + " overlapping neighbor does not form a tight enclosure with its neighbor.");
                                    report.passOrFail = false;
                                    totaledgect += 1;
                                    matchededges += 0;
                                }
                            }
                            //ee-----------------es
                            //rs--------------------------re
                            else if (Math.Abs(edgeend.X - relstart.X) <= report.coordtol && Math.Abs(edgeend.Y - relstart.Y) <= report.coordtol && Math.Abs(edgeend.Z - relstart.Z) <= coordtol)
                            {
                                string x = edgeend.X.ToString();
                                string y = edgeend.Y.ToString();
                                string z = edgeend.Z.ToString();
                                string coordstr = "(" + x + "," + y + "," + z + ")";
                                ml.Add("MATCH: " + edgekp.Value.sbdec + " Edge " + surfedgect.ToString() + " Coordinate " + coordstr);
                                double Ax = edgestart.X - relstart.X;
                                double Ay = edgestart.Y - relstart.Y;
                                double Az = edgestart.Z - relstart.Z;
                                Vector.MemorySafe_CartVect A = new Vector.MemorySafe_CartVect(Ax, Ay, Az);

                                double Bx = edgestart.X - relend.X;
                                double By = edgestart.Y - relend.Y;
                                double Bz = edgestart.Z - relend.Z;
                                Vector.MemorySafe_CartVect B = new Vector.MemorySafe_CartVect(Bx, By, Bz);

                                double dotstart = Vector.DotProductMag(A, B);
                                //both of these dot products should point in opposite directions, proving the edge is entirely enveloped
                                if (Math.Abs(dotstart) - 1 <= report.vectorangletol)
                                {
                                    ml.Add("PASS" + edgekp.Value.sbdec + " Edge " + surfedgect.ToString() + " overlapping neighbor forms a tight enclosure with its neighbor.");
                                    totaledgect += 1;
                                    matchededges += 1;
                                }
                                else
                                {
                                    ml.Add("FAIL" + edgekp.Value.sbdec + " Edge " + surfedgect.ToString() + " overlapping neighbor does not form a tight enclosure with its neighbor.");
                                    report.passOrFail = false;
                                    totaledgect += 1;
                                    matchededges += 0;
                                }
                            }
                            //ee-----------------es
                            //re--------------------------rs
                            else if (Math.Abs(edgeend.X - relend.X) <= report.coordtol && Math.Abs(edgeend.Y - relend.Y) <= report.coordtol && Math.Abs(edgeend.Z - relend.Z) <= coordtol)
                            {
                                string x = edgeend.X.ToString();
                                string y = edgeend.Y.ToString();
                                string z = edgeend.Z.ToString();
                                string coordstr = "(" + x + "," + y + "," + z + ")";
                                ml.Add("MATCH: " + edgekp.Value.sbdec + " Edge " + surfedgect.ToString() + " Coordinate " + coordstr);
                                double Ax = edgestart.X - relstart.X;
                                double Ay = edgestart.Y - relstart.Y;
                                double Az = edgestart.Z - relstart.Z;
                                Vector.MemorySafe_CartVect A = new Vector.MemorySafe_CartVect(Ax, Ay, Az);

                                double Bx = edgestart.X - relend.X;
                                double By = edgestart.Y - relend.Y;
                                double Bz = edgestart.Z - relend.Z;
                                Vector.MemorySafe_CartVect B = new Vector.MemorySafe_CartVect(Bx, By, Bz);

                                double dotstart = Vector.DotProductMag(A, B);
                                //both of these dot products should point in opposite directions, proving the edge is entirely enveloped
                                if (Math.Abs(dotstart) - 1 <= report.vectorangletol)
                                {
                                    ml.Add("PASS" + edgekp.Value.sbdec + " Edge " + surfedgect.ToString() + " overlapping neighbor forms a tight enclosure with its neighbor.");
                                    totaledgect += 1;
                                    matchededges += 1;
                                }
                                else
                                {
                                    ml.Add("FAIL" + edgekp.Value.sbdec + " Edge " + surfedgect.ToString() + " overlapping neighbor does not form a tight enclosure with its neighbor.");
                                    report.passOrFail = false;
                                    totaledgect += 1;
                                    matchededges += 0;
                                }
                            }
                            //overlapping edges
                            else
                            {
                                ml.Add(edgekp.Value.sbdec + " Edge " + surfedgect.ToString() + " is overlapped at both ends by its neighboring edge.");
                                double Ax = edgestart.X - relstart.X;
                                double Ay = edgestart.Y - relstart.Y;
                                double Az = edgestart.Z - relstart.Z;
                                Vector.MemorySafe_CartVect A = new Vector.MemorySafe_CartVect(Ax, Ay, Az);

                                double Bx = edgestart.X - relend.X;
                                double By = edgestart.Y - relend.Y;
                                double Bz = edgestart.Z - relend.Z;
                                Vector.MemorySafe_CartVect B = new Vector.MemorySafe_CartVect(Bx, By, Bz);

                                double Cx = edgeend.X - relstart.X;
                                double Cy = edgeend.Y - relstart.Y;
                                double Cz = edgeend.Z - relstart.Z;
                                Vector.MemorySafe_CartVect C = new Vector.MemorySafe_CartVect(Cx, Cy, Cz);

                                double Dx = edgeend.X - relend.X;
                                double Dy = edgeend.Y - relend.Y;
                                double Dz = edgeend.Z - relend.Z;
                                Vector.MemorySafe_CartVect D = new Vector.MemorySafe_CartVect(Dx, Dy, Dz);

                                double dotstart = Vector.DotProductMag(A, B);
                                double dotend = Vector.DotProductMag(C, D);
                                //both of these dot products should point in opposite directions, proving the edge is entirely enveloped
                                if (Math.Abs(dotstart) - 1 <= report.vectorangletol && Math.Abs(dotend) - 1 <= report.vectorangletol)
                                {
                                    ml.Add("PASS" + edgekp.Value.sbdec + " Edge " + surfedgect.ToString() + " overlapping neighbor forms a tight enclosure with its neighbor.");
                                    totaledgect += 1;
                                    matchededges += 1;
                                }
                                else
                                {
                                    ml.Add("FAIL" + edgekp.Value.sbdec + " Edge " + surfedgect.ToString() + " overlapping neighbor does not form a tight enclosure with its neighbor.");
                                    report.passOrFail = false;
                                    totaledgect += 1;
                                    matchededges += 0;
                                }
                            }
                        }

                    }
                    else if (edgekp.Value.relatedEdges.Count() > 1)
                    {
                        ml.Add(edgekp.Value.sbdec + " Edge " + surfedgect.ToString() + " has " + edgekp.Value.relatedEdges.Count() + " neighboring edges.");
                        //more robust testing
                        Vector.EdgeFamily[] orderededges = new Vector.EdgeFamily[edgekp.Value.relatedEdges.Count()];
                        //align the related edges
                        orderededges = AlignEdges(orderededges, edgekp.Value, coordtol);

                        int coordcount = 0;
                        double segmentslength = 0;
                        int lastct = edgekp.Value.relatedEdges.Count() * 2 - 2;
                        Vector.CartCoord st = new Vector.CartCoord();
                        Vector.CartCoord end = new Vector.CartCoord();
                        foreach (Vector.EdgeFamily edge in orderededges)
                        {

                            if (coordcount == 0)
                            {
                                st.X = edge.startendpt[0].X;
                                st.Y = edge.startendpt[0].Y;
                                st.Z = edge.startendpt[0].Z;
                            }

                            if (coordcount == lastct)
                            {
                                end.X = edge.startendpt[1].X;
                                end.Y = edge.startendpt[1].Y;
                                end.Z = edge.startendpt[1].Z;
                            }
                            Vector.MemorySafe_CartVect v = Vector.CreateMemorySafe_Vector(edge.startendpt[0], edge.startendpt[1]);
                            double mag = Vector.VectorMagnitude(v);
                            segmentslength += mag;
                            coordcount += 2;
                        }
                        Vector.MemorySafe_CartVect v2 = Vector.CreateMemorySafe_Vector(edgekp.Value.startendpt[0], edgekp.Value.startendpt[1]);
                        double mag2 = Vector.VectorMagnitude(v2);
                        if (Math.Abs(segmentslength - mag2) < report.lengthtol)
                        {
                            ml.Add(edgekp.Value.sbdec + ":PASS:Multiple Overlapping edges properly match.");
                        }
                        else
                        {
                            //then something is wrong.
                            ml.Add(edgekp.Value.sbdec + ":FAIL:Overlapping edges do not match as expected.");
                            report.passOrFail = false;
                        }

                    }
                    else if (edgekp.Value.relatedEdges.Count() == 0)
                    {
                        //something is wrong
                        ml.Add(edgekp.Value.sbdec + "FAIL:" + edgekp.Value.sbdec + " Edge " + surfedgect.ToString() + " has no reported neighboring edges.");
                        report.passOrFail = false;
                    }
                    surfedgect += 1;
                }
                report.MessageList[spaceid] = ml;
                //all edges align = true
                if (report.passOrFail)
                {
                    report.longMsg = "TEST PASSED: " + totaledgect + " edges in the gbXML file.  " + matchededges + " edges found with ideal alignment.";
                }
                //all edges align = false
                else
                {
                    report.longMsg = "TEST FAILED: " + totaledgect + " edges in the gbXML file.  " + matchededges + " edges found with ideal alignment.";
                }
                return report;

            }
            catch (Exception e)
            {
                report.longMsg = ("ERROR, we have run into an unexpected issue:" + e.ToString());
                report.passOrFail = false;
                return report;
            }
        }
Esempio n. 17
0
        public static DOEgbXMLPhase2Report CheckSpaceEnclosureSG(List<gbXMLSpaces> spaces, DOEgbXMLPhase2Report report)
        {
            try
            {
                report.testSummary = "This test checks the enclosure defined by the ShellGeometry PolyLoops for each given space in your gbXML file.";
                report.testSummary += " This is an optional test because ShellGeometry definitions are optional.";
                report.testSummary += " An enclosure test is important because it ensures that each of the surfaces in the gbXML definition is properly aligned ";
                report.testSummary += " with its neighbor.  The test checks to make sure that all edges of each surface line up with one another so that there are not";
                report.testSummary += "any gaps.";
                report.passOrFail = true;
                foreach (gbXMLSpaces space in spaces)
                {
                    List<string> ml = new List<string>();
                    Dictionary<int, Vector.EdgeFamily> uniqueedges = new Dictionary<int, Vector.EdgeFamily>();

                    if (space.sg.cs.ploops.Count() > 0)
                    {
                        string rep = space.id + " has ShellGeometry PolyLoops.  Conducting tests of ShellGeometry PolyLoops water tightness";
                        report.TestPassedDict[rep] = true;
                        int sgcount = 1;
                        foreach (DOEgbXML.gbXMLSpaces.PolyLoop pl in space.sg.cs.ploops)
                        {
                            string surfaceid = "shellgeometry-" + sgcount;
                            uniqueedges = Vector.GetEdgeFamilies(surfaceid, uniqueedges, pl.plcoords, report.coordtol, report.vectorangletol);
                            sgcount++;
                        }
                        if (uniqueedges.Count > 0)
                        {
                            string erep = space.id + ": Gathered edges of the ShellGeometry PolyLoop successfullly.";
                            report.TestPassedDict[erep] = true;
                        }
                        else
                        {
                            string erep = space.id + ": Gathered edges of the ShellGeometry PolyLoop unsuccessfullly.";
                            report.TestPassedDict[erep] = false;
                        }

                        //see how well enclosure is formed
                        //new function added April 11, 2014
                        report = MatchEdges(uniqueedges, ml, report, space.id);
                    }
                    else
                    {
                        string rep = space.id + " does not has ShellGeometry PolyLoops (this is not an error).  Conducting tests of ShellGeometry PolyLoops water tightness";
                        report.TestPassedDict[rep] = false;
                    }
                    report.MessageList[space.id] = ml;
                }

            }
            catch (Exception e)
            {
                report.longMsg = ("SORRY, we have run into an unexpected issue:" + e.ToString());
                report.passOrFail = false;
                return report;
            }
            return report;
        }
        public static DOEgbXMLPhase2Report SurfaceIDUniquenessTest(XmlDocument gbXMLDoc, XmlNamespaceManager gbXMLnsm, DOEgbXMLPhase2Report report)
        {
            //report pass or fail attribute should always be set to false
            
            List<string> surfaceIdList = new List<string>();
            try
            {
                report.testSummary = "This test ensures that all Surface elements in the gbXML file are unique.  This is a requirement of all gbXML files.  ";
                report.testSummary += "It might not appear important at first glance, but having unique Surface id elements ensures that information about Surfaces in the file ";
                report.testSummary += "can be located without any confusion.  Naming two different surfaces with the same id would make certain analyses impossible to properly conduct.";
                XmlNodeList nodes = gbXMLDoc.SelectNodes("/gbXMLv5:gbXML/gbXMLv5:Campus/gbXMLv5:Surface", gbXMLnsm);
                foreach (XmlNode node in nodes)
                {
                    List<string> ml = new List<string>();
                    //looks to see if the surfaceId is already included in the list of space IDs being generated
                    string surfaceId = "";
                    XmlAttributeCollection xmlatts = node.Attributes;
                    foreach (XmlAttribute att in xmlatts)
                    {
                        if (att.Name == "id")
                        {
                            surfaceId = att.Value;
                        }
                    }
                    if (surfaceIdList.Contains(surfaceId))
                    {
                        //not unique
                        ml.Add("FAIL: The id " + surfaceId + " is not a unique id.");
                    }
                    //unique
                    else
                    {
                        surfaceIdList.Add(surfaceId);
                        ml.Add("PASS: The id " + surfaceId + " is a unique id.");
                        report.MessageList[surfaceId] = ml;
                    }
                }
                if (report.TestPassedDict.ContainsValue(false))
                {
                    report.passOrFail = false;
                    report.longMsg = "TEST FAILED: This test has failed.  All Surface elements in this gbXML file do not have id attributes that are unique.";

                }
                else
                {
                    report.longMsg = "TEST PASSED: All Surface elements in this gbXML file have unique id attributes.";
                    report.passOrFail = true;
                }

            }
            catch (Exception e)
            {
                report.longMsg = ("SORRY, we have run into an unexpected issue:" + e.ToString());
                report.passOrFail = false;
                return report;
            }
            return report;
        }
Esempio n. 19
0
        private static void ProcessReport(DOEgbXMLPhase2Report report, string path)
        {
            if (!File.Exists(path))
            {

                using (System.IO.StreamWriter file = new System.IO.StreamWriter(path))
                {
                    file.WriteLine("Explanation of Test: " + report.testSummary);
                    if (report.passOrFail) { file.WriteLine("Test has Passed."); }
                    else { file.WriteLine("Test has Failed."); }
                    file.WriteLine("Explanation of Why Test Passed or Failed: " + report.longMsg);
                    if (report.TestPassedDict.Count() > 0)
                    {
                        file.WriteLine("Summary of findings: ");
                        foreach (KeyValuePair<string, bool> kp in report.TestPassedDict)
                        {
                            // If the line doesn't contain the word 'Second', write the line to the file.
                            string line = kp.Key + ":" + kp.Value.ToString();
                            file.WriteLine(line);
                        }

                    }
                    //more detail

                    if (report.MessageList.Count() > 0)
                    {
                        foreach (KeyValuePair<string, List<string>> message in report.MessageList)
                        {

                            foreach (string finding in message.Value)
                            {
                                string line = message.Key + ": ";
                                line += finding;
                                file.WriteLine(line);
                            }
                        }
                    }
                    file.WriteLine("\n");
                }
            }
            else
            {
                using (StreamWriter sw = File.AppendText(path))
                {
                    sw.WriteLine("Explanation of Test: " + report.testSummary);
                    if (report.passOrFail) { sw.WriteLine("Test has Passed."); }
                    else { sw.WriteLine("Test has failed."); }
                    sw.WriteLine("Explanation of Why Test Passed or Failed: " + report.longMsg);
                    if (report.TestPassedDict.Count() > 0)
                    {
                        sw.WriteLine("Summary of findings: ");
                        foreach (KeyValuePair<string, bool> kp in report.TestPassedDict)
                        {
                            // If the line doesn't contain the word 'Second', write the line to the file.
                            string line = kp.Key + ":" + kp.Value.ToString();
                            sw.WriteLine(line);
                        }

                    }
                    //more detail

                    if (report.MessageList.Count() > 0)
                    {
                        foreach (KeyValuePair<string, List<string>> message in report.MessageList)
                        {

                            foreach (string finding in message.Value)
                            {
                                string line = message.Key + ": ";
                                line += finding;
                                sw.WriteLine(line);
                            }
                        }
                    }
                    sw.WriteLine("\n");
                }
            }
        }
        public static DOEgbXMLPhase2Report AtMost2SpaceAdjId(XmlDocument gbXMLDoc, XmlNamespaceManager gbXMLnsm, DOEgbXMLPhase2Report report)
        {
            //pass or fail attribute should always be set to false
            report.passOrFail = true;
            report.testSummary = "A simple test to ensure that each Surface element has at least 1 but no more than 2 allowed AdjacentSpaceIds.";
            try
            {
                
                XmlNodeList nodes = gbXMLDoc.SelectNodes("/gbXMLv5:gbXML/gbXMLv5:Campus/gbXMLv5:Surface", gbXMLnsm);
                string surfacetype = "";
                foreach (XmlNode surface in nodes)
                {
                    int count = 0;
                    List<string> ml = new List<string>();
                    string surfaceId="";
                    XmlAttributeCollection xmlatts = surface.Attributes;
                    foreach (XmlAttribute att in xmlatts)
                    {
                        if (att.Name == "id")
                        {
                            surfaceId += att.Value;
                        }

                        if(att.Name == "surfaceType")
                        {
                            surfacetype = att.Value;
                            break;
                        }
                    }
                    foreach (XmlNode chld in surface.ChildNodes)
                    {
                        if (chld.Name == "AdjacentSpaceId")
                        {
                            count += 1;
                        }
                    }
                    //the adjacent space id is required, but must be less than 2
                    if (count > 0 && count <= 2)
                    {
                        ml.Add("PASS:  There are " + count.ToString() + " AdjacentSpaceId nodes for this Surface.");
                        report.MessageList[surfaceId] = ml;
                    }
                    else
                    {
                        if (surfacetype == "Shade")
                        {
                            continue;
                        }
                        else
                        {
                            ml.Add("FAIL:  There are " + count.ToString() + " AdjacentSpaceId nodes for this Surface.");
                            report.MessageList[surfaceId] = ml;
                            report.passOrFail = false;
                        }
                    }
                }
                if (report.passOrFail)
                {
                    report.longMsg = "TEST PASSED:  This gbXML file is has Surface elements all within the required maximum allotment of AdjacentSpaceId nodes (2, i.e - to describe each enclosed neighbor).";
                }
                else
                {
                    report.longMsg = "TEST FAILED:  This gbXML file has instances where the allowed number of AdjacentSpaceId nodes (2, i.e - to describe each enclosed neighbor) has been exceeded.  Contact your BIM/CAD authoring tool to let them know to correct the issue.";
                }
            }
            catch (Exception e)
            {
                report.longMsg = ("SORRY, we have run into an unexpected issue:" + e.ToString());
                report.passOrFail = false;
                return report;
            }
            return report;
        }
Esempio n. 21
0
        public static DOEgbXMLPhase2Report CheckSurfaceEnclosure(Dictionary<string, List<SurfaceDefinitions>> surfaceEnclosures, DOEgbXMLPhase2Report report)
        {
            try
            {
                report.testSummary = "This test checks surfaces proclaiming to be children of a given space ID.";
                report.testSummary += "  It searches each of the surfaces' edges and tries to find other edges that align.";
                report.passOrFail = true;
                foreach (KeyValuePair<string, List<SurfaceDefinitions>> kp in surfaceEnclosures)
                {
                    List<string> ml = new List<string>();
                    ml.Add(kp.Key + ": Testing begins.");
                    Dictionary<int, Vector.EdgeFamily> uniqueedges = new Dictionary<int, Vector.EdgeFamily>();

                    foreach (SurfaceDefinitions surface in kp.Value)
                    {
                        uniqueedges = Vector.GetEdgeFamilies(surface.SurfaceId, uniqueedges, surface.PlCoords, .0001, .0001);
                    }
                    ml.Add("Gathered edges and their neighboring relationships.");
                    ml.Add("Validating the surfaces' edges alignment with one another (water tightness check.");
                    //check the edge families to see how water tight the edges are
                    //there should always be at least one related Edge
                    //if there is only one, it should match exactly (or within some settable tolerance)
                    //if there is more than one, they each should only intersect at their ends (within some tolerance) and not intersect
                    //and there should be no gaps
                    //new function added April 11, 2014
                    report = MatchEdges(uniqueedges, ml, report, kp.Key);

                    report.MessageList[kp.Key] = ml;
                }
            }
            catch (Exception e)
            {

            }
            return report;
        }
        protected void Page_Load(object sender, EventArgs e)
        {
            if (TestDetailLabelOverView != null)
            {
                if (Request.QueryString["type"] != "Error")
                {
                    // List of reports
                    List<DOEgbXMLPhase2Report> reportlist = new List<DOEgbXMLPhase2Report>();
                    if (Session["reportList"] == null || Request.QueryString["type"] == null)
                    {
                        Response.Redirect(@"~/");
                    }
                    reportlist = (List<DOEgbXMLPhase2Report>)Session["reportList"];

                    #region Get Current Report
                    //looking for the right report from the list
                    int testType = 0;
                    int subType = -1;

                    if (Request.QueryString["type"] != null)
                    {
                        try
                        {
                            testType = (int)Convert.ToInt32(Request.QueryString["type"]);
                        }
                        catch
                        {
                            return;
                        }
                    }

                    if (Request.QueryString["subtype"] != null)
                    {
                        try
                        {
                            subType = (int)Convert.ToInt32(Request.QueryString["subtype"]);
                        }
                        catch
                        {
                            return;
                        }
                    }

                    DOEgbXMLPhase2Report rightReport = new DOEgbXMLPhase2Report();
                    foreach (DOEgbXMLPhase2Report report in reportlist)
                    {
                        if (report.testType == (TestType)testType)
                        {
                            if (report.subTestIndex == -1 || report.subTestIndex == subType)
                            {
                                rightReport = report;
                            }
                        }
                    }
                    #endregion Get Current Report

                    #region Title
                    string title = rightReport.testType.ToString();
                    title = title.Replace("_", " ");
                    if (subType != -1)
                    {
                        title += " " + subType;
                    }
                    TestDetailLabelName.Text += "<h2>" + title + "</h2>";
                    #endregion Title
                    #region Description
                    TestDetailLabelOverView.Text += "<h4>Test Summary:</h4><p>" + rightReport.testSummary + "</p>";
                    #endregion Description
                    #region Message Summary
                    var passTest = rightReport.TestPassedDict.Values;
                    bool individualTestBool = true;
                    foreach (bool testResult in passTest)
                    {
                        if (testResult == false)
                        {
                            individualTestBool = false;
                            break;
                        }
                    }

                    string output = "<div class='panel panel-default'><div class='panel-heading'><h4 class='panel-title'>Test Results:</h4></div><div class='panel-body'>";
                    if (rightReport.passOrFail && individualTestBool)
                    {
                        output += "<p class='text-success panel-body'>" + rightReport.longMsg + "</p>";
                    }
                    else
                    {
                        output += "<p class='text-danger panel-body'>" + rightReport.longMsg + "</p>";
                    }
                    #endregion Message Summary
                    #region Message Detail
                    //message list, print out each message in the list if there are any
                    if (rightReport.MessageList.Count() > 0)
                    {
                        output += "<div id='notaccordion'>";
                        foreach (KeyValuePair<string, List<string>> message in rightReport.MessageList)
                        {
                            bool panelError = false;
                            string currentKeyOutput = "";
                            #region Panel Body
                            string currentBodyOutput = "<div>";
                            foreach (string finding in message.Value)
                            {
                                if (finding.Substring(0, 5) == "PASS:"******"PERFECT MATCH:" || finding.Substring(0,12) =="TEST PASSED:")
                                {
                                    currentBodyOutput += "<p class='text-success'>" + finding + "</p>";
                                }
                                else if (finding.Substring(0, 5) == "FAIL:" || finding.Substring(0,12) == "TEST FAILED:")
                                {
                                    currentBodyOutput += "<p class='text-danger'>" + finding + "</p>";
                                    panelError = true;
                                }
                                else
                                {
                                    currentBodyOutput += "<p class='text-info'>" + finding + "</p>";
                                }
                            }
                            currentBodyOutput += "</div>";
                            #endregion Panel Body
                            #region Panel Header
                            if (panelError)
                            {
                                currentKeyOutput += "<h3 style='color:Red'>" + message.Key + "</h3>";
                            }
                            else
                            {
                                currentKeyOutput += "<h3>" + message.Key + "</h3>";
                            }
                            #endregion Panel Header
                            output += currentKeyOutput + currentBodyOutput;
                        }
                        output += "</div>";
                    }
                    else if (rightReport.TestPassedDict.Count() > 0)
                    {
                        output += "<div id='notaccordion'>";
                        foreach (KeyValuePair<string, bool> pair in rightReport.TestPassedDict)
                        {
                            //output += "<p class='text-info'>" + pair.Key + ":" + pair.Value.ToString() + "</p>";
                            string currentKey = "";
                            if (currentKey == pair.Key)
                            {
                                output += "<p>" + pair.Value.ToString() + "</p>";
                            }
                            else
                            {
                                output += "<h3>" + pair.Key + "</h3>";
                                output += "<div><p>" + pair.Value.ToString() + "</p></div>";
                                currentKey = pair.Key;
                            }
                        }
                        output += "</div>";
                    }
                    output += "</div></div>";
                    #endregion Message Detail
                    TestDetailLabelResults.Text = output;
                }
                else
                {
                    TestDetailImage.Visible = false;
                    TestDetailLabelResults.Text = Session["table"].ToString();
                }
            }
        }
Esempio n. 23
0
        private void ProcessReport(DOEgbXMLPhase2Report report, bool createTable)
        {
            //add report to report list
            //have to deep copy the report before put report in the list
            DOEgbXMLPhase2Report tmpreport = report.Copy();
            ReportList.Add(tmpreport);

            //title
            int subType = -1;
            string title = report.testType.ToString();
            if (report.subTestIndex != -1 && report.subTestIndex != null)
            {
                subType = report.subTestIndex;
            }
            title = title.Replace("_", " ");
            if (subType != -1)
            {
                title += " " + subType;
            }
            //message
            var passTest = report.TestPassedDict.Values;
            bool individualTestBool = true;
            foreach (bool testResult in passTest)
            {
                if (testResult == false)
                {
                    individualTestBool = false;
                    break;
                }
            }

            //description
            log += "Explanation of Test: " + report.testSummary + System.Environment.NewLine;

            if (report.passOrFail && individualTestBool)
            {
                log += "Test has Passed" + System.Environment.NewLine;
            }
            else
            {
                log += "Test has Failed" + System.Environment.NewLine;
                overallPassTest = false;
            }
            log += "Explanation of What Happened: " + report.longMsg + System.Environment.NewLine;

            //message list, print out each message in the list if there are any
            if (report.MessageList.Count() > 0)
            {
                foreach (KeyValuePair<string, List<string>> message in report.MessageList)
                {
                    foreach (string finding in message.Value)
                    {
                        log += message.Key + ": " + finding + System.Environment.NewLine;
                    }
                }
            }
            else if (report.TestPassedDict.Count() > 0)
            {
                foreach (KeyValuePair<string, bool> pair in report.TestPassedDict)
                {
                    log += pair.Key + ": " + pair.Value + System.Environment.NewLine;
                }
            }
            log += System.Environment.NewLine;

            //create table row
            if (createTable)
            {
                if (report.standResult.Count == 0)
                {
                    report.standResult.Add("---");
                    report.testResult.Add("---");
                    report.idList.Add("");
                }

                //for each output
                for (int i = 0; i < report.standResult.Count; i++)
                {
                    bool sameString = false;
                    if (report.standResult[i] == report.testResult[i])
                        sameString = true;

                    //check if test pass or fail
                    if ((report.passOrFail && individualTestBool))// || sameString)
                        TestResultPanel.Controls.Add(new LiteralControl("<tr class='success'>"));
                    else
                    {
                        TestResultPanel.Controls.Add(new LiteralControl("<tr class='danger'>"));
                        overallPassTest = false;
                    }

                    TestResultPanel.Controls.Add(new LiteralControl("<td style='text-align:left'><a href='TestDetailPage.aspx?type=" + (int)report.testType + "&subtype=" + report.subTestIndex + "' target='_blank'>" + title + " " + report.idList[i] + "</a></td>"));

                    if ((report.passOrFail && individualTestBool))// || sameString)
                    {
                        TestResultPanel.Controls.Add(new LiteralControl("<td>&plusmn" + report.tolerance + " " + report.unit + "</td><td>Pass</td></tr>"));
                    }
                    else
                    {
                        TestResultPanel.Controls.Add(new LiteralControl("<td>&plusmn" + report.tolerance + " " + report.unit + "</td><td>Fail</td></tr>"));
                    }
                }
            }
        }