def GetSolidAngle(a,b,c): a = rs.VectorUnitize(a) b = rs.VectorUnitize(b) c = rs.VectorUnitize(c) numer = rs.VectorDotProduct(rs.VectorCrossProduct(a,b),c) denom = 1 + rs.VectorDotProduct(a,b) + rs.VectorDotProduct(b,c) + rs.VectorDotProduct(c,a) angle = 2*math.atan2(numer, denom) return abs(angle)
def make_topology(self): # if self.scope is None: # print('Scope is not set for this extrusion') # raise SyntaxError base = self.base pts = rhgt.curve_points(base) self.representations['mesh'] = Mesh() # make top and bottom bottompl = Polyline(pts) bottom = Mesh.CreateFromClosedPolyline(bottompl) top = Mesh.CreateFromClosedPolyline(bottompl) top.Translate(0, 0, self.height) self.topo = Topology() self.topo.bot = bottom self.topo.top = top self.representations['mesh'].Append(top) self.representations['mesh'].Append(bottom) # make sides for i in range(len(pts) - 1): vect = pts[i + 1] - pts[i] n = Vector3d.CrossProduct(vect, Vector3d(0, 0, 1)) n = rs.VectorUnitize(n) ns_dot = rs.VectorDotProduct(n, self.vects[1]) ew_dot = rs.VectorDotProduct(n, self.vects[0]) threshold = 0.7 side = 'front' if ns_dot <= -threshold: side = 'front' elif ns_dot >= threshold: side = 'back' elif ew_dot < -threshold: side = 'left' else: side = 'right' # TODO:test how to determin direction from dot product # rs.AddTextDot(side,(pts[i]+pts[i+1])/2) # create face #print('self.height=', self.height) extr = Vector3d(0, 0, self.height) face = Mesh() face.Vertices.Add(pts[i]) face.Vertices.Add(pts[i + 1]) face.Vertices.Add(pts[i + 1] + extr) face.Vertices.Add(pts[i] + extr) face.Faces.AddFace(0, 1, 2, 3) # add to defined side self.topo[side].Append(face) self.representations['mesh'].Append(face)
def toldrop(self): vect1 = rs.VectorCreate(self.points[-2], self.points[-3]) vect2 = rs.VectorCreate(self.points[-1], self.points[-2]) norm = self.mpos.Mesh.NormalAt(self.mpos) alpha = g.Vector3d.VectorAngle(vect1, vect2) if alpha > self.antol and rs.VectorDotProduct( norm, g.Vector3d(0., 0., 1.) ) < 0: # if the angle between 2 moves larger than tolerance self.state = 'off' # the waterflow is off the facade alpha = g.Vector3d.VectorAngle(vect2, g.Vector3d(0., 0., -1.)) if alpha > (math.pi / 2 - self.androp) and rs.VectorDotProduct( norm, g.Vector3d(0., 0., 1.)) < 0: # if the geometry is too steep self.state = 'off' # the waterflow is off the facade
def IsPointInside(meshId, pt, tolerance = 1e-6): faceVerts = rs.MeshFaces(meshId, face_type=False) totalAngle = 0 i = 0 while i < len(faceVerts): ptA = faceVerts[i] ptB = faceVerts[i + 1] ptC = faceVerts[i + 2] a = rs.VectorSubtract(ptA, pt) b = rs.VectorSubtract(ptB, pt) c = rs.VectorSubtract(ptC, pt) angle = GetSolidAngle(a,b,c) normal = Normal(ptA, ptB, ptC) center = Centroid(ptA, ptB, ptC) faceVec = rs.VectorSubtract(pt, center) dot = rs.VectorDotProduct(normal, faceVec) factor = 1 if dot > 0 else -1 totalAngle += angle * factor i += 3 absTotal = abs(totalAngle) inside = abs(absTotal - (4*math.pi)) < tolerance print("The total solid angle is %.02fPI"%(absTotal/math.pi)) return inside
def depressCrvs(crvs, paths, startPt, radius, sd): newCrvs = [] for i in range(len(crvs)): divPts = rs.DivideCurve(crvs[i], 100) if i < len(crvs) - 1: cntPt01 = centerCrv(crvs[i]) cntPt02 = centerCrv(crvs[i + 1]) horVec = rs.VectorCreate(cntPt01, cntPt02) for j in range(len(divPts)): path = rs.PointClosestObject(divPts[j], paths)[0] param = rs.CurveClosestPoint(path, divPts[j]) close = rs.EvaluateCurve(path, param) dist = rs.Distance(close, divPts[j]) tan = rs.CurveTangent(crvs[i], param) vec = [0, 0, -1] #rs.VectorCrossProduct(horVec,tan) testVec = rs.VectorCreate(cntPt01, divPts[j]) if rs.VectorDotProduct(vec, testVec) < 0: rs.VectorReverse(vec) vec = rs.VectorUnitize(vec) border = 1 entry = 1 if j > len(divPts) / 2: border = rs.Distance(rs.CurveEndPoint(crvs[i]), divPts[j]) else: border = rs.Distance(rs.CurveStartPoint(crvs[i]), divPts[j]) if border < sd * 3: border = border / (sd * 3) entryDist = rs.Distance(startPt, divPts[j]) if entryDist < sd * 10: entry = entryDist / (sd * 10) if dist < sd * 2: val = radius * (bellCrv(dist, sd)) divPts[j] = rs.PointAdd(divPts[j], vec * val * border * entry) newCrvs.append(rs.AddCurve(divPts)) return divPts
def faces(): surfaces = rs.GetObjects("select surfaces", filter=rs.filter.surface) points = [ rs.EvaluateSurface(surface, *rs.SurfaceParameter(surface, (0.5, 0.5))) for surface in surfaces ] x = reduce(lambda s, point: s + point.X, points, 0) / len(points) y = reduce(lambda s, point: s + point.Y, points, 0) / len(points) z = reduce(lambda s, point: s + point.Z, points, 0) / len(points) # find the center of the object mass_center = rs.AddPoint(x, y, z) extrude_curves = {} # find the appropriate extrusion curve with the lowest dot product for surface in surfaces: surface_center = rs.EvaluateSurface( surface, *rs.SurfaceParameter(surface, (0.5, 0.5))) center_vector = rs.VectorCreate(surface_center, mass_center) normals = [] normals.append( rs.SurfaceNormal(surface, rs.SurfaceParameter(surface, (0.5, 0.5)))) normals.append(-rs.SurfaceNormal( surface, rs.SurfaceParameter(surface, (0.5, 0.5)))) if (rs.VectorDotProduct(normals[0], center_vector) < rs.VectorDotProduct(normals[1], center_vector)): extrude_curve = normals[0] else: extrude_curve = normals[1] extrude_curve = rs.VectorUnitize(extrude_curve) extrude_curve = rs.VectorScale(extrude_curve, 0.25) extrude_curve = [ surface_center, rs.VectorAdd(surface_center, extrude_curve) ] extrude_curve = rs.AddCurve(extrude_curve) rs.ExtrudeSurface(surface, extrude_curve) rs.DeleteObject(extrude_curve) rs.DeleteObject(surface) rs.DeleteObject(mass_center)
def drawHeightsGrid(pSource, gridPoints): for i in range(len(gridPoints)): for j in range(len(gridPoints[i])): start = gridPoints[i][j] v1 = rs.VectorUnitize(rs.VectorCreate(start, pSource)) theta = rs.VectorDotProduct(v1, [0, 0, 1]) end = [start[0], start[1], 20 * abs(theta)] rs.AddLine(start, end)
def anglesCheck(self): vect1 = rs.VectorCreate(self.points[-2], self.points[-3]) vect2 = rs.VectorCreate(self.points[-1], self.points[-2]) norm = self.mesh.NormalAt(self.mpos) alpha = g.Vector3d.VectorAngle(vect1, vect2) # check the tolerance angle if alpha > angleTol and rs.VectorDotProduct(norm, g.Vector3d( 0., 0., 1.)) < 0: # if the angle between 2 moves larger than tolerance self.state = 'off' # the waterflow is off the facade edgePoints.append(self.pos) # check the drop angle alpha = g.Vector3d.VectorAngle(vect2, g.Vector3d(0., 0., -1.)) if alpha > (math.pi / 2 - angleDrop) and rs.VectorDotProduct( norm, g.Vector3d(0., 0., 1.)) < 0: # if the geometry is too steep self.state = 'off' # the waterflow is off the facade
def drop(self): # drop angle check function move = rs.VectorCreate(self.points[-1], self.points[-2]) alpha = g.Vector3d.VectorAngle(move, g.Vector3d(0., 0., -1.)) norm = self.mesh.NormalAt(self.mpos) if alpha > (math.pi / 2 - self.androp) and rs.VectorDotProduct( norm, g.Vector3d(0., 0., 1.)) < 0: # if the geometry is too steep self.state = 'off' # the waterflow is off the facade
def Orthogonal(vecIn): vecIn = rs.VectorUnitize(vecIn) # Pick any vector which isn't aligned to the input otherVec = rs.coerce3dvector((1.0, 0.0, 0.0)) if abs(rs.VectorDotProduct(vecIn, otherVec)) > 0.99: otherVec = rs.coerce3dvector((0.0, 1.0, 0.0)) # Create a unit length orthogonal to both the other one, and the original one return rs.VectorUnitize(rs.VectorCrossProduct(vecIn, otherVec))
def tol(self): # tolerance angle check function vect1 = rs.VectorCreate(self.points[-2], self.points[-3]) vect2 = rs.VectorCreate(self.points[-1], self.points[-2]) norm = self.mesh.NormalAt(self.mpos) alpha = g.Vector3d.VectorAngle(vect1, vect2) if alpha > self.antol and rs.VectorDotProduct( norm, g.Vector3d(0., 0., 1.) ) < 0: # if the angle between 2 moves larger than tolerance self.state = 'off' # the waterflow is off the facade
def BasisFromDirection(direction): b2 = rs.VectorUnitize(direction) for b in range(3): b0 = UnitVector(b) # At least one unit vector must meet this condition inner = rs.VectorDotProduct(b0, b2) if -0.5 < inner <= 0.5: b0 = rs.VectorUnitize(b0 - b2 * inner) b1 = rs.VectorCrossProduct(b2, b0) return [b0, b1, b2] return UnitBasis()
def AddArcDir(ptStart, ptEnd, vecDir): vecBase = rs.PointSubtract(ptEnd, ptStart) if rs.VectorLength(vecBase)==0.0: return if rs.IsVectorParallelTo(vecBase, vecDir): return vecBase = rs.VectorUnitize(vecBase) vecDir = rs.VectorUnitize(vecDir) vecBisector = rs.VectorAdd(vecDir, vecBase) vecBisector = rs.VectorUnitize(vecBisector) dotProd = rs.VectorDotProduct(vecBisector, vecDir) midLength = (0.5*rs.Distance(ptStart, ptEnd))/dotProd vecBisector = rs.VectorScale(vecBisector, midLength) return rs.AddArc3Pt(ptStart, rs.PointAdd(ptStart, vecBisector), ptEnd)
def surfaceIrradiance_fixed(towerIn, sunIn, intensityIn): sunUnit = rs.VectorUnitize(sunIn) for floor in range(len(towerIn)): numPoints = len(towerIn[floor]) for i in range(numPoints): p1 = towerIn[floor][i] p2 = towerIn[floor][(i + 1) % numPoints] v1 = rs.VectorSubtract(p2, p1) v2 = [0, 0, 1] n = rs.VectorCrossProduct(v1, v2) if rs.VectorLength(n) > rs.UnitAbsoluteTolerance(10**(-3), True): cosTheta = rs.VectorDotProduct(rs.VectorUnitize(n), sunUnit) if cosTheta > 0: factor = intensityIn * cosTheta / 200 #200 is just to shorten the vector to something manageable v = rs.VectorScale(n, factor) AddVector(v, p1)
def addArc(startPt, endPt, vecDir): vecBase = rs.PointSubtract(endPt, startPt) if rs.VectorLength(vecBase) == 0.0: return if rs.IsVectorParallelTo(vecBase, vecDir): return vecBase = rs.VectorUnitize(vecBase) vecDir = rs.VectorUnitize(vecDir) vecBisector = rs.VectorAdd(vecDir, vecBase) vecBisector = rs.VectorUnitize(vecBisector) midlength = (0.5*rs.Distance(startPt, endPt)) / (rs.VectorDotProduct(vecBisector, vecDir)) vecBisector = rs.VectorScale(vecBisector, midlength) return rs.AddArc3Pt(startPt, endPt, rs.PointAdd(startPt, vecBisector))
def addArcDiv(ptStart, ptEnd, vecDir): vecBase = rs.PointSubtract(ptEnd, ptStart) # error handling if rs.VectorLength(vecBase) == 0.0: return if rs.IsVectorParallelTo(vecBase, vecDir): return vecBase = rs.VectorUnitize( vecBase ) # normalize vector == force magnitude to 1 to just compare direction vecDir = rs.VectorUnitize(vecDir) vecBisector = rs.VectorAdd(vecDir, vecBase) vecBisector = rs.VectorUnitize(vecBisector) dotProd = rs.VectorDotProduct(vecBisector, vecDir) midLength = (0.5 * rs.Distance(ptStart, ptEnd)) / dotProd vecBisector = rs.VectorScale(vecBisector, midLength) return rs.AddArc3Pt(ptStart, rs.PointAdd(pt.Start, vecBisector), ptEnd)
def anglesCheck(self): vect1 = rs.VectorUnitize(rs.VectorCreate(self.points[-2], self.points[-3])) vect2 = rs.VectorUnitize(rs.VectorCreate(self.points[-1], self.points[-2])) norm = self.mesh.NormalAt(self.mpos) # check the tolerance angle #alpha = g.Vector3d.VectorAngle(vect1, vect2) alpha = math.acos(min(1., rs.VectorDotProduct(vect1, vect2))) if alpha > angleTol and norm.Z < 0 : # if the angle between 2 moves larger than tolerance self.pop() self.state = 'off' # the waterflow is off the facade edgePoints.append(self.pos) # check the drop angle #alpha = g.Vector3d.VectorAngle(vect2, g.Vector3d(0., 0., -1.)) alpha = math.acos(-vect2.Z) if alpha > angleDrop and norm.Z < 0 : # if the geometry is too steep self.pop() self.state = 'off' # the waterflow is off the facade edgePoints.append(self.pos)
def appendEdgeDirection(self): """ Calculate the unit vector of offset directions for self.edges and append in list: self.offsetDirection. :rtype: None (result in self.offsetDirection) """ for edge in self.edges: # make vertical vector curveVector = rs.VectorCreate(rs.CurveStartPoint(edge), rs.CurveEndPoint(edge)) midPoint = rs.CurveMidPoint(edge) vec1 = rs.VectorRotate(curveVector, 90.0, [0, 0, 1]) vec2 = rs.VectorRotate(curveVector, -90.0, [0, 0, 1]) midToCenterVec = rs.VectorCreate(midPoint, self.center) offsetVec = "" if rs.VectorDotProduct(vec1, midToCenterVec) > 0: offsetVec = vec1 else: offsetVec = vec2 offsetVec = rs.VectorUnitize(offsetVec) # result self.offsetDirection.append(offsetVec)
def get_extreme_srf(brep, h_tol, top=True): """ algorithm: 1. pick n random pts on each surface, P 2. get the 3 lowest points in P (disabled for now; just does straight averaging) 3. determine their dot product with the unit z and their avg height 4. throw out all surfaces that aren't within the dot product threshold. 5. of the remaining surfaces, sort to get the lowest one. if any of them have a height within the height tolerance, select them as well. 6. return these lowest srfs. """ sample_num = 100 s_avg_normal, s_avg_height, s_srf = [[], [], []] dotprod_threshold = 0.9 for s in brep.Faces: u, v = [s.Domain(0), s.Domain(1)] test_params = [(rand.uniform(u.T0, u.T1), rand.uniform(v.T0, v.T1)) for i in xrange(sample_num)] test_points = [s.PointAt(p[0], p[1]) for p in test_params] #sort params and points by z test_points, test_params = zip(*sorted(zip(test_points, test_params), key=lambda x: x[0].Z, reverse=False)) test_Z = sum([t.Z for t in test_points]) / len(test_points) dotprods = [ rs.VectorDotProduct(s.NormalAt(p[0], p[1]), [0, 0, 1]) for p in test_params ] avg_dotprod = sum(dotprods) / len(dotprods) if top == False: avg_dotprod = -avg_dotprod #flip if searching for bottom. if (avg_dotprod) > dotprod_threshold: s_avg_normal.append(avg_dotprod) s_avg_height.append(test_Z) s_srf.append(s) # for i,p in enumerate(test_points): # docpt = rs.AddPoint(p) # if i<5: # rs.ObjectLayer(docpt,"Layer 05") #if top == True, search from the top... if top == False: s_avg_normal, s_avg_height, s_srf = zip( *sorted(zip(s_avg_normal, s_avg_height, s_srf), key=lambda x: x[1], reverse=False)) height_threshold = s_avg_height[0] + h_tol extreme_surfaces = [] for srf, height in zip(s_srf, s_avg_height): if height < height_threshold: extreme_surfaces.append(srf) else: s_avg_normal, s_avg_height, s_srf = zip( *sorted(zip(s_avg_normal, s_avg_height, s_srf), key=lambda x: x[1], reverse=True)) height_threshold = s_avg_height[0] - h_tol extreme_surfaces = [] for srf, height in zip(s_srf, s_avg_height): if height > height_threshold: extreme_surfaces.append(srf) return extreme_surfaces
#Function to draw a vector_A def AddVector(base, vec): rs.AddPoint(base) tip = rs.PointAdd(base, vec) line = rs.AddLine(base, tip) rs.CurveArrows(line, 2) #Base_point and direction of an original vector base_point = (20, 10, 5) vector_A = (10, 10, 10) AddVector(base_point, vector_A) #Create vector vector_B = rs.VectorCreate((25, 16, -2), base_point) AddVector(base_point, vector_B) #Vector add vector_C = rs.VectorAdd(vector_A, vector_B) AddVector(base_point, vector_C) #vector dot product s = rs.VectorDotProduct(vector_A, vector_B) print s #Vector cross product vector_D = rs.VectorCrossProduct(vector_A, vector_B) AddVector(base_point, vector_D) length_D = rs.VectorLength(vector_D) print length_D
vector3 = rs.VectorAdd(vector1, vector2) if unit == "Yes": vector3 = rs.VectorUnitize(vector3) * scale #copy the origin and move it along the new vector newPt = rs.CopyObject(originPt, vector3) #visualize the vector with a green line rs.ObjectColor(rs.AddLine(origin, newPt), (0, 255, 0)) #Subtraction of Two Vectors elif result == "Vector Subtraction": vector3 = rs.VectorSubtract(vector1, vector2) if unit == "Yes": vector3 = rs.VectorUnitize(vector3) * scale #copy the origin point and move along new vector newPt = rs.CopyObject(originPt, vector3) #visualize the vector with a green line rs.ObjectColor(rs.AddLine(origin, newPt), (0, 255, 0)) elif result == "Vector Dot Product": vector3 = rs.VectorDotProduct(vector1, vector2) #dot product is just a scalar value print it to screen for now print vector3 elif result == "Vector Cross Product": vector3 = rs.VectorCrossProduct(vector1, vector2) if unit == "Yes": vector3 = rs.VectorUnitize(vector3) * scale newPt = rs.CopyObject(originPt, vector3) rs.ObjectColor(rs.AddLine(origin, newPt), (0, 255, 0))
def reverse_if_needed(self, current, previous): dot_product = rs.VectorDotProduct(current, previous) if (dot_product < 0): return rs.VectorReverse(current) else: return current
def LineProjectedPoint(lineIn, pIn): pLine0 = lineIn[0] pLine1 = lineIn[1] u = rs.VectorUnitize(rs.VectorSubtract(pLine1, pLine0)) projectedScale = rs.VectorDotProduct(rs.VectorSubtract(pIn, pLine0), u) return rs.VectorAdd(pLine0, rs.VectorScale(u, projectedScale))
def get_distance(self, x, y, z): dp = rs.VectorDotProduct(self.nrm, rg.Vector3d(x, y, z)) return -(dp + self.d)
def Update(self, t): self.mesh = self.meshOrig.Duplicate() for i, v in enumerate(self.mesh.Vertices): val = self.pn.noise2(util.Remap(v.X, 10, 90, 0, 3), util.Remap(v.Y, 0, 50, 0, 3)) vec = self.meshOrig.Normals[i] vec = rg.Vector3d(vec) vec *= val * 8 xform = rg.Transform.Translation(vec) v.Transform(xform) self.mesh.Vertices[i] = v for i, v in enumerate(self.mesh.Vertices): val = self.pn.noise3(util.Remap(v.X, 10, 90, 0, 1), util.Remap(v.Y, 0, 50, 0, 1), util.Remap(t, 0, 150, 0, 4)) vec = self.meshOrig.Normals[i] vec = rg.Vector3d(vec) vec *= val * 20 xform = rg.Transform.Translation(vec) v.Transform(xform) self.mesh.Vertices[i] = v if self.meshID: sc.doc.Objects.Delete(self.meshID, True) self.meshID = sc.doc.Objects.AddMesh(self.mesh) if True: tempMesh = rg.Mesh() for j in range(0, len(self.mesh.Faces) - 1): vertices = [] faceIndex = j face = self.mesh.Faces[faceIndex] for i in list(face): vertices.append(rg.Point3d(self.mesh.Vertices[i])) r, plane = rg.Plane.FitPlaneToPoints(vertices) if r == rg.PlaneFitResult.Success: center = geo.CentroidOfPoints(vertices) plane.Origin = center d = rs.VectorDotProduct(plane.Normal, self.mesh.FaceNormals[faceIndex]) if d < 0: plane.Flip() projVec = ProjectVectorToPlane(rg.Vector3d(0, -1, 0), plane) a = rg.Vector3d.VectorAngle(plane.XAxis, projVec, plane.Normal) plane.Rotate(a, plane.Normal) xform = rg.Transform.PlaneToPlane(rg.Plane.WorldXY, plane) newHead = self.head.Duplicate() xformPlane = rg.Plane(rg.Point3d(.5, .5, 0), rg.Vector3d(0, 0, 1)) s = 8 scaleForm = rg.Transform.Scale(xformPlane, s, s, s) newHead.Transform(scaleForm) newHead.Transform(xform) tempMesh.Append(newHead) #x = sc.doc.Objects.AddMesh(newHead) if self.headsID: sc.doc.Objects.Delete(self.headsID, True) self.headsID = sc.doc.Objects.AddMesh(tempMesh)
def VectorAngleCosine(v1, v2): return rs.VectorDotProduct(rs.VectorUnitize(v1), rs.VectorUnitize(v2))