Revit Transform Matrix from point cloud to revit link - api

We insert a point cloud in Revit and have to move and rotate it in several axles to get a good world alignment. We then need to apply the same transforms to a Revit MEP link that contains edgwise piping.
I have acquired the 3x4 matrix from the point cloud in revit, I would like to apply that to the revit mep link so that they are in alignment.
I have successfully applied the translation portion of the transform, I am stuck on the rotation portion. Could someone please assist with this. Dyslexia and Matrices do not work well together.
Thanks to Jeremy at the Building Coder for getting me this far!
9/4/19 - I edited the rotational part of the code, however the "ElementTransformUtils.RotateElement" does not have any effect on the link in Revit.
Autodesk.Revit.DB.View
pView = ActiveUIDocument.Document.ActiveView;Autodesk.Revit.DB.Transaction
t = new Autodesk.Revit.DB.Transaction(ActiveUIDocument.Document, "EdgewiseCoordination");
t.Start();
UIDocument uidoc = this.ActiveUIDocument;
Document document = uidoc.Document;
Autodesk.Revit.ApplicationServices.Application application = document.Application;
ElementId elementid = null;
elementid = uidoc.Selection.PickObject(ObjectType.Element, "Select element to Copy Transform or ESC to reset the view").ElementId;
Element e = document.GetElement(elementid);
Instance ei = e as Instance;
Transform pct = ei.GetTransform();
ElementId elementid2 = null;
elementid2 = uidoc.Selection.PickObject(ObjectType.Element, "Select element to Apply Transform or ESC to reset the view").ElementId;
Element e2 = document.GetElement(elementid2);
Instance ei2 = e2 as Instance;
ElementTransformUtils.MoveElement(document,elementid2,pct.Origin);
Line lineaxis = GetRotationAxisFromTransform(pct);
double tangle = GetRotationAngleFromTransform(pct);
ElementTransformUtils.RotateElement(document,elementid2,lineaxis,tangle);
t.Commit();
}
private static Line GetRotationAxisFromTransform(Transform transform)
{
double x = transform.BasisY.Z - transform.BasisZ.Y;
double y = transform.BasisZ.X - transform.BasisX.Z;
double z = transform.BasisX.Y - transform.BasisY.X;
return Line.CreateUnbound(transform.Origin, new XYZ(x, y, z));
}
private static double GetRotationAngleFromTransform(Transform transform)
{
double x = transform.BasisX.X;
double y = transform.BasisY.Y;
double z = transform.BasisZ.Z;
double trace = x + y + z;
return Math.Acos((trace - 1) / 2.0);
}
Earlier Code to save out the transform----------------------------------
public void Objectlocation()
{
Autodesk.Revit.DB.View
pView = ActiveUIDocument.Document.ActiveView;Autodesk.Revit.DB.Transaction
t = new Autodesk.Revit.DB.Transaction(ActiveUIDocument.Document, "Objectlocation");
t.Start();
UIDocument uidoc = this.ActiveUIDocument;
Document document = uidoc.Document;
Autodesk.Revit.ApplicationServices.Application application = document.Application;
ElementId elementid = null;
elementid = uidoc.Selection.PickObject(ObjectType.Element, "Select element or ESC to reset the view").ElementId;
Element e = document.GetElement(elementid);
Instance ei = e as Instance;
Transform pct = ei.GetTransform();
//string spctrans = TransformString(pct);
//TaskDialog.Show("Point Cloud Transform", spctrans);
//spctrans = (spctrans + ",0,0,0,1");
string slocx = TransformStringX(pct);
string slocy = TransformStringY(pct);
string slocz = TransformStringZ(pct);
string slocation = (slocx + "," + slocy + "," + slocz + ",0,0,0,1");
using (StreamWriter sw = new StreamWriter("test.txt"))
{
sw.WriteLine(slocation);
}
t.Commit();
}
static public string RealString( double a )
{
return a.ToString( "0.####################" );
}
static public string PointStringX( XYZ p )
{
double convunit = 0;
convunit = UnitUtils.ConvertFromInternalUnits(p.X,DisplayUnitType.DUT_DECIMAL_INCHES);
return string.Format( "{0}", RealString( convunit ));
}
static public string TransformStringX( Transform t )
{
return string.Format( "{0},{1},{2},{3}", PointStringX( t.BasisX ),
PointStringX( t.BasisY ), PointStringX( t.BasisZ ), PointStringX( t.Origin ) );
}
static public string PointStringY( XYZ p )
{
double convunit = 0;
convunit = UnitUtils.ConvertFromInternalUnits(p.Y,DisplayUnitType.DUT_DECIMAL_INCHES);
return string.Format( "{0}", RealString( convunit ));
}
static public string TransformStringY( Transform t )
{
return string.Format( "{0},{1},{2},{3}", PointStringY( t.BasisX ),
PointStringY( t.BasisY ), PointStringY( t.BasisZ ), PointStringY( t.Origin ) );
}
static public string PointStringZ( XYZ p )
{
double convunit = 0;
convunit = UnitUtils.ConvertFromInternalUnits(p.Z,DisplayUnitType.DUT_DECIMAL_INCHES);
return string.Format( "{0}", RealString( convunit ));
}
static public string TransformStringZ( Transform t )
{
return string.Format( "{0},{1},{2},{3}", PointStringZ( t.BasisX ),
PointStringZ( t.BasisY ), PointStringZ( t.BasisZ ), PointStringZ( t.Origin ) );
}
I edited the stuff you had on bcoder to split up the matrix in order to match the acad api that I was feeding it into.
ACAD API below-----------------------------------------------------------
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;
using System.Reflection;
namespace Transformer
{
public class Commands
{
[CommandMethod("TRANS", CommandFlags.UsePickSet)]
static public void TransformEntity()
{
Document doc =
Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
// Our selected entity (only one supported, for now)
ObjectId id;
// First query the pickfirst selection set
PromptSelectionResult psr = ed.SelectImplied();
if (psr.Status != PromptStatus.OK || psr.Value == null)
{
// If nothing selected, ask the user
PromptEntityOptions peo =
new PromptEntityOptions(
"\nSelect entity to transform: "
);
PromptEntityResult per = ed.GetEntity(peo);
if (per.Status != PromptStatus.OK)
return;
id = per.ObjectId;
}
else
{
// If the pickfirst set has one entry, take it
SelectionSet ss = psr.Value;
if (ss.Count != 1)
{
ed.WriteMessage(
"\nThis command works on a single entity."
);
return;
}
ObjectId[] ids = ss.GetObjectIds();
id = ids[0];
}
PromptResult pr = ed.GetString("\nEnter property name: ");
if (pr.Status != PromptStatus.OK)
return;
string prop = pr.StringResult;
// Now let's ask for the matrix string
pr = ed.GetString("\nEnter matrix values: ");
if (pr.Status != PromptStatus.OK)
return;
// Split the string into its individual cells
string[] cells = pr.StringResult.Split(new char[] { ',' });
if (cells.Length != 16)
{
ed.WriteMessage("\nMust contain 16 entries.");
return;
}
try
{
// Convert the array of strings into one of doubles
double[] data = new double[cells.Length];
for (int i = 0; i < cells.Length; i++)
{
data[i] = double.Parse(cells[i]);
}
// Create a 3D matrix from our cell data
Matrix3d mat = new Matrix3d(data);
// Now we can transform the selected entity
Transaction tr =
doc.TransactionManager.StartTransaction();
using (tr)
{
Entity ent =
tr.GetObject(id, OpenMode.ForWrite)
as Entity;
if (ent != null)
{
bool transformed = false;
// If the user specified a property to modify
if (!string.IsNullOrEmpty(prop))
{
// Query the property's value
object val =
ent.GetType().InvokeMember(
prop, BindingFlags.GetProperty, null, ent, null
);
// We only know how to transform points and vectors
if (val is Point3d)
{
// Cast and transform the point result
Point3d pt = (Point3d)val,
res = pt.TransformBy(mat);
// Set it back on the selected object
ent.GetType().InvokeMember(
prop, BindingFlags.SetProperty, null,
ent, new object[] { res }
);
transformed = true;
}
else if (val is Vector3d)
{
// Cast and transform the vector result
Vector3d vec = (Vector3d)val,
res = vec.TransformBy(mat);
// Set it back on the selected object
ent.GetType().InvokeMember(
prop, BindingFlags.SetProperty, null,
ent, new object[] { res }
);
transformed = true;
}
}
// If we didn't transform a property,
// do the whole object
if (!transformed)
ent.TransformBy(mat);
}
tr.Commit();
}
}
catch (Autodesk.AutoCAD.Runtime.Exception ex)
{
ed.WriteMessage(
"\nCould not transform entity: {0}", ex.Message
);
}
}
}
}
END ACAD API

Related

Syntax Highlighting for go in vb.net

Ok so I have been making a simple code editor in vb.net for go.. (for personal uses)
I tried this code -
Dim tokens As String = "(break|default|func|interface|select|case|defer|go|map|struct|chan|else|goto|package|switch|const|fallthrough|if|range|type|continue|for|import|return|var)"
Dim rex As New Regex(tokens)
Dim mc As MatchCollection = rex.Matches(TextBox2.Text)
Dim StartCursorPosition As Integer = TextBox2.SelectionStart
For Each m As Match In mc
Dim startIndex As Integer = m.Index
Dim StopIndex As Integer = m.Length
TextBox2.[Select](startIndex, StopIndex)
TextBox2.SelectionColor = Color.FromArgb(0, 122, 204)
TextBox2.SelectionStart = StartCursorPosition
TextBox2.SelectionColor = Color.RebeccaPurple
Next
but I couldn't add something like print statements say I want a fmt.Println("Hello World"), that is not possible, anyone help me?
I want a simple result that will do proper syntax without glitching text colors like this current code does.
Here's a code showing how to update highlighting with strings and numbers.
You would need to tweak it further to support syntax like comments, etc.
private Regex BuildExpression()
{
string[] exprs = {
"(break|default|func|interface|select|case|defer|go|map|struct|chan|else|goto|package|switch|const|fallthrough|if|range|type|continue|for|import|return|var)",
#"([0-9]+\.[0-9]*(e|E)(\+|\-)?[0-9]+)|([0-9]+\.[0-9]*)|([0-9]+)",
"(\"\")|\"((((\\\\\")|(\"\")|[^\"])*\")|(((\\\\\")|(\"\")|[^\"])*))"
};
StringBuilder sb = new StringBuilder();
for (int i = 0; i < exprs.Length; i++)
{
string expr = exprs[i];
if ((expr != null) && (expr != string.Empty))
sb.Append(string.Format("(?<{0}>{1})", "_" + i.ToString(), expr) + "|");
}
if (sb.Length > 0)
sb.Remove(sb.Length - 1, 1);
RegexOptions options = RegexOptions.ExplicitCapture | RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.IgnoreCase;
return new Regex(sb.ToString(), options);
}
private void HighlightSyntax()
{
var colors = new Dictionary<int, Color>();
var expression = BuildExpression();
Color[] clrs = { Color.Teal, Color.Red, Color.Blue };
int[] intarray = expression.GetGroupNumbers();
foreach (int i in intarray)
{
var name = expression.GroupNameFromNumber(i);
if ((name != null) && (name.Length > 0) && (name[0] == '_'))
{
var idx = int.Parse(name.Substring(1));
if (idx < clrs.Length)
colors.Add(i, clrs[idx]);
}
}
foreach (Match match in expression.Matches(richTextBox1.Text))
{
int index = match.Index;
int length = match.Length;
richTextBox1.Select(index, length);
for (int i = 0; i < match.Groups.Count; i++)
{
if (match.Groups[i].Success)
{
if (colors.ContainsKey(i))
{
richTextBox1.SelectionColor = colors[i];
break;
}
}
}
}
}
What we found during development of our Code Editor libraries, is that the regular expression-based parsers are hard to adapt to fully support advanced syntax like contextual keywords (LINQ) or interpolated strings.
You might find a bit more information here:
https://www.alternetsoft.com/blog/code-parsing-explained
The most accurate syntax highlighting for VB.NET can be implemented using Microsoft.CodeAnalysis API, it's the same API used internally by Visual Studio text editor.
Below is sample code showing how to get classified spans for VB.NET code (every span contains start/end position within the text and classification type, i.e. keyword, string, etc.). These spans then can be used to highlight text inside a textbox.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Classification;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.Text;
public class VBClassifier
{
private Workspace workspace;
private static string FileContent = #"
Public Sub Run()
Dim test as TestClass = new TestClass()
End Sub";
public void Classify()
{
var project = InitProject();
var doc = AddDocument(project, "file1.vb", FileContent);
var spans = Classify(doc);
}
protected IEnumerable<ClassifiedSpan> Classify(Document document)
{
var text = document.GetTextAsync().Result;
var span = new TextSpan(0, text.Length);
return Classifier.GetClassifiedSpansAsync(document, span).Result;
}
protected Document AddDocument(Project project, string fileName, string code)
{
var documentId = DocumentId.CreateNewId(project.Id, fileName);
ApplySolutionChanges(s => s.AddDocument(documentId, fileName, code, filePath: fileName));
return workspace.CurrentSolution.GetDocument(documentId);
}
protected virtual void ApplySolutionChanges(Func<Solution, Solution> action)
{
var solution = workspace.CurrentSolution;
solution = action(solution);
workspace.TryApplyChanges(solution);
}
protected MefHostServices GetRoslynCompositionHost()
{
IEnumerable<Assembly> assemblies = MefHostServices.DefaultAssemblies;
var compositionHost = MefHostServices.Create(assemblies);
return compositionHost;
}
protected Project CreateDefaultProject()
{
var solution = workspace.CurrentSolution;
var projectId = ProjectId.CreateNewId();
var projectName = "VBTest";
ProjectInfo projectInfo = ProjectInfo.Create(
projectId,
VersionStamp.Default,
projectName,
projectName,
LanguageNames.VisualBasic,
filePath: null);
ApplySolutionChanges(s => s.AddProject(projectInfo));
return workspace.CurrentSolution.Projects.FirstOrDefault();
}
protected Project InitProject()
{
var host = GetRoslynCompositionHost();
workspace = new AdhocWorkspace(host);
return CreateDefaultProject();
}
}
Update:
Here's a Visual Studio project demonstrating both approaches:
https://drive.google.com/file/d/1LLuzy7yDFAE-v40I7EswECYQSthxheEf/view?usp=sharing

Query with distinct keyword and subquery not working in Hive with udf

Not working Query :
select lookup(city, state, tax,'addresslookup')
from (select distinct city, state, tax
from open_glory.addylookup) a
Working Query (without distinct):
select lookup(city, state, tax,'addresslookup')
from (select city, state, tax
from open_glory.addylookup) a
Any help would be appreciated.
UDF code:
Not working Query :
select lookup(city, state, tax,'addresslookup')
from (select distinct city, state, tax
from open_glory.addylookup) a
Working Query (without distinct):
select lookup(city, state, tax,'addresslookup')
from (select city, state, tax
from open_glory.addylookup) a
Any help would be appreciated.
UDF code:
public class Lookup extends GenericUDF {
private static String delimiter = "|";
private ConcurrentHashMap < String, HashMap < String, String >> fileMap = new ConcurrentHashMap < String, HashMap < String, String >> ();
protected String loggedInUser;
protected String loggedInApplication;
private transient GenericUDFUtils.StringHelper returnHelper;
private transient StringConverter[] stringConverter;
private static final Logger LOG = LoggerFactory.getLogger(Lookup.class.getName());
#Override
public ObjectInspector initialize(ObjectInspector[] arguments)
throws UDFArgumentException {
if (arguments.length < 2) {
throw new UDFArgumentLengthException(
"lookup takes 2 or more arguments");
}
stringConverter = new StringConverter[arguments.length];
for (int i = 0; i < arguments.length; i++) {
if (arguments[0].getCategory() != Category.PRIMITIVE) {
throw new UDFArgumentException(
"lookup only takes primitive types");
}
stringConverter[i] = new PrimitiveObjectInspectorConverter.StringConverter(
(PrimitiveObjectInspector) arguments[i]);
}
setLoggedInUser();
returnHelper = new GenericUDFUtils.StringHelper(
PrimitiveCategory.STRING);
LOG.info("initialize successful");
return PrimitiveObjectInspectorFactory.writableStringObjectInspector;
}
private void setLoggedInUser() {
if (loggedInUser == null) {
loggedInUser = SessionState.get().getUserName();
if (loggedInUser != null) {
int idx = loggedInUser.indexOf('.');
loggedInApplication = idx > -1 ? loggedInUser.substring(0, idx) : null;
}
}
}
private void initMap(String f) {
LOG.info("initMap involked");
if (loggedInApplication == null)
throw new NullPointerException(
"Unable to retrieve application name from user.");
String filePath = "/basepath/" + loggedInApplication.toLowerCase() + "/" + f +
".txt";
String line = null;
try {
LOG.info("filePath =" + filePath);
FileSystem fs = FileSystem.get(new Configuration());
FSDataInputStream in = fs.open(new Path(filePath));
BufferedReader br = new BufferedReader(new InputStreamReader( in ));
HashMap < String, String > map = new HashMap < String, String > ();
while ((line = br.readLine()) != null) {
// ignore comment lines
if (line.startsWith("#")) {
continue;
}
String[] strs = line.split("\t");
if (strs.length == 2) {
map.put(strs[0].toUpperCase().trim(), strs[1].trim());
} else if (strs.length > 2) {
map.put(getKey(strs), strs[strs.length - 1].trim());
}
}
fileMap.put(f, map);
br.close();
} catch (Exception e) {
LOG.error(e.getMessage(), e);
}
}
public Text getValue(String s, String f) {
initMap(f);
HashMap < String, String > map = fileMap.get(f);
LOG.info("getValue() fileMap =" + fileMap);
String v = map.get(s);
return v == null ? null : new Text(v);
}
#Override
public Object evaluate(DeferredObject[] arguments) throws HiveException {
String val = buildVal(arguments);
String lookupFile = (String) stringConverter[arguments.length - 1].convert(arguments[arguments.length - 1].get());
Text returnVal = getValue(val.toUpperCase(), lookupFile.toLowerCase());
return returnVal == null ? null : returnHelper.setReturnValue(returnVal.toString());
}
#Override
public String getDisplayString(String[] arg0) {
return "lookup()";
}
private String buildVal(DeferredObject[] arguments) throws HiveException {
StringBuilder builder = new StringBuilder();
int cnt = arguments.length - 1;
for (int i = 0; i < cnt; i++) {
builder.append((String) stringConverter[i].convert(arguments[i].get()));
if (i < cnt - 1) {
builder.append(delimiter);
}
}
return builder.toString();
}
private String getKey(String[] strs) {
StringBuilder builder = new StringBuilder();
int cnt = strs.length - 1;
for (int i = 0; i < cnt; i++) {
builder.append(strs[i].toUpperCase().trim());
if (i < cnt - 1) {
builder.append(delimiter);
}
}
return builder.toString();
}
}

SSAS Cube Metadata using SSIS script component with C# program

I am using script component in ssis with C# code using Microsoft.Analysisservices namespace to fetch the cube metadata. The code looks somewhat like this
using System;
using System.Data;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;
using Microsoft.AnalysisServices;
using System.Windows.Forms;
[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
//IDTSConnectionManager100 connMgr;
Server OLAPServer = new Server();
public override void AcquireConnections(object Transaction)
{
OLAPServer.Connect(this.Connections.OLAPConnection.ConnectionString);
}
public override void PreExecute()
{
base.PreExecute();
/*
Add your code here for preprocessing or remove if not needed
*/
}
public override void PostExecute()
{
base.PostExecute();
/*
Add your code here for postprocessing or remove if not needed
You can set read/write variables here, for example:
Variables.MyIntVar = 100
*/
}
public override void CreateNewOutputRows()
{
IDTSVariables100 vars = null;
string OLAPDBName;
VariableDispenser.LockOneForRead("OLAPDBName", ref vars);
Database OLAPDB;
OLAPDBName = vars[0].Value.ToString();
try
{
OLAPDB = OLAPServer.Databases.GetByName(OLAPDBName);
}
catch
{
return;
}
// loop through cubes
CubeCollection Cubes = OLAPDB.Cubes;
MeasureGroupCollection Mgroups;
CubeDimensionCollection Dimensions;
MeasureGroupDimensionCollection MgroupDims;
DimensionAttributeCollection Attributes;
foreach (Cube cb in Cubes)
{
//Test for one Measure Group
//MeasureGroup mgroup = Mgroups.GetByName("Inward Exposure");
Mgroups = cb.MeasureGroups;
// all dimensions associated with that Measure Group
// loop through Measure Groups
foreach (MeasureGroup mg in Mgroups)
{
// loop though all cube dimensions
Dimensions = cb.Dimensions;**strong text**
foreach (CubeDimension dim in Dimensions)
{
bool CanBeAnalysed = false;**strong text**
// loop through dimensions and see if dimension exists in mgroupDims (ie check if it can be analysed)
MgroupDims = mg.Dimensions;
foreach (MeasureGroupDimension mgd in MgroupDims)
{
if (mgd.CubeDimension == dim)
{
CanBeAnalysed = true;
break;
}
}
// loop through each Measure and Attribute a
String DimName = dim.Name;
bool DimVisible = dim.Visible;
String MgroupName = mg.Name;
String CubeName = cb.Name;
String MeasureExpression;
String Description;
// for every attribute in dimension
Attributes = dim.Dimension.Attributes;
foreach (DimensionAttribute Attr in Attributes)
{
String AttrName = Attr.Name;
bool AttrVisible = Attr.AttributeHierarchyVisible;
String AttrNameColumn = Attr.NameColumn.ToString();
String AttributeRelationship = Attr.AttributeRelationships.ToString();
// get every measure in measuregroup
foreach (Measure m in mg.Measures)
{
String MeasureName = m.Name.ToString();
bool MeasureVisible = m.Visible;
String MeasureNameColumn = m.Source.ToString();
if (m.MeasureExpression != null)
{
// MessageBox.Show(m.MeasureExpression.ToString());
MeasureExpression = m.MeasureExpression.ToString();
}
else
{
// MessageBox.Show(m.MeasureExpression.ToString());
MeasureExpression = " " ;
}
if (m.Description != null)
{
// MessageBox.Show(m.MeasureExpression.ToString());
Description = m.Description.ToString();
}
else
{
// MessageBox.Show(m.MeasureExpression.ToString());
Description = " ";
}
Output0Buffer.AddRow();
Output0Buffer.OLAPDBName = OLAPDBName;
Output0Buffer.CubeName = CubeName;
Output0Buffer.DimensionName = DimName;
Output0Buffer.DimensionVisible = DimVisible;
Output0Buffer.AttrDDSColumn = AttrNameColumn;
Output0Buffer.AttrName = AttrName;
Output0Buffer.AttrVisible = AttrVisible;
Output0Buffer.MeasureGroupName = MgroupName;
Output0Buffer.MeasureName = MeasureName;
Output0Buffer.MeasureVisible = MeasureVisible;
Output0Buffer.MeasureDDSColumn = MeasureNameColumn;
Output0Buffer.IsAnalysable = CanBeAnalysed;
Output0Buffer.MeasureExpression = MeasureExpression;
Output0Buffer.Description = Description;
Output0Buffer.AttributeRelationship = AttributeRelationship;
}
}
} // end of Cube Dim Loop
} // end of Measure Group loop
} // end of cube loop
}
}
I was successful in getting the cube metadata with the above code.However, i am stuck at getting the metadata of the perspective cube and the Relationships of the measure groups i.e whether the measure groups are many-many. Any help is very much appreciated.
Here is some code for detecting dimension relationships including many-to-many. See the GetDimensionUsage function:
https://raw.githubusercontent.com/BIDeveloperExtensions/bideveloperextensions/master/SSAS/PrinterFriendlyDimensionUsage.cs
Here is some code around navigating perspectives:
https://raw.githubusercontent.com/BIDeveloperExtensions/bideveloperextensions/master/SSAS/TriStatePerspectivesPlugin.cs
Start reading around the following line:
if (perspective.MeasureGroups.Contains(mg.Name))

How to use GroupFormatter with ObjectListView control

I cannot seem to find anywhere, any examples on how to make use of the GroupFormatter delegate to allow me to add footers to my groups when using the ObjectListView control.
Does anyone have any examples that could demonstrate this? I want to remove the text from the group header and add a footer (different text per footer). As well as changing font, etc.
Any examples would be very helpful.
You can analyze the code for the
public void MakeGroupies<T>(T[] values, string[] descriptions, object[] images, string[] subtitles, string[] tasks)
method of the ObjectListView class. That explicitly sets the GroupKeyGetter, GroupKeyToTitleConverter and GroupFormatter property delegates.
This is C# but your VB adaptation should be straightforward. I am using this small test class as the object type to bind to the list view.
public class TestClass
{
private readonly string _s;
private readonly float _f;
public TestClass( string p1, float p2 )
{
this._s = p1;
this._f = p2;
}
[OLVColumn(DisplayIndex = 1, Name="S", Title="String")]
public string S {get {return this._s;}}
[OLVColumn( DisplayIndex = 2, Name = "F", Title = "Float" )]
public float F {get {return this._f;}}
}
So as not to manually define column traits I am using attributes inside the bound object and a
BrightIdeasSoftware.Generator.GenerateColumns( this.olv, typeof( TestClass ) );
call in the form/user control where I am using the list view. In fact here is the method that completely isolates ObjectListView configuration:
void SetData( TestClass[] objects )
{
// build list columns
Generator.GenerateColumns( this.olv, typeof( TestClass ) );
// use groups and make current column the priimary sort column
this.olv.ShowGroups = true;
this.olv.SortGroupItemsByPrimaryColumn = false;
// loop through columns and set properties
foreach( OLVColumn col in this.olv.Columns )
{
col.Groupable = true;
col.Sortable = true;
if( col.Name == "F" )
{
col.MakeGroupies<float>( new float[] { 10f, 100f, 1000f }, new string[] { "<10", "10-100", "100-1000", ">1000" } );
}
else if( col.Name == "S" )
{
col.UseInitialLetterForGroup = false;
//
col.GroupKeyGetter = ( obj ) =>
{
TestClass tc = (TestClass)obj;
switch( char.ToLower( tc.S[0] ) )
{
case 'a':
case 'e':
case 'i':
case 'o':
case 'u': return true;
default: return false;
}
};
//
col.GroupKeyToTitleConverter = ( o ) => { bool b = (bool)o; return b ? "vowel" : "consonant"; };
//
col.GroupFormatter = ( /*OLVGroup*/ group, /*GroupingParameters*/ parms ) =>
{
string s = string.Format ("{0} {1}", group.GroupId, group.Id);
//group.BottomDescription = "BottomDescription: " + s;
//group.TopDescription = "TopDescription: " + s;
group.Footer = "Footer: " + s;
};
}
}
//
this.olv.RebuildColumns();
//
this.olv.SetObjects( objects );
}
You will definitely have one different footer per each group.

Rewriting from MonoTouch Application to MonoDroid

I'm going to rewrite the application from Monotouh to Monodroid application for android. Correct me if I'm wrong. The logic remains the same as in MonoTouch or change anything? If something changes, please tell me, what?
As far as I understand, only GIU changes. Thanks in advance!
So, this is my code where i call data from my server:
namespace Mobile{
public static class SiteHelper
{
public static string DbPath = Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.Personal), "Sql_1.4.sqlite");
public const string TempDbPath = "./Sql.sqlite";
public static UIView View { get; set; }
public static BaseController Controller { get; set; }
private static event NIHandler _noInternetHandler;
private static bool _noInternetShoved = false;
public static string SiteDomain = "http://mysite.com"; //files which connecting to the DB on server (.asx files)
private delegate void NIHandler ();
public static XDocument DoRequest (string Request)
{
if (_noInternetHandler != null) {
foreach (var del in _noInternetHandler.GetInvocationList()) {
_noInternetHandler -= del as NIHandler;
}
}
if (Controller != null)
_noInternetHandler += new NIHandler (Controller.PushThenNoInternet);
string CryptoString = "";
string Language = "ru";
using (MD5 md5Hash = MD5.Create()) {
string hashKey = Guid.NewGuid ().ToString ().Substring (0, 4);
CryptoString = Request + (Request.Contains ("?") ? "&" : "?") + "hash=" + GetMd5Hash (
md5Hash,
"myprogMobhash_" + hashKey
) + "&hashKey=" + hashKey + "&language=" + Language;
UIActivityIndicatorView _preloader = null;
if (Controller != null) {
Controller.InvokeOnMainThread (delegate() {
_preloader = new UIActivityIndicatorView (UIActivityIndicatorViewStyle.Gray);
if (View != null && Request.IndexOf ("login.ashx") == -1
&& Request.IndexOf ("yandex") == -1
&& Request.IndexOf ("GetDialogMessages") == -1) {
lock (_preloader) {
if (_preloader != null && !_preloader.IsAnimating)
_preloader.HidesWhenStopped = true;
_preloader.Frame = new RectangleF (150, 170, 30, 30);
_preloader.Transform = MonoTouch.CoreGraphics.CGAffineTransform.MakeScale ((float)1.3, (float)1.3);
_preloader.StartAnimating ();
View.Add (_preloader);
}
}
});
}
/*ctx.GetText(Resource.String.SiteAddress)*/
Stream Stream = null;
try {
HttpWebRequest request = new HttpWebRequest (new Uri (SiteDomain + "/FolderWithFiles/" + CryptoString));
request.Timeout = 8000;
Stream = request.GetResponse ().GetResponseStream ();
_noInternetShoved = false;
if (_noInternetHandler != null)
_noInternetHandler -= new NIHandler (Controller.PushThenNoInternet);
} catch (WebException) {
if (_noInternetHandler != null)
_noInternetHandler.Invoke ();
var resp = new XDocument (new XElement ("Response",
new XElement ("status", "error"),
new XElement ("error", "Отсутствует интернет"))
);
return resp;
}
StreamReader Sr = new StreamReader (Stream);
string Resp = Sr.ReadToEnd ();
XDocument Response = XDocument.Parse (Resp.Substring (0, Resp.IndexOf ("<html>") == -1 ? Resp.Length : Resp.IndexOf ("<!DOCTYPE html>")));
string Hash = Response.Descendants ().Where (x => x.Name == "hash")
.FirstOrDefault ().Value;
string HashKey = Response.Descendants ().Where (x => x.Name == "hashKey")
.FirstOrDefault ().Value;
Sr.Close ();
Stream.Close ();
if (Controller != null && _preloader != null) {
Controller.InvokeOnMainThread (delegate() {
lock (_preloader) {
_preloader.StopAnimating ();
_preloader.RemoveFromSuperview ();
}
});
}
if (VerifyMd5Hash (
md5Hash,
"mobileSitehash_" + HashKey,
Hash
))
return Response;
else
throw new Exception ();
}
}
public static XDocument DoWriteFileRequest (string Request, byte[] file)
{
string CryptoString = "";
string Language = "ru";
using (MD5 md5Hash = MD5.Create()) {
string hashKey = Guid.NewGuid ().ToString ().Substring (0, 4);
CryptoString = Request + (Request.Contains ("?") ? "&" : "?") + "hash=" + GetMd5Hash (
md5Hash,
"mobileMobhash_" + hashKey
) + "&hashKey=" + hashKey + "&language=" + Language;
HttpWebRequest Req = (HttpWebRequest)WebRequest.Create (SiteDomain + "/misc/mobile/" + CryptoString);
Req.Method = "POST";
Stream requestStream = Req.GetRequestStream ();
requestStream.Write (file, 0, file.Length);
requestStream.Close ();
Stream Stream = Req.GetResponse ().GetResponseStream ();
StreamReader Sr = new StreamReader (Stream);
string Resp = Sr.ReadToEnd ();
XDocument Response = XDocument.Parse (Resp);
string Hash = Response.Descendants ().Where (x => x.Name == "hash")
.FirstOrDefault ().Value;
string HashKey = Response.Descendants ().Where (x => x.Name == "hashKey")
.FirstOrDefault ().Value;
Sr.Close ();
Stream.Close ();
if (VerifyMd5Hash (
md5Hash,
"mobileSitehash_" + HashKey,
Hash
))
return Response;
else
throw new Exception ();
}
}
public static string GetMd5Hash (MD5 md5Hash, string input)
{
// Convert the input string to a byte array and compute the hash.
byte[] data = md5Hash.ComputeHash (Encoding.UTF8.GetBytes (input));
// Create a new Stringbuilder to collect the bytes
// and create a string.
StringBuilder sBuilder = new StringBuilder ();
// Loop through each byte of the hashed data
// and format each one as a hexadecimal string.
for (int i = 0; i < data.Length; i++) {
sBuilder.Append (data [i].ToString ("x2"));
}
// Return the hexadecimal string.2
return sBuilder.ToString ();
}
//Geting the info for my app
public static List<PackageListModel> GetUserPackages (int UserID)
{
List<PackageListModel> Events = new List<PackageListModel> ();
string Req = "SomeFile.ashx?UserID=" + UserID;
XDocument XmlAnswer = DoRequest (Req);
if (XmlAnswer.Descendants ("status").First ().Value == "ok") {
foreach (var el in XmlAnswer.Descendants ("Response").First ().Descendants().Where(x=>x.Name == "Event")) {
PackageListModel Event = null;
Event = new PackageListModel ()
{
ID = int.Parse(el.Attribute("ID").Value),
Title = el.Element("Title").Value,
Date = el.Element("Date").Value,
Price = el.Element("Price").Value,
ImageUrl = el.Element("ImageUrl").Value,
Location = el.Element("Location").Value
};
Events.Add (Event);
}
}
return Events;
}
//Получить пользовательские поездки
public static List<TransporterListModel> GetUserTransporters (int UserID)
{
List<TransporterListModel> Events = new List<TransporterListModel> ();
string Req = "SomeFile.ashx?UserID=" + UserID;
XDocument XmlAnswer = DoRequest (Req);
if (XmlAnswer.Descendants ("status").First ().Value == "ok") {
foreach (var el in XmlAnswer.Descendants ("Response").First ().Descendants().Where(x=>x.Name == "Event")) {
TransporterListModel Event = null;
Event = new TransporterListModel ()
{
ID = int.Parse(el.Attribute("ID").Value),
Date = el.Element("Date").Value,
Price = el.Element("Price").Value,
TransportsStr = el.Element("Transports").Value,
Location = el.Element("Location").Value
};
Events.Add (Event);
}
}
return Events;
}
}
}
}
I think you should read this.
In brief - you can reuse application logic that not depends on platform-specific parts, so working with database/server can be shared between MonoTouch and Mono for Android.