cannot extract triangulated geometry from IFC using xBIM - c#

I am trying to extract triangulated meshes of all geometries in an IFC file using this code
I have already loaded the model with ifcstore.open...
var context = new Xbim3DModelContext(model);
context.CreateContext();
//var geometries = context.ShapeGeometries();
//XbimShapeTriangulation mesh = null;
var geometries = context.ShapeInstances();
foreach (var g in geometries)
{
//var ms = new MemoryStream(((IXbimShapeGeometryData)g).ShapeData);
//var br = new BinaryReader(ms);
//mesh = br.ReadShapeTriangulation();
////mesh = mesh.Transform(((XbimShapeInstance)g).Transformation);
//Console.WriteLine(g.Format + " | " + g.ShapeLabel);
//Console.WriteLine(mesh.Faces.Count() + " | " + mesh.Vertices.Count());
var tri = context.ShapeGeometryMeshOf(g);
Console.WriteLine(tri.TriangleIndexCount + " | " + tri.ToString());
}
If I'm using the commented part of the above code, the mesh returns without being triangulated. The format is PolyHedronBinary.
If I use the context.ShapeGeometryMeshOf() method, there is an exception thrown : invalid geometry type .
Please help me with triangulating the geometries of the model.
I have also read about the method "read" in XbimWindowsUI/Xbim.Presentation/MeshGeometry3DExtensions.cs, but I am not able to figure out what I have to pass as the "m3d" parameter ?
/// <summary>
/// Reads a triangulated model from an array of bytes and adds the mesh
/// to the current state
/// </summary>
/// <param name="m3D"></param>
/// <param name="mesh">byte array of XbimGeometryType.PolyhedronBinary Data</param>
/// <param name="transform">Transforms the mesh to the new position if not null</param>
public static void Read(
this MeshGeometry3D m3D,
byte[] mesh,
XbimMatrix3D? transform = null)
It will be great if anybody could provide/ point me to example usage of this method.
I need to rebuild the IFC model in Unity and hence I need the triangulated mesh data.
Also suggest if there is anyway to achieve this more efficiently and/or in a simpler way!

I used some code from the xBIM GIT repository for this:
IfcStore model = IfcStore.Open(ifcFileName);
if (model.GeometryStore.IsEmpty)
{
var context = new Xbim3DModelContext(model);
context.CreateContext();
}
foreach (var ifcElement in model.Instances.OfType<IfcElement>())
{
XbimModelPositioningCollection modelPositions = new XbimModelPositioningCollection();
short userDefinedId = 0;
model.UserDefinedId = userDefinedId;
modelPositions.AddModel(model.ReferencingModel);
if (model.IsFederation)
{
foreach (var refModel in model.ReferencedModels)
{
refModel.Model.UserDefinedId = ++userDefinedId;
var v = refModel.Model as IfcStore;
if (v != null)
modelPositions.AddModel(v.ReferencingModel);
}
}
var modelBounds = modelPositions.GetEnvelopeInMeters();
var p = modelBounds.Centroid();
var modelTranslation = new XbimVector3D(-p.X, -p.Y, -p.Z);
var oneMeter = model.ModelFactors.OneMetre;
var translation = XbimMatrix3D.CreateTranslation(modelTranslation * oneMeter);
var scaling = XbimMatrix3D.CreateScale(1 / oneMeter);
var transform = translation * scaling;
var mat = GetStyleFromXbimModel(ifcElement);
var m = GetGeometry(ifcElement, transform, mat);
var myRetTuple = WriteTriangles(m);
}`
the WriteTriangle-Function:
private Tuple<Point3D> WriteTriangles(IXbimMeshGeometry3D wpfMeshGeometry3D)
{
var axesMeshBuilder = new MeshBuilder();
var pos = wpfMeshGeometry3D.Positions.ToArray();
var nor = wpfMeshGeometry3D.Normals.ToArray();
var areasum = 0.00;
for (var i = 0; i < wpfMeshGeometry3D.TriangleIndices.Count; i += 3)
{
var p1 = wpfMeshGeometry3D.TriangleIndices[i];
var p2 = wpfMeshGeometry3D.TriangleIndices[i + 1];
var p3 = wpfMeshGeometry3D.TriangleIndices[i + 2];
if (nor[p1] == nor[p2] && nor[p1] == nor[p3]) // same normals
{
var cnt = FindCentroid(new[] { pos[p1], pos[p2], pos[p3] });
CreateNormal(cnt, nor[p1], axesMeshBuilder);
}
else
{
CreateNormal(pos[p1], nor[p1], axesMeshBuilder);
CreateNormal(pos[p2], nor[p2], axesMeshBuilder);
CreateNormal(pos[p3], nor[p3], axesMeshBuilder);
}
var point1 = new Point3D(pos[p1].X, pos[p1].Y, pos[p1].Z);
var point2 = new Point3D(pos[p2].X, pos[p2].Y, pos[p2].Z);
var point3 = new Point3D(pos[p3].X, pos[p3].Y, pos[p3].Z);
}
return Tuple.Create(point1, point2, point3);
}
and some additional methods from xBIM GeometryHandler:
private static XbimPoint3D FindCentroid(XbimPoint3D[] p)
{
double x = 0;
double y = 0;
double z = 0;
var n = 0;
foreach (var item in p)
{
x += item.X;
y += item.Y;
z += item.Z;
n++;
}
if (n <= 0)
return new XbimPoint3D(x, y, z);
x /= n;
y /= n;
z /= n;
return new XbimPoint3D(x, y, z);
}
private static void CreateNormal(XbimPoint3D pnt, XbimVector3D vector3D, MeshBuilder axesMeshBuilder)
{
var cnt = new Point3D() { X = pnt.X, Y = pnt.Y, Z = pnt.Z };
var path = new List<Point3D> { cnt };
const double nrmRatio = .2;
path.Add(
new Point3D(
cnt.X + vector3D.X * nrmRatio,
cnt.Y + vector3D.Y * nrmRatio,
cnt.Z + vector3D.Z * nrmRatio
));
const double lineThickness = 0.001;
axesMeshBuilder.AddTube(path, lineThickness, 9, false);
}
private static WpfMeshGeometry3D GetGeometry(IPersistEntity selection, XbimMatrix3D modelTransform, Material mat)
{
var tgt = new WpfMeshGeometry3D(mat, mat);
tgt.BeginUpdate();
using (var geomstore = selection.Model.GeometryStore)
{
using (var geomReader = geomstore.BeginRead())
{
foreach (var shapeInstance in geomReader.ShapeInstancesOfEntity(selection).Where(x => x.RepresentationType == XbimGeometryRepresentationType.OpeningsAndAdditionsIncluded))
{
IXbimShapeGeometryData shapegeom = geomReader.ShapeGeometry(shapeInstance.ShapeGeometryLabel);
if (shapegeom.Format != (byte)XbimGeometryType.PolyhedronBinary)
continue;
var transform = shapeInstance.Transformation * modelTransform;
tgt.Add(
shapegeom.ShapeData,
shapeInstance.IfcTypeId,
shapeInstance.IfcProductLabel,
shapeInstance.InstanceLabel,
transform,
(short)selection.Model.UserDefinedId
);
}
}
}
tgt.EndUpdate();
return tgt;
}
private static DiffuseMaterial GetStyleFromXbimModel(IIfcProduct item, double opacity = 1)
{
var context = new Xbim3DModelContext(item.Model);
var productShape = context.ShapeInstancesOf(item)
.Where(s => s.RepresentationType != XbimGeometryRepresentationType.OpeningsAndAdditionsExcluded)
.ToList();
var wpfMaterial = GetWpfMaterial(item.Model, productShape.Count > 0 ? productShape[0].StyleLabel : 0);
var newmaterial = wpfMaterial.Clone();
((DiffuseMaterial)newmaterial).Brush.Opacity = opacity;
return newmaterial as DiffuseMaterial;
}
private static Material GetWpfMaterial(IModel model, int styleId)
{
var sStyle = model.Instances[styleId] as IIfcSurfaceStyle;
var wpfMaterial = new WpfMaterial();
if (sStyle != null)
{
var texture = XbimTexture.Create(sStyle);
texture.DefinedObjectId = styleId;
wpfMaterial.CreateMaterial(texture);
return wpfMaterial;
}
var defautMaterial = ModelDataProvider.DefaultMaterials;
Material material;
if (defautMaterial.TryGetValue(model.GetType().Name, out material))
{
return material;
}
var color = new XbimColour("red", 1, 1, 1);
wpfMaterial.CreateMaterial(color);
return wpfMaterial;
}

Related

CSharp Generate polygons from a set of intersecting lines

https://gis.stackexchange.com/questions/58245/generate-polygons-from-a-set-of-intersecting-lines
https://i.stack.imgur.com/UUyHF.png
https://i.stack.imgur.com/3ClRI.png
I want to find the bounding polygon like this link.
I'm using C# nettopologysuite like the jts library shown in this link, but the polygon I want doesn't come out.
How can I extract polygons?
Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
Database db = doc.Database;
Editor ed = doc.Editor;
PromptEntityOptions pEntOpt1 = new PromptEntityOptions("Outter Boundary");
pEntOpt1.SetRejectMessage("is Not Polyline");
pEntOpt1.AddAllowedClass(typeof(Polyline), true);
PromptEntityResult pEntRes1 = ed.GetEntity(pEntOpt1);
string typeName = RXObject.GetClass(typeof(Polyline)).DxfName;
TypedValue[] tv = new TypedValue[1] { new TypedValue((int)DxfCode.Start, typeName) };
SelectionFilter sf = new SelectionFilter(tv);
PromptSelectionResult pSelectRes = ed.GetSelection(sf);
if (pSelectRes.Status != PromptStatus.OK)
return;
ObjectId boudaryPlineId = pEntRes1.ObjectId;
ObjectId[] innerPlineids = pSelectRes.Value.GetObjectIds();
ObjectIdCollection innerBoundaries = new ObjectIdCollection(innerPlineids);
try
{
using (doc.LockDocument())
{
using (Transaction tr = db.TransactionManager.StartTransaction())
{
Polygonizer polygonizer = new Polygonizer();
GeometryFactory gf = new GeometryFactory();
Polyline boundaryPline = tr.GetObject(boudaryPlineId, OpenMode.ForWrite) as Polyline;
Coordinate[] coords = new Coordinate[boundaryPline.NumberOfVertices + 1];
for (int j = 0; j < boundaryPline.NumberOfVertices; j++)
{
Point3d pos = boundaryPline.GetPoint3dAt(j);
coords[j] = new Coordinate(pos.X, pos.Y);
}
coords[boundaryPline.NumberOfVertices] = new Coordinate(boundaryPline.StartPoint.X, boundaryPline.StartPoint.Y);
Polygon pg = gf.CreatePolygon(coords);
List<Geometry> plines = new List<Geometry>();
foreach (ObjectId indexid in innerBoundaries)
{
Polyline indexPline = tr.GetObject(indexid, OpenMode.ForWrite) as Polyline;
Coordinate[] coords2 = new Coordinate[indexPline.NumberOfVertices];
for (int i = 0; i < indexPline.NumberOfVertices; i++)
{
Point3d pos = indexPline.GetPoint3dAt(i);
coords2[i] = new Coordinate(pos.X, pos.Y);
}
LineString ls1 = new LineString(coords2);
polygonizer.Add(ls1);
}
ICollection<Geometry> test = polygonizer.GetPolygons();
foreach (Geometry polygon in test)
{
// to do
}
tr.Commit();
}
}
}
catch
{
}
outter Boundary
inner Boundary
The Red Polygon I want to find
This is my second question in English, so please understand the lack of expression.
-------------- After applying the answer below --------------
private List<NetGeometry> GetPolygons(Transaction tr, List<LineString> lineStrings)
{
List<NetGeometry> polygons = new List<NetGeometry>();
Polygonizer polygonizer = new Polygonizer(false);
GeometryFactory gf = new GeometryFactory(new PrecisionModel(10000));
var noder = new SnapRoundingNoder(new PrecisionModel(10000)); // adjust PrecisionModel to your needs, must be fixed.
noder.ComputeNodes(lineStrings.Select(s => (ISegmentString)new NodedSegmentString(s.Coordinates, s)).ToList());
var noded = noder.GetNodedSubstrings();
polygonizer.Add(noded.Select(n => (Geometry)gf.CreateLineString(n.Coordinates)).ToList());
//for ( int i = 0; i < lineStrings.Count; i++)
//{
// polygonizer.Add(lineStrings[i]);
//}
ICollection<NetGeometry> result = polygonizer.GetPolygons();
foreach (NetGeometry index in result)
{
if ( index is Polygon pg)
{
polygons.Add(pg);
}
}
return polygons;
}
Results after application
All input geometries to Polygonizer should be LineStrings.
The whole input set of LineStrings must be fully noded:
var noder = new SnapRoundingNoder(new PrecisionModel(1000)); // adjust PrecisionModel to your needs, must be fixed.
noder.ComputeNodes(lines.Select(s => (ISegmentString)new NodedSegmentString(s.Coordinates, s)).ToList());
var noded = noder.GetNodedSubstrings();
polygonizer.Add(noded.Select(n => (Geometry)gf.CreateLineString(n.Coordinates)).ToList());

Unity c sharp - changing the resolution aspect ratio according to screen size through code

Hello I want to resize the screen aspect ratio according to the screen size through code but I couldn't find a way to do that:
public class ResolutionFixer : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
var res = Screen.currentResolution;
float ratio = (float)res.width/res.height;
print(ratio);
//change the game's ratio aspect to the give ratio here
}
Note: tried using:
Screen.SetResolution(res.width, res.height, true);
but it didn't work
According to this, I think you cannot emulate Screen.SetResolution() in Editor, Try building it and see if it works
Resizing the Game View through code is possible with some reflection.
This works for me:
using UnityEditor;
using System.Reflection;
public static class GameViewUtils {
public enum GameViewSizeType {
AspectRatio,
FixedResolution
}
private static readonly object gameViewSizesInstance;
private static readonly MethodInfo getGroup;
static GameViewUtils() {
var sizesType = typeof(Editor).Assembly.GetType("UnityEditor.GameViewSizes");
var singleType = typeof(ScriptableSingleton<>).MakeGenericType(sizesType);
var instanceProp = singleType.GetProperty("instance");
getGroup = sizesType.GetMethod("GetGroup");
gameViewSizesInstance = instanceProp.GetValue(null, null);
}
public static void AddCustomSize(GameViewSizeType viewSizeType, GameViewSizeGroupType sizeGroupType, int width, int height, string resolutionName) {
var group = GetGroup(sizeGroupType);
var addCustomSize = getGroup.ReturnType.GetMethod("AddCustomSize"); // or group.GetType().
var assembly = Assembly.Load("UnityEditor.dll");
var gameViewSize = assembly.GetType("UnityEditor.GameViewSize");
var gameViewSizeType = assembly.GetType("UnityEditor.GameViewSizeType");
var ctor = gameViewSize.GetConstructor(new [] {
gameViewSizeType,
typeof(int),
typeof(int),
typeof(string)
});
var newSize = ctor.Invoke(new object[] { (int)viewSizeType, width, height, resolutionName });
addCustomSize.Invoke(group, new [] { newSize });
}
public static void SetSize(int index) {
var gvWndType = typeof(Editor).Assembly.GetType("UnityEditor.GameView");
var selectedSizeIndexProp = gvWndType.GetProperty("selectedSizeIndex",
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
var gvWnd = EditorWindow.GetWindow(gvWndType);
selectedSizeIndexProp.SetValue(gvWnd, index, null);
}
public static bool SizeExists(GameViewSizeGroupType sizeGroupType, string text) {
return FindSize(sizeGroupType, text) != -1;
}
public static int FindSize(GameViewSizeGroupType sizeGroupType, string text) {
// GameViewSizes group = gameViewSizesInstance.GetGroup(sizeGroupType);
// string[] texts = group.GetDisplayTexts();
// for loop...
var group = GetGroup(sizeGroupType);
var getDisplayTexts = group.GetType().GetMethod("GetDisplayTexts");
var displayTexts = getDisplayTexts.Invoke(group, null) as string[];
for(int i = 0; i < displayTexts.Length; i++) {
string display = displayTexts[i];
// the text we get is "Name (W:H)" if the size has a name, or just "W:H" e.g. 16:9
// so if we're querying a custom size text we substring to only get the name
// You could see the outputs by just logging
// Debug.Log(display);
int pren = display.IndexOf('(');
if (pren != -1)
display = display.Substring(0, pren - 1); // -1 to remove the space that's before the prens. This is very implementation-dependant
if (display == text)
return i;
}
return -1;
}
public static bool SizeExists(GameViewSizeGroupType sizeGroupType, int width, int height) {
return FindSize(sizeGroupType, width, height) != -1;
}
public static int FindSize(GameViewSizeGroupType sizeGroupType, int width, int height) {
// goal:
// GameViewSizes group = gameViewSizesInstance.GetGroup(sizeGroupType);
// int sizesCount = group.GetBuiltinCount() + group.GetCustomCount();
// iterate through the sizes via group.GetGameViewSize(int index)
var group = GetGroup(sizeGroupType);
var groupType = group.GetType();
var getBuiltinCount = groupType.GetMethod("GetBuiltinCount");
var getCustomCount = groupType.GetMethod("GetCustomCount");
int sizesCount = (int)getBuiltinCount.Invoke(group, null) + (int)getCustomCount.Invoke(group, null);
var getGameViewSize = groupType.GetMethod("GetGameViewSize");
var gvsType = getGameViewSize.ReturnType;
var widthProp = gvsType.GetProperty("width");
var heightProp = gvsType.GetProperty("height");
var indexValue = new object[1];
for(int i = 0; i < sizesCount; i++) {
indexValue[0] = i;
var size = getGameViewSize.Invoke(group, indexValue);
int sizeWidth = (int)widthProp.GetValue(size, null);
int sizeHeight = (int)heightProp.GetValue(size, null);
if (sizeWidth == width && sizeHeight == height)
return i;
}
return -1;
}
private static object GetGroup(GameViewSizeGroupType type) {
return getGroup.Invoke(gameViewSizesInstance, new object[] { (int)type });
}
}
Based on the answers in this thread: http://answers.unity.com/answers/1791883/view.html

Shuffling list of competitors, each month different competitor

for my friends sportscompetition, each player has to play 1 game a month against an other player. Now if i have a list of 20 players or so its not that hard to randomize the first month so i have 10 matches.
All the months after that though i'm not sure how to get the randomizer working so they won't be matched against a player they have played against.
Right now i made an sql database with Players(Name, (int)Id, Email) , Matches(Id, Player1ID, Player2ID)
I'm thinking for a randomize of the list and checking if each match doesn't contain 2 id's from a match in the database. And if 1 match does, redo the entire randomize of that month.
But i'm not sure if thats the best way.
This is what i have so far, i have yet to test it after i add some 'leden' and 'matches' to my database.
private void MaakMatchen(Maand maand)
{
List<Lid> leden = new List<Lid>();
var dbManager = new Manager();
using (var conGildenhof = dbManager.GetConnection())
{
using (var comLeden = conGildenhof.CreateCommand())
{
comLeden.CommandType = CommandType.Text;
comLeden.CommandText = "select * from dbo.Leden";
conGildenhof.Open();
using (var alleleden = comLeden.ExecuteReader())
{
Int32 voornaamPos = alleleden.GetOrdinal("Voornaam");
Int32 familienaamPos = alleleden.GetOrdinal("Familienaam");
Int32 LidNummerPos = alleleden.GetOrdinal("LidNummer");
while (alleleden.Read())
{
leden.Add(new Classes.Lid(alleleden.GetString(voornaamPos), alleleden.GetString(familienaamPos), alleleden.GetInt32(LidNummerPos)));
}
leden = Randomize(leden);
}
}
using (var comInsert = conGildenhof.CreateCommand())
{
comInsert.CommandType = CommandType.Text;
comInsert.CommandText = "Insert into dbo.Matches (Lid1Id, Lid2Id, Maand) values (#lid1, #lid2, #maand)";
var parLid1 = comInsert.CreateParameter();
parLid1.ParameterName = "#lid1";
comInsert.Parameters.Add(parLid1);
var parLid2 = comInsert.CreateParameter();
parLid2.ParameterName = "#lid2";
comInsert.Parameters.Add(parLid2);
var parMaand = comInsert.CreateParameter();
parMaand.ParameterName = "#maand";
comInsert.Parameters.Add(parMaand);
int lengte = leden.Count();
for (int i = 0; i < lengte; i = i + 2)
{
parLid1.Value = leden[i].LidNummer;
parLid2.Value = leden[i + 1].LidNummer;
parMaand.Value = (int)maand;
comInsert.ExecuteNonQuery();
}
}
}
}
private List<Lid> Randomize(List<Lid> leden)
{
for (int i=0;i<100;i++)
{
leden = Shuffle(leden);
}
int temp = CheckUp(leden);
while (temp != 100)
{
leden = Shuffle(leden, temp);
temp = CheckUp(leden);
}
return leden;
}
private List<Lid> Shuffle(List<Lid> leden)
{
Random rnd = new Random();
int a = rnd.Next(1, leden.Count() + 1);
int b = rnd.Next(1, leden.Count() + 1);
var temp = new Lid();
temp = leden[a];
leden[a] = leden[b];
leden[b] = temp;
return leden;
}
private List<Lid> Shuffle(List<Lid> leden, int id)
{
Random rnd = new Random();
int a = rnd.Next(1, leden.Count() + 1);
int b = id;
var temp = new Lid();
temp = leden[a];
leden[a] = leden[b];
leden[b] = temp;
return leden;
}
private int CheckUp(List<Lid> leden)
{
int lengte = leden.Count();
List<Matches> matches = new List<Matches>();
var dbManager = new Manager();
using (var conGildenhof = dbManager.GetConnection())
{
using (var comMatches = conGildenhof.CreateCommand())
{
comMatches.CommandType = CommandType.Text;
comMatches.CommandText = "select * from dbo.Matches";
conGildenhof.Open();
using (var allematches = comMatches.ExecuteReader())
{
Int32 lid1Pos = allematches.GetOrdinal("Lid1Id");
Int32 lid2Pos = allematches.GetOrdinal("Lid2Id");
Int32 maandPos = allematches.GetOrdinal("Maand");
while (allematches.Read())
{
matches.Add(new Classes.Matches(allematches.GetInt32(lid1Pos), allematches.GetInt32(lid2Pos), (Maand)allematches.GetInt32(maandPos)));
}
}
}
}
for (int i=0;i<lengte;i=i+2)
{
foreach (Matches match in matches)
{
if (leden[i].LidNummer == match.Lid1Id)
{
if (leden[i + 1].LidNummer == match.Lid2Id)
return leden[i].LidNummer;
}
if (leden[i].LidNummer == match.Lid2Id)
{
if (leden[i + 1].LidNummer == match.Lid1Id)
return leden[i].LidNummer;
}
}
}
return 100;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
var maand = new int();
int.TryParse(TextBoxMaand.Text, out maand);
if (maand == 0)
TextBoxMaand.Text = "GETAL!";
else
{
MaakMatchen((Maand)maand);
}
}
I would shuffle the players first and create the matches in a second iteration
List<Player> players = GetPlayers();
Random _rnd = new Random();
// shuffle players
players = players.OrderBy(_ => _rnd.Next()).ToList();
// create matches
var matches = players.Take(players.Count / 2).Zip(players.Skip(players.Count / 2), (p1, p2) => new Match(p1,p2));
https://dotnetfiddle.net/sGxbx4

Filter products with ElasticSearch concat a lot of filter

I've been trying to filter products with Elasticsearch for a few hours, unfortunately to no avail.
I need to find products that belong to certain categories and at the same time have selected several brands and one size.
Help :(
json screen
querycontainer build method
private QueryContainer CreateOrQueryFromFilter(QueryContainer queryContainer, SortedSet<string> filter, string fieldName)
{
if (filter != null && filter.Count > 0)
{
foreach (var item in filter)
{
queryContainer |= new TermQuery()
{
Name = fieldName + "named_query",
Boost = 1.1,
Field = fieldName,
Value = item
};
}
}
return queryContainer;
}
and search method
public ResultModel SearchRequest(RequestModel r)
{
string key = string.Format("search-{0}-{1}", r.CacheKey + "-" + ProductCatalog.Model.Extension.StringHelper.UrlFriendly(r.SearchText), r.Prefix);
node = new Uri("http://xxxx:9200/");
settings = new ConnectionSettings(node);
settings.DisableDirectStreaming();
settings.DefaultIndex("products");
client = new ElasticClient(settings);
// return AppCache.Get(key, () =>
// {
DateTime start = DateTime.Now;
ResultModel result = new ResultModel(r.Canonical, r.RouteObject);
if (!string.IsNullOrEmpty(r.Prefix))
{
result.Prefix = r.Prefix;
}
QueryContainer c = new QueryContainer();
if (r.CategoryFilterChilds != null && r.CategoryFilterChilds.Count > 0)
{
var a1 = new SortedSet<string>(r.CategoryFilterChilds.Select(a => (string)a.ToString()));
c = CreateOrQueryFromFilter(c, a1, "categories");
}
else
{
if (r.CategoryFilterRoots != null && r.CategoryFilterRoots.Count > 0)
{
var a1 = new SortedSet<string>(r.CategoryFilterRoots.Select(a => (string)a.ToString()));
c = CreateOrQueryFromFilter(c, a1, "categories");
}
else
{
// null
}
}
var filters = new AggregationDictionary();
if (r.IsBrandFilter)
{
c = CreateOrQueryFromFilter(c, r.SelectedBrands, "brands");
}
if (r.IsColorFilter)
{
c = CreateOrQueryFromFilter(c, r.SelectedBrands, "colors");
}
int skip = (r.Page * r.PageSize) - r.PageSize;
ISearchRequest r2 = new SearchRequest("products");
r2.From = 1;
r2.Size = r.PageSize;
r2.Query = c;
string[] Fields = new[] { "brands", "shopId" };
AggregationBase aggregations = null;
foreach (string sField in Fields)
{
var termsAggregation = new TermsAggregation("agg_" + sField)
{
Field = sField,
Size = 120,
Order = new List<TermsOrder> { TermsOrder.TermDescending }
};
if (aggregations == null)
{
aggregations = termsAggregation;
}
else
{
aggregations &= termsAggregation;
}
}
r2.Aggregations = aggregations;
var c2 = client.Search<ShopProductElastic>(r2);
var ShopsBuf = (Nest.BucketAggregate)(c2.Aggregations["agg_brands"]);
var ShopsCount = ShopsBuf.Items.Count();
var results = c2;
result.BrandsRequest = new SortedDictionary<string, int>();
foreach (Nest.KeyedBucket<object> item in ShopsBuf.Items)
{
result.BrandsRequest.Add((string)item.Key, (int)(item.DocCount ?? 0));
}
result.CategorySelected = r.CategoryCurrent;
result.TotalCount = 10;
var costam = results.Documents.ToList();
var targetInstance = Mapper.Map<List<Products>>(costam);
result.Products = targetInstance;
result.Page = r.Page;
result.PageSize = r.PageSize;
result.IsBrandFilter = r.IsBrandFilter;
result.IsColorFilter = r.IsColorFilter;
result.IsPatternFilter = r.IsPatternFilter;
result.IsSeasonFilter = r.IsSeasonFilter;
result.IsShopFilter = r.IsShopFilter;
result.IsSizeFilter = r.IsSizeFilter;
result.IsStyleFilter = r.IsStyleFilter;
result.IsTextileFilter = r.IsTextileFilter;
DateTime stop = DateTime.Now;
result.SearchTime = stop - start;
result.SearchText = r.SearchText;
return result;
// }, TimeSpan.FromHours(8));
}
I have all products that have a given brand or categories. However, i need all products of a selected brand in selected categories

How to train model with TensorflowSharp

I am new with TensorfolwSharp. I see some examples about how to load model and predict using TensorfolwSharp. But I cannot find examples to train model using TensorfolwSharp. I give it a try and stuck at Optimizer now. Too many parameters for ApplyAdam, not even sure this is the right function to use.
Following is my WORKING Tensorflow code.
dataX = pd.read_csv('dataX.csv', sep = ',', header = None)
dataX = pd.read_csv('dataY.csv', sep = ',', header = None)
x = tf.placeholder(tf.float32, [None, trainX.shape[1]])
y = tf.placeholder(tf.float32, [None, 1])
W0 = tf.Variable(tf.random_normal([trainX.shape[1], h0size], seed = seed))
b0 = tf.Variable(tf.random_normal([h0size], seed = seed))
h = tf.matmul(x, W0) + b0
pred = tf.sigmoid(h)
cost = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(labels = y, logits = h))
optimizer = tf.train.AdamOptimizer(learning_rate).minimize(cost)
with tf.Session() as sess:
sess.run(init)
for epoch in range(50):
_, c = sess.run([optimizer, cost], feed_dict ={x: dataX, y: dataX})
Following is my attemp to convert to TensorflowSharp
using (var session = new TFSession())
{
var graph = session.Graph;
//dataX = pd.read_csv('dataX.csv', sep = ',', header = None)
//dataY = pd.read_csv('dataY.csv', sep = ',', header = None)
float[,] aX = LoadCsv("dataX.csv");
float[,] aY = LoadCsv("dataY.csv");
TFTensor dataX = new TFTensor(aX);
TFTensor dataY = new TFTensor(aY);
//x = tf.placeholder(tf.float32, [None, trainX.shape[1]])
//y = tf.placeholder(tf.float32, [None, 1])
var x = graph.Placeholder(TFDataType.Float, new TFShape(dataX.Shape));
var y = graph.Placeholder(TFDataType.Float, new TFShape(dataY.Shape));
var W0 = graph.Variable(graph.RandomNormal(new TFShape(dataX.Shape[1], 1)));
var b0 = graph.Variable(graph.RandomNormal(new TFShape(1)));
var h = graph.Add(graph.MatMul(x, W0), b0);
var pred = graph.Sigmoid(h);
var cost = graph.ReduceMean(graph.SigmoidCrossEntropyWithLogits(y,h));
//optimizer = tf.train.AdamOptimizer(learning_rate).minimize(cost)
// Too many parameters for ApplyAdam, not even sure this is the right function to use.
TFOutput var, m = 0, v = 0, beta1_power, beta2_power, lr = 0.01, beta1 = 0.9, beta2 = 0.999, epsilon = 0.00000001, grad;
var optimizer = graph.ApplyAdam(var, m, v, beta1_power, beta2_power, lr, beta1, beta2, epsilon, grad);
for (int i = 0; i < 50 ; i++)
session.GetRunner().Run(
inputs: new[] { optimizer },
inputValues: new[] { dataX, dataY }
);
}
TensorFlow API doesn't provide optimizer classes yet. So to minimize cost function you should calculate gradients using API and then manually update trainable parameters of your model. Here is an example with separate classes for convinience:
class Model : IDisposable
{
TFSession _session;
TFGraph _graph;
TFOutput _input;
TFOutput _output;
LinearLayer _y_out;
TFOutput _cost;
TFTensor _dataX;
TFTensor _dataY;
GradientDescentOptimizer _gradientDescentOptimizer;
public Model()
{
float[,] aX = LoadCsv("dataX.csv");
float[,] aY = LoadCsv("dataY.csv");
_dataX = new TFTensor(aX);
_dataY = new TFTensor(aY);
_session = new TFSession();
_graph = _session.Graph;
_input = _graph.Placeholder(TFDataType.Float);
_output = _graph.Placeholder(TFDataType.Float);
_y_out = new LinearLayer(_graph, _input, (int)_dataX.Shape[0], 1);
cost = _graph.ReduceMean(_graph.SigmoidCrossEntropyWithLogits(_y_out.Result, _output));
_gradientDescentOptimizer = new GradientDescentOptimizer(_graph, _cost, _y_out.W, _y_out.b);
_gradientDescentOptimizer.ApplyGradientDescent(_graph);
var runner = _session.GetRunner();
runner.AddTarget(_y_out.InitB.Operation);
runner.Run();
}
public void TrainModelIteration()
{
var runner = _session.GetRunner();
runner.AddInput(_input, _dataX);
runner.AddInput(_output, _dataY);
for (int i = 0; i < 2; i++)
{
runner.Fetch(_gradientDescentOptimizer.Updates[i]);
}
runner.Run();
}
public void Dispose()
{
_graph.Dispose();
_session.Dispose();
}
}
class LinearLayer
{
public TFOutput Result { get; set; }
public TFOutput W { get; set; }
public TFOutput b { get; set; }
public TFOutput InitW { get; set; }
public TFOutput InitB { get; set; }
public LinearLayer(TFGraph graph, TFOutput x, int inSize, int outSize)
{
var wShape = new TFShape(inSize, outSize);
W = graph.VariableV2(wShape, TFDataType.Float);
TFOutput tfOutputWShape = graph.Const(wShape);
TFOutput initialW = graph.RandomUniform(tfOutputWShape, TFDataType.Float);
InitW = graph.Assign(W, initialW);
var bShape = new TFShape(outSize);
b = graph.VariableV2(bShape, TFDataType.Float);
TFOutput tfOutputBShape = graph.Const(bShape);
TFOutput initialB = graph.RandomUniform(tfOutputBShape, TFDataType.Float);
InitB = graph.Assign(b, initialB);
var matMul = graph.MatMul(x, W);
Result = graph.Add(matMul, b);
}
}
class GradientDescentOptimizer
{
private TFOutput[] _variables;
public TFOutput[] Updates { get; set; }
private TFOutput[] _gradients;
public GradientDescentOptimizer(TFGraph graph, TFOutput grad, TFOutput w, TFOutput b)
{
_variables = new TFOutput[4];
_variables[0] = w;
_variables[1] = b;
_gradients = graph.AddGradients(new TFOutput[] { grad }, new TFOutput[] { w, b });
Updates = new TFOutput[4];
}
public void ApplyGradientDescent(TFGraph graph, float alpha = 0.01f)
{
TFOutput tfAlpha = graph.Const(alpha);
for (int i = 0; i < 2; i++)
{
Updates[i] = graph.ApplyGradientDescent(_variables[i], tfAlpha, _gradients[i]);
}
}
}

Categories